Compare commits

..

37 Commits

Author SHA1 Message Date
3801a97722 feat: add nlohmann/json lib (#1552)
* feat: add nlohmann/json lib

* remove build test off
2024-04-24 21:35:45 -05:00
jadebenn
0367c67c85 chore: move the pet minigame table loading logic out of petcomponent (#1551)
* move the pet minigame table loading logic out of petcomponent

* misc fixes

* actually, using paths is dumb here when they're already char strings. why bother? silly me.

* removed unga bunga reference-casting

* add back in puzzle not found error message

* pre-allocate unordered map and make getter const-correct

* Update dDatabase/CDClientDatabase/CDClientTables/CDTamingBuildPuzzleTable.cpp

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>

---------

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2024-04-24 10:09:15 -05:00
jadebenn
8fdc212cda chore: Convert heap allocation to optional (#1553)
* chore: Convert heap allocation to optional

* Update dGame/dComponents/PetComponent.h

Default-initialize
2024-04-24 10:09:04 -05:00
99e7349f6c feat: slashcommands for showall, findplayer, get/openhttpmoninfo, and debug world packet (#1545)
* feat: showall, findplayer, get/openhttpmoninfo

http monitor info is planned to be used later, just putting in info that i've since reverse engineered and don't want lost

Additionally add debug world packet for duture dev use

Tested all new commands and variation of command arguments

* fix missing newline at eofs

* address most feedback

* Compormise and use struct with (de)serialize

* remove httpmoninfo commands
2024-04-17 21:47:28 -05:00
jadebenn
fafe2aefad chore: Nitpicking-utils (#1549)
* nit

* GeneralUtils const-correctness and minor fixes

* use copy instead of reference for char iteration loops

* fix typo and reorganize some functions
2024-04-14 23:14:54 -07:00
David Markowitz
5049f215ba chore: Use string to access SQLite columns (#1535)
* use string to access field name

* Update DEVGMCommands.cpp

* corrected column name

* constexpr array

include <array>

Revert "constexpr array"

This reverts commit 1492e8b1773ed5fbbe767c74466ca263178ecdd4.

Revert "include <array>"

This reverts commit 2b7a67e89ad673d420f496be97f9bc51fd2d5e59.

include <array>

constexpr array

---------

Co-authored-by: jadebenn <jonahbenn@yahoo.com>
2024-04-13 23:41:51 -05:00
David Markowitz
3a6123fe36 fix console sound (#1547) 2024-04-11 10:29:49 -05:00
David Markowitz
b8b2b687e2 inherit exception for CppSQLite3Exception (#1544)
catch any exception just in case exception isnt inherited from
2024-04-10 07:32:54 -05:00
d067a8d12f chore: split out slash commands into multiple files (#1539)
* chore: split out slash commands into multiple files
Breakup the monolithic file
don't register slashcommands on startup

* fix typo
2024-04-09 20:15:51 -05:00
David Markowitz
1ee45639af Update GeneralUtils.h (#1541) 2024-04-09 00:20:25 -05:00
jadebenn
db192d2cde chore: Fix use of uninitialized variable in RemoveItemFromInventory (#1540) 2024-04-08 21:50:41 -07:00
David Markowitz
28ce8ac54d remove usage of xmldoc as a ptr (#1538)
resolves a memory leak in BrickDatabase, adds stability to character save doc.

Tested that saving manually via force-save, logout and /crash all saved my position and my removed banana as expected.
The doc was always deleted on character destruction and on any updates, so this is just a semantic change (and now we no longer have new'd tinyxml2::documents on the heap)
2024-04-08 15:13:49 -05:00
David Markowitz
be0a2f6f14 fix jittering (#1537) 2024-04-08 15:13:31 -05:00
David Markowitz
3260a063cb ignore whitespace in try parse (#1536) 2024-04-08 15:13:19 -05:00
feeac2e041 feat: refactor slash commands system into more scalable system (#1510)
* WIP, but working

* Scaffolding

* testing and making it compile again

* move all commands to functions

* renaming to compile

* fix failing tests

idk how these werent failing before.  Seems to have been magic.

* move commandss into their namespace
make help command useful
fix mac error

TODO: remove the multiple not founds/ rework the structure to split into help and handling

* Just need to fill out the fields, but it's all there templated

* Add all aliases, register missing commands

* All help text

* remove test logs

* improvements

pass through added code for optimizations and cleanup as well as reduce the amount of scoping for readability and maintainability

* Update SlashCommandHandler.cpp

* only save command if it is a GM command

* simplify if checks

* remove broken delimiter

* Update SlashCommandHandler.cpp

* Update SlashCommandHandler.cpp

---------

Co-authored-by: David Markowitz <EmosewaMC@gmail.com>
2024-04-08 15:11:59 -05:00
jadebenn
18c27b14c8 disable non conforming volatile behavior on MSVC (#1534) 2024-04-05 12:56:23 -05:00
jadebenn
bcfaa6c7fe const return oversight (#1532) 2024-04-05 01:14:52 -07:00
jadebenn
06e7d57e0d chore: Remove dpEntity pointers from collision checking (#1529)
* chore: Remove dpEntity pointers from collision checking

* Update fn documentation in ProximityMonitorComponent.h

* use more idiomatic method to calculate vector index

* feedback

* missed a ranges::find replacement

* adjust for feedback. last changes tonight.

* okay, also remove unneeded include. then sleep.

* for real tho

* update to use unordered_set instead of set
2024-04-05 00:52:26 -05:00
David Markowitz
b340d7c8f9 replace white and blacklist (#1530) 2024-04-05 00:51:40 -05:00
David Markowitz
24de0e5fdb Update GeneralUtils.cpp (#1528)
same check as the header
2024-04-03 19:06:29 -05:00
20408d8dfe chore: remove chat_internal and processes everything over chat connection (#1508)
* WIP

* get rid of redundent case and some formatting issues

* move some things around for cleaner diffs

* remove dead code that does nothing and add connection check

* fix whitespace

* address feedback
2024-03-31 22:27:50 -05:00
David Markowitz
c1c5db6593 update4 fp check (#1524) 2024-03-31 21:46:51 -05:00
David Markowitz
884a41f36a update to current knowledge (#1523)
Should be 100% live accurate as far as logic and bitstream reads goes.

Tested with all valiant weapons and crux prime weapons (drops from dragons) that combat does not desync and that the client reports the same level and amount of skill deserialize issues as before.
2024-03-30 11:16:06 -05:00
David Markowitz
bbc0908989 Update 9_Update_Leaderboard_Storage.sql (#1520) 2024-03-30 08:18:03 -05:00
David Markowitz
5996f3cbf4 fix stewblaster stopping for non-players (#1521)
fixes an issue when stew blaster would stop for non-players and would stand still permanently due to enemy hitboxes being removed.  Tested that stewblaster only stops for players and starts moving when there are no players in the vicinity
2024-03-30 08:17:56 -05:00
jadebenn
150031861d Update README.md (#1518) 2024-03-28 21:32:46 -05:00
jadebenn
9d8e0a9c4a unbreak the stacktraces (#1516) 2024-03-27 06:10:39 +01:00
David Markowitz
bd9b790e1d feat: Add MovingAI pathing for NPCs without combatAI (#1509)
* remove goto

* Update MovementAIComponent.cpp

* convert to PathWaypoint

Easier for usage with paths

* add path parsing

* ref removal, simplification of work

* it works

* Update MovementAIComponent.cpp

* disable pathing for combat

we just need it for npcs for now, combat ai can be done later

* fixed stuttery enemies

wow

* start at ramped up speed

* add pausing and resuming

* Update MovementAIComponent.cpp

* Update MovementAIComponent.h

* Update CMakeLists.txt
2024-03-26 21:06:22 -05:00
David Markowitz
39b81b6263 rename and shorted BehaviorTemplate enum (#1512)
just a renaming of the enum and the value names and deletion of the empty cpp file.  Code compiles still.
2024-03-26 06:35:35 -05:00
David Markowitz
1e09ec92e3 Update PlayerContainer.cpp (#1513)
Prevents a bad actor from possibly spamming the server with sequential IDs and allocating a bunch of memory.

Tested that I can still send and receive friend requests
2024-03-26 06:20:45 -05:00
David Markowitz
2b253a8248 fix: movement ai remove goto, do todo, remove unused call (#1505)
* remove goto

* Update MovementAIComponent.cpp
2024-03-24 22:24:38 -05:00
David Markowitz
3262bc3a86 chore: Remove news in Behavior members (#1504)
* Remove news in behavior members

Tested that GrowingFlowers still have their SkillEvent fired with the correct parameters, gftikitorch works, sharks eating stinky fish still work

* explicitly default move assignment and copy operators/constructors

---------

Co-authored-by: jadebenn <jadebenn@users.noreply.github.com>
2024-03-24 21:43:01 -05:00
David Markowitz
3a4e554da9 update switch behavior (#1503)
was using very old code from pre-foss that has not been updated with the new behavior knowledge.  The code has been updated accordingly to what the client expects.

Tested that ice shurikens can now destroy the legs of the skeleton towers in crux prime.  Tested that the following weapons can still do damage to enemies and objects in the world:
surikens of ice
serratorizer
Super Morning Star
Super Dagger
elite long barrel blaster (charge and normal)
Mosaic Wand
2024-03-24 14:01:12 -05:00
jadebenn
35ce8771e5 chore: supress warnings on external library headers and actually get rid of the last old-style casts (#1502)
* chore: supress warnings on external library headers and actually get rid of the last old-style casts

* remove commented out section I forgot

* update cmake required version to 3.25 unless we can find another way to do this

* update readme

* Update CMakeLists.txt
2024-03-17 20:48:09 -05:00
David Markowitz
b9092a3cce update serialization, remove unused variable (#1501)
Tested that players show up as normal on each others screens, tested that money magnet still works with item 8600, tested that gravity still works in Moon Base.
2024-03-10 01:15:43 -06:00
David Markowitz
0b4f70a76b Update StoryBoxInteractServer.cpp (#1500)
Update StoryBoxInteractServer.cpp
2024-03-08 19:29:40 -06:00
David Markowitz
4bc4624bc9 feat: add further MovementAI skeleton (#1499)
* add movement ai skeleton

Zone loading code is tested to load and read the correct values using logs.  other ldf data is unaffected as I walked around crux and dragons/apes can still spawn and be killed.

* format
2024-03-08 19:29:01 -06:00
209 changed files with 5841 additions and 4350 deletions

3
.gitmodules vendored
View File

@@ -17,6 +17,3 @@
[submodule "thirdparty/magic_enum"]
path = thirdparty/magic_enum
url = https://github.com/Neargye/magic_enum.git
[submodule "thirdparty/fmt"]
path = thirdparty/fmt
url = https://github.com/fmtlib/fmt.git

View File

@@ -1,11 +1,12 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.25)
project(Darkflame)
include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file
@@ -72,7 +73,8 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
elseif(MSVC)
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
add_compile_options("/wd4267" "/utf-8")
# Also disable non-portable MSVC volatile behavior
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
@@ -94,6 +96,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
find_package(MariaDB)
find_package(JSON)
# Create a /resServer directory
make_directory(${CMAKE_BINARY_DIR}/resServer)
@@ -102,7 +105,7 @@ make_directory(${CMAKE_BINARY_DIR}/resServer)
make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy resource files on first build
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blocklist.dcf")
message(STATUS "Checking resource file integrity")
include(Utils)
@@ -213,29 +216,29 @@ if (APPLE)
endif()
# Load all of our third party directories
add_subdirectory(thirdparty)
add_subdirectory(thirdparty SYSTEM)
# Create our list of include directories
set(INCLUDED_DIRECTORIES
include_directories(
"dPhysics"
"dNavigation"
"dNet"
"thirdparty/magic_enum/include/magic_enum"
"thirdparty/raknet/Source"
"thirdparty/tinyxml2"
"thirdparty/recastnavigation"
"thirdparty/SQLite"
"thirdparty/cpplinq"
"thirdparty/cpp-httplib"
"thirdparty/MD5"
"tests"
"tests/dCommonTests"
"tests/dGameTests"
"tests/dGameTests/dComponentsTests"
SYSTEM "thirdparty/magic_enum/include/magic_enum"
SYSTEM "thirdparty/raknet/Source"
SYSTEM "thirdparty/tinyxml2"
SYSTEM "thirdparty/recastnavigation"
SYSTEM "thirdparty/SQLite"
SYSTEM "thirdparty/cpplinq"
SYSTEM "thirdparty/cpp-httplib"
SYSTEM "thirdparty/MD5"
)
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
@@ -244,14 +247,9 @@ if(APPLE)
include_directories("/usr/local/include/")
endif()
# Actually include the directories from our list
foreach(dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
# Add linking directories:
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
endif()
file(
GLOB HEADERS_DZONEMANAGER
@@ -287,7 +285,7 @@ add_subdirectory(dPhysics)
add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "fmt" "raknet" "MariaDB::ConnCpp" "magic_enum")
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "MariaDB::ConnCpp" "magic_enum" "nlohmann_json::nlohmann_json")
# Add platform specific common libraries
if(UNIX)

View File

@@ -51,7 +51,7 @@ git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
### Windows packages
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</font> or later!).
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.25**</font> or later!).
### MacOS packages
Ensure you have [brew](https://brew.sh) installed.
@@ -73,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
```
#### Required CMake version
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed.
This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
You can check your CMake version by using the following command in a terminal.
```bash
cmake --version

20
cmake/FindJSON.cmake Normal file
View File

@@ -0,0 +1,20 @@
include(FetchContent)
message(STATUS "Fetching json...")
FetchContent_Declare(
json
GIT_REPOSITORY https://github.com/nlohmann/json
GIT_TAG v3.11.3
)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
FetchContent_MakeAvailable(json)
message(STATUS "json fetched and is now ready.")
set(JSON_FOUND TRUE)

View File

@@ -141,6 +141,6 @@ elseif(APPLE)
endif()
# Add directories to include lists
target_include_directories(MariaDB::ConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
target_include_directories(MariaDB::ConnCpp SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
set(MariaDB_FOUND TRUE)

View File

@@ -54,14 +54,14 @@ int main(int argc, char** argv) {
Server::SetupLogger("AuthServer");
if (!Game::logger) return EXIT_FAILURE;
Log::Info("Starting Auth server...");
Log::Info("Version: {:s}", PROJECT_VERSION);
Log::Info("Compiled on: {:s}", __TIMESTAMP__);
LOG("Starting Auth server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
Database::Connect();
} catch (sql::SQLException& ex) {
Log::Info("Got an error while connecting to the database: {:s}", ex.what());
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("AuthServer");
delete Game::server;
delete Game::logger;
@@ -77,7 +77,7 @@ int main(int argc, char** argv) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
Log::Info("Master is at {:s}:{:d}", masterIP, masterPort);
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
Game::randomEngine = std::mt19937(time(0));
@@ -110,7 +110,7 @@ int main(int argc, char** argv) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= authFramerate) {
Log::Info("No connection to master!");
LOG("No connection to master!");
break; //Exit our loop, shut down.
}
} else framesSinceMasterDisconnect = 0;
@@ -151,7 +151,7 @@ int main(int argc, char** argv) {
std::this_thread::sleep_until(t);
}
Log::Info("Exited Main Loop! (signal {:d})", Game::lastSignal);
LOG("Exited Main Loop! (signal %d)", Game::lastSignal);
//Delete our objects here:
Database::Destroy("AuthServer");
delete Game::server;

View File

@@ -1,6 +1,6 @@
add_executable(AuthServer "AuthServer.cpp")
target_link_libraries(AuthServer PRIVATE ${COMMON_LIBRARIES} dServer)
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)

View File

@@ -27,8 +27,8 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
ExportWordlistToDCF(filepath + ".dcf", true);
}
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
ReadWordlistDCF("blacklist.dcf", false);
if (BinaryIO::DoesFileExist("blocklist.dcf")) {
ReadWordlistDCF("blocklist.dcf", false);
}
//Read player names that are ok as well:
@@ -44,20 +44,20 @@ dChatFilter::~dChatFilter() {
m_DeniedWords.clear();
}
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool allowList) {
std::ifstream file(filepath);
if (file) {
std::string line;
while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
if (allowList) m_ApprovedWords.push_back(CalculateHash(line));
else m_DeniedWords.push_back(CalculateHash(line));
}
}
}
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
std::ifstream file(filepath, std::ios::binary);
if (file) {
fileHeader hdr;
@@ -70,13 +70,13 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead);
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
if (allowList) m_ApprovedWords.reserve(wordsToRead);
else m_DeniedWords.reserve(wordsToRead);
size_t word = 0;
for (size_t i = 0; i < wordsToRead; ++i) {
BinaryIO::BinaryRead(file, word);
if (whiteList) m_ApprovedWords.push_back(word);
if (allowList) m_ApprovedWords.push_back(word);
else m_DeniedWords.push_back(word);
}
@@ -90,14 +90,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
return false;
}
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowList) {
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
BinaryIO::BinaryWrite(file, size_t(allowList ? m_ApprovedWords.size() : m_DeniedWords.size()));
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
for (size_t word : allowList ? m_ApprovedWords : m_DeniedWords) {
BinaryIO::BinaryWrite(file, word);
}
@@ -105,10 +105,10 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteLis
}
}
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList) {
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
if (message.empty()) return { };
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
if (!allowList && m_DeniedWords.empty()) return { { 0, message.length() } };
std::stringstream sMessage(message);
std::string segment;
@@ -126,16 +126,16 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
size_t hash = CalculateHash(segment);
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && allowList) {
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && allowList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !allowList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}

View File

@@ -21,10 +21,10 @@ public:
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
~dChatFilter();
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList = true);
void ReadWordlistPlaintext(const std::string& filepath, bool allowList);
bool ReadWordlistDCF(const std::string& filepath, bool allowList);
void ExportWordlistToDCF(const std::string& filepath, bool allowList);
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList = true);
private:
bool m_DontGenerateDCF;

View File

@@ -11,6 +11,6 @@ add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}
add_library(dChatServer ${DCHATSERVER_SOURCES})
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer")
target_link_libraries(dChatServer PRIVATE ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer PRIVATE ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)

View File

@@ -1,6 +1,6 @@
#include "ChatIgnoreList.h"
#include "PlayerContainer.h"
#include "eChatInternalMessageType.h"
#include "eChatMessageType.h"
#include "BitStreamUtils.h"
#include "Game.h"
#include "Logger.h"
@@ -13,7 +13,7 @@
// The only thing not auto-handled is instance activities force joining the team on the server.
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receivingPlayer);
//portion that will get routed:
@@ -27,16 +27,16 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
Log::Info("Tried to get ignore list, but player {:d} not found in container", playerId);
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
if (!receiver.ignoredPlayers.empty()) {
Log::Debug("Player {:d} already has an ignore list, but is requesting it again.", playerId);
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
} else {
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
if (ignoreList.empty()) {
Log::Debug("Player {:d} has no ignores", playerId);
LOG_DEBUG("Player %llu has no ignores", playerId);
return;
}
@@ -69,13 +69,13 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
Log::Info("Tried to get ignore list, but player {:d} not found in container", playerId);
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
constexpr int32_t MAX_IGNORES = 32;
if (receiver.ignoredPlayers.size() > MAX_IGNORES) {
Log::Debug("Player {:d} has too many ignores", playerId);
LOG_DEBUG("Player %llu has too many ignores", playerId);
return;
}
@@ -91,11 +91,11 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
// Check if the player exists
LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY;
if (toIgnoreStr == receiver.playerName || toIgnoreStr.find("[GM]") == 0) {
Log::Debug("Player {:d} tried to ignore themselves", playerId);
LOG_DEBUG("Player %llu tried to ignore themselves", playerId);
bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR);
} else if (std::count(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), toIgnoreStr) > 0) {
Log::Debug("Player {:d} is already ignoring {:s}", playerId, toIgnoreStr);
LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED);
} else {
@@ -105,7 +105,7 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
// Fall back to query
auto player = Database::Get()->GetCharacterInfo(toIgnoreStr);
if (!player || player->name != toIgnoreStr) {
Log::Debug("Player {:s} not found", toIgnoreStr);
LOG_DEBUG("Player %s not found", toIgnoreStr.c_str());
} else {
ignoredPlayerId = player->id;
}
@@ -119,7 +119,7 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
Log::Debug("Player {:d} is ignoring {:s}", playerId, toIgnoreStr);
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
} else {
@@ -141,7 +141,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
Log::Info("Tried to get ignore list, but player {:d} not found in container", playerId);
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return;
}
@@ -153,7 +153,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
auto toRemove = std::remove(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), removedIgnoreStr);
if (toRemove == receiver.ignoredPlayers.end()) {
Log::Debug("Player {:d} is not ignoring {:s}", playerId, removedIgnoreStr);
LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
return;
}

View File

@@ -14,11 +14,11 @@
#include "eObjectBits.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eClientMessageType.h"
#include "eGameMessageType.h"
#include "StringifiedEnum.h"
#include "eGameMasterLevel.h"
#include "ChatPackets.h"
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Get from the packet which player we want to do something with:
@@ -60,7 +60,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Now, we need to send the friendlist to the server they came from:
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(playerID);
//portion that will get routed:
@@ -93,7 +93,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
auto& requestor = Game::playerContainer.GetPlayerDataMutable(requestorPlayerID);
if (!requestor) {
Log::Info("No requestor player {:d} sent to {:s} found.", requestorPlayerID, playerName);
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
return;
}
@@ -355,6 +355,67 @@ void ChatPacketHandler::HandleGMLevelUpdate(Packet* packet) {
inStream.Read(player.gmLevel);
}
void ChatPacketHandler::HandleWho(Packet* packet) {
CINSTREAM_SKIP_HEADER;
FindPlayerRequest request;
request.Deserialize(inStream);
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
if (!sender) return;
const auto& player = Game::playerContainer.GetPlayerData(request.playerName.GetAsString());
bool online = player;
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(request.requestor);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::WHO_RESPONSE);
bitStream.Write<uint8_t>(online);
bitStream.Write(player.zoneID.GetMapID());
bitStream.Write(player.zoneID.GetInstanceID());
bitStream.Write(player.zoneID.GetCloneID());
bitStream.Write(request.playerName);
SystemAddress sysAddr = sender.sysAddr;
SEND_PACKET;
}
void ChatPacketHandler::HandleShowAll(Packet* packet) {
CINSTREAM_SKIP_HEADER;
ShowAllRequest request;
request.Deserialize(inStream);
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
if (!sender) return;
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(request.requestor);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SHOW_ALL_RESPONSE);
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
bitStream.Write(Game::playerContainer.GetPlayerCount());
bitStream.Write(Game::playerContainer.GetSimCount());
bitStream.Write<uint8_t>(request.displayIndividualPlayers);
bitStream.Write<uint8_t>(request.displayZoneData);
if (request.displayZoneData || request.displayIndividualPlayers){
for (auto& [playerID, playerData ]: Game::playerContainer.GetAllPlayers()){
if (!playerData) continue;
bitStream.Write<uint8_t>(0); // structure packing
if (request.displayIndividualPlayers) bitStream.Write(LUWString(playerData.playerName));
if (request.displayZoneData) {
bitStream.Write(playerData.zoneID.GetMapID());
bitStream.Write(playerData.zoneID.GetInstanceID());
bitStream.Write(playerData.zoneID.GetCloneID());
}
}
}
SystemAddress sysAddr = sender.sysAddr;
SEND_PACKET;
}
// the structure the client uses to send this packet is shared in many chat messages
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
@@ -376,7 +437,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
LUWString message(size);
inStream.Read(message);
Log::Info("Got a message from ({:s}) via [{:s}]: {:s}", sender.playerName, StringifiedEnum::ToString(channel), message.GetAsString());
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
switch (channel) {
case eChatChannel::TEAM: {
@@ -391,7 +452,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
break;
}
default:
Log::Info("Unhandled Chat channel [{:s}]", StringifiedEnum::ToString(channel));
LOG("Unhandled Chat channel [%s]", StringifiedEnum::ToString(channel).data());
break;
}
}
@@ -412,7 +473,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
inStream.IgnoreBytes(4);
inStream.Read(channel);
if (channel != eChatChannel::PRIVATE_CHAT) Log::Info("WARNING: Received Private chat with the wrong channel!");
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
inStream.Read(size);
inStream.IgnoreBytes(77);
@@ -424,7 +485,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
LUWString message(size);
inStream.Read(message);
Log::Info("Got a message from ({:s}) via [{:s}]: {:s} to {:s}", sender.playerName, StringifiedEnum::ToString(channel), message.GetAsString(), receiverName);
LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str());
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
if (!receiver) {
@@ -454,7 +515,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(routeTo.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
@@ -506,13 +567,13 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
if (team->memberIDs.size() > 3) {
// no more teams greater than 4
Log::Info("Someone tried to invite a 5th player to a team");
LOG("Someone tried to invite a 5th player to a team");
return;
}
SendTeamInvite(other, player);
Log::Info("Got team invite: {:d} -> {:s}", playerID, invitedPlayer.GetAsString());
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.GetAsString().c_str());
}
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
@@ -526,7 +587,7 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
LWOOBJID leaderID = LWOOBJID_EMPTY;
inStream.Read(leaderID);
Log::Info("Accepted invite: {:d} -> {:d} ({:d})", playerID, leaderID, declined);
LOG("Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
if (declined) {
return;
@@ -535,13 +596,13 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
auto* team = Game::playerContainer.GetTeam(leaderID);
if (team == nullptr) {
Log::Info("Failed to find team for leader ({:d})", leaderID);
LOG("Failed to find team for leader (%llu)", leaderID);
team = Game::playerContainer.GetTeam(playerID);
}
if (team == nullptr) {
Log::Info("Failed to find team for player ({:d})", playerID);
LOG("Failed to find team for player (%llu)", playerID);
return;
}
@@ -557,7 +618,7 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
auto* team = Game::playerContainer.GetTeam(playerID);
Log::Info("({:d}) leaving team", playerID);
LOG("(%llu) leaving team", playerID);
if (team != nullptr) {
Game::playerContainer.RemoveMember(team, playerID, false, false, true);
@@ -575,7 +636,7 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
inStream.Read(kickedPlayer);
Log::Info("({:d}) kicking ({:s}) from team", playerID, kickedPlayer.GetAsString());
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.GetAsString().c_str());
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer.GetAsString());
@@ -608,7 +669,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
inStream.IgnoreBytes(4);
inStream.Read(promotedPlayer);
Log::Info("({:d}) promoting ({:s}) to team leader", playerID, promotedPlayer.GetAsString());
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.GetAsString().c_str());
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer.GetAsString());
@@ -696,7 +757,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -711,7 +772,7 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -738,7 +799,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool b
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -763,7 +824,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -780,7 +841,7 @@ void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -809,7 +870,7 @@ void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFr
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -835,7 +896,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -869,7 +930,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
[bool] - is FTP*/
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(friendData.playerID);
//portion that will get routed:
@@ -906,7 +967,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
}
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -920,7 +981,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
// Portion that will get routed:
@@ -943,7 +1004,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID);
//portion that will get routed:

View File

@@ -50,6 +50,8 @@ namespace ChatPacketHandler {
void HandleFriendResponse(Packet* packet);
void HandleRemoveFriend(Packet* packet);
void HandleGMLevelUpdate(Packet* packet);
void HandleWho(Packet* packet);
void HandleShowAll(Packet* packet);
void HandleChatMessage(Packet* packet);
void HandlePrivateChatMessage(Packet* packet);

View File

@@ -17,7 +17,6 @@
#include "PlayerContainer.h"
#include "ChatPacketHandler.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "ChatIgnoreList.h"
#include "StringifiedEnum.h"
@@ -60,9 +59,9 @@ int main(int argc, char** argv) {
//Read our config:
Log::Info("Starting Chat server...");
Log::Info("Version: {:s}", PROJECT_VERSION);
Log::Info("Compiled on: {:s}", __TIMESTAMP__);
LOG("Starting Chat server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
std::string clientPathStr = Game::config->GetValue("client_location");
@@ -74,7 +73,7 @@ int main(int argc, char** argv) {
Game::assetManager = new AssetManager(clientPath);
} catch (std::runtime_error& ex) {
Log::Info("Got an error while setting up assets: {:s}", ex.what());
LOG("Got an error while setting up assets: %s", ex.what());
return EXIT_FAILURE;
}
@@ -83,7 +82,7 @@ int main(int argc, char** argv) {
try {
Database::Connect();
} catch (sql::SQLException& ex) {
Log::Info("Got an error while connecting to the database: {:s}", ex.what());
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("ChatServer");
delete Game::server;
delete Game::logger;
@@ -181,48 +180,30 @@ int main(int argc, char** argv) {
void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
Log::Info("A server has disconnected, erasing their connected players from the list.");
}
LOG("A server has disconnected, erasing their connected players from the list.");
} else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
LOG("A server is connecting, awaiting user list.");
} else if (packet->length < 4 || packet->data[0] != ID_USER_PACKET_ENUM) return; // Nothing left to process or not the right packet type
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Log::Info("A server is connecting, awaiting user list.");
}
CINSTREAM;
inStream.SetReadOffset(BYTES_TO_BITS(1));
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
eConnectionType connection;
eChatMessageType chatMessageID;
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
Game::playerContainer.InsertPlayer(packet);
break;
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
Game::playerContainer.RemovePlayer(packet);
break;
case eChatInternalMessageType::MUTE_UPDATE:
inStream.Read(connection);
if (connection != eConnectionType::CHAT) return;
inStream.Read(chatMessageID);
switch (chatMessageID) {
case eChatMessageType::GM_MUTE:
Game::playerContainer.MuteUpdate(packet);
break;
case eChatInternalMessageType::CREATE_TEAM:
case eChatMessageType::CREATE_TEAM:
Game::playerContainer.CreateTeamServer(packet);
break;
case eChatInternalMessageType::ANNOUNCEMENT: {
//we just forward this packet to every connected server
CINSTREAM;
Game::server->Send(inStream, packet->systemAddress, true); //send to everyone except origin
break;
}
default:
Log::Info("Unknown CHAT_INTERNAL id: {:d}", static_cast<int>(packet->data[3]));
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
switch (chat_message_type) {
case eChatMessageType::GET_FRIENDS_LIST:
ChatPacketHandler::HandleFriendlistRequest(packet);
break;
@@ -296,6 +277,23 @@ void HandlePacket(Packet* packet) {
ChatPacketHandler::HandleGMLevelUpdate(packet);
break;
case eChatMessageType::LOGIN_SESSION_NOTIFY:
Game::playerContainer.InsertPlayer(packet);
break;
case eChatMessageType::GM_ANNOUNCE:{
// we just forward this packet to every connected server
inStream.ResetReadPointer();
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
}
break;
case eChatMessageType::UNEXPECTED_DISCONNECT:
Game::playerContainer.RemovePlayer(packet);
break;
case eChatMessageType::WHO:
ChatPacketHandler::HandleWho(packet);
break;
case eChatMessageType::SHOW_ALL:
ChatPacketHandler::HandleShowAll(packet);
break;
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
@@ -308,7 +306,6 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::GUILD_KICK:
case eChatMessageType::GUILD_GET_STATUS:
case eChatMessageType::GUILD_GET_ALL:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::BLUEPRINT_MODERATED:
case eChatMessageType::BLUEPRINT_MODEL_READY:
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
@@ -323,7 +320,6 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::CSR_REQUEST:
case eChatMessageType::CSR_REPLY:
case eChatMessageType::GM_KICK:
case eChatMessageType::GM_ANNOUNCE:
case eChatMessageType::WORLD_ROUTE_PACKET:
case eChatMessageType::GET_ZONE_POPULATIONS:
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
@@ -332,33 +328,18 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
case eChatMessageType::UGCC_REQUEST:
case eChatMessageType::WHO:
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
case eChatMessageType::ACHIEVEMENT_NOTIFY:
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
case eChatMessageType::UNEXPECTED_DISCONNECT:
case eChatMessageType::PLAYER_READY:
case eChatMessageType::GET_DONATION_TOTAL:
case eChatMessageType::UPDATE_DONATION:
case eChatMessageType::PRG_CSR_COMMAND:
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
Log::Info("Unhandled CHAT Message id: {:s} {:d}", StringifiedEnum::ToString(chat_message_type), GeneralUtils::ToUnderlying(chat_message_type));
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
break;
default:
Log::Info("Unknown CHAT Message id: {:d}", GeneralUtils::ToUnderlying(chat_message_type));
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
switch (static_cast<eWorldMessageType>(packet->data[3])) {
case eWorldMessageType::ROUTE_PACKET: {
Log::Info("Routing packet from world");
break;
}
default:
Log::Info("Unknown World id: {:d}", static_cast<int>(packet->data[3]));
}
LOG("Unknown CHAT Message id: %i", chatMessageID);
}
}

View File

@@ -9,9 +9,9 @@
#include "BitStreamUtils.h"
#include "Database.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "ChatPackets.h"
#include "dConfig.h"
#include "eChatMessageType.h"
void PlayerContainer::Initialize() {
m_MaxNumberOfBestFriends =
@@ -28,7 +28,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
if (!inStream.Read(playerId)) {
Log::Warn("Failed to read player ID");
LOG("Failed to read player ID");
return;
}
@@ -49,8 +49,9 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
data.sysAddr = packet->systemAddress;
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
m_PlayerCount++;
Log::Info("Added user: {:s} ({:d}), zone: {:d}", data.playerName, data.playerID, data.zoneID.GetMapID());
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID());
}
@@ -64,7 +65,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
const auto& player = GetPlayerData(playerID);
if (!player) {
Log::Info("Failed to find user: {:d}", playerID);
LOG("Failed to find user: %llu", playerID);
return;
}
@@ -87,7 +88,8 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
}
}
Log::Info("Removed user: {:d}", playerID);
m_PlayerCount--;
LOG("Removed user: %llu", playerID);
m_Players.erase(playerID);
Database::Get()->UpdateActivityLog(playerID, eActivityType::PlayerLoggedOut, player.zoneID.GetMapID());
@@ -103,7 +105,7 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
auto& player = this->GetPlayerDataMutable(playerID);
if (!player) {
Log::Warn("Failed to find user: {:d}", playerID);
LOG("Failed to find user: %llu", playerID);
return;
}
@@ -145,7 +147,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_MUTE);
bitStream.Write(player);
bitStream.Write(time);
@@ -207,7 +209,7 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
if (team->memberIDs.size() >= 4) {
Log::Warn("Tried to add player to team that already had 4 players");
LOG("Tried to add player to team that already had 4 players");
const auto& player = GetPlayerData(playerID);
if (!player) return;
ChatPackets::SendSystemMessage(player.sysAddr, u"The teams is full! You have not been added to a team!");
@@ -352,7 +354,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::TEAM_GET_STATUS);
bitStream.Write(team->teamID);
bitStream.Write(deleteTeam);
@@ -390,7 +392,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
return m_Players[playerID];
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {

View File

@@ -71,6 +71,9 @@ public:
const PlayerData& GetPlayerData(const std::string& playerName);
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
PlayerData& GetPlayerDataMutable(const std::string& playerName);
uint32_t GetPlayerCount() { return m_PlayerCount; };
uint32_t GetSimCount() { return m_SimCount; };
const std::map<LWOOBJID, PlayerData>& GetAllPlayers() { return m_Players; };
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
@@ -93,5 +96,7 @@ private:
std::unordered_map<LWOOBJID, std::u16string> m_Names;
uint32_t m_MaxNumberOfBestFriends = 5;
uint32_t m_MaxNumberOfFriends = 50;
uint32_t m_PlayerCount = 0;
uint32_t m_SimCount = 0;
};

View File

@@ -29,7 +29,7 @@ void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
break;
}
default: {
Log::Warn("Encountered unwritable AMFType {:d}!", GeneralUtils::ToUnderlying(type));
LOG("Encountered unwritable AMFType %i!", type);
}
case eAmf::Undefined:
case eAmf::Null:

View File

@@ -54,14 +54,14 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
completeUncompressedModel.append(reinterpret_cast<char*>(uncompressedChunk.get()));
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
} else {
Log::Warn("Failed to inflate chunk {} for model %llu. Error: {}", chunkCount, model.id, err);
LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
break;
}
chunkCount++;
}
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
if (!document) {
Log::Warn("Failed to initialize tinyxml document. Aborting.");
LOG("Failed to initialize tinyxml document. Aborting.");
return 0;
}
@@ -70,13 +70,13 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
"</LXFML>",
completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos
) {
Log::Info("Brick-by-brick model {} will be deleted!", model.id);
LOG("Brick-by-brick model %llu will be deleted!", model.id);
Database::Get()->DeleteUgcModelData(model.id);
modelsTruncated++;
}
}
} else {
Log::Info("Brick-by-brick model {} will be deleted!", model.id);
LOG("Brick-by-brick model %llu will be deleted!", model.id);
Database::Get()->DeleteUgcModelData(model.id);
modelsTruncated++;
}
@@ -121,11 +121,11 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
try {
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
Log::Info("Updated model {} to sd0", model.id);
LOG("Updated model %i to sd0", model.id);
updatedModels++;
} catch (sql::SQLException exception) {
Log::Warn("Failed to update model {}. This model should be inspected manually to see why."
"The database error is {}", model.id, exception.what());
LOG("Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", model.id, exception.what());
}
}
}

View File

@@ -70,6 +70,5 @@ else ()
endif ()
target_link_libraries(dCommon
PUBLIC fmt
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
INTERFACE dDatabase)

View File

@@ -28,7 +28,7 @@ void make_minidump(EXCEPTION_POINTERS* e) {
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
}
Log::Info("Creating crash dump {:s}", name);
LOG("Creating crash dump %s", name);
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return;
@@ -83,7 +83,7 @@ struct bt_ctx {
static inline void Bt(struct backtrace_state* state) {
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
Log::Info("backtrace is enabled, crash dump located at {:s}", fileName);
LOG("backtrace is enabled, crash dump located at %s", fileName.c_str());
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
backtrace_print(state, 2, file);
@@ -95,13 +95,13 @@ static inline void Bt(struct backtrace_state* state) {
static void ErrorCallback(void* data, const char* msg, int errnum) {
auto* ctx = (struct bt_ctx*)data;
fmt::print(stderr, "ERROR: {:s} ({:d})", msg, errnum);
fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
ctx->error = 1;
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
FILE* file = fopen(fileName.c_str(), "w+");
if (file != nullptr) {
fmt::print(file, "ERROR: {:s} ({:d})", msg, errnum);
fprintf(file, "ERROR: %s (%d)", msg, errnum);
fclose(file);
}
}
@@ -119,13 +119,15 @@ void CatchUnhandled(int sig) {
try {
if (eptr) std::rethrow_exception(eptr);
} catch(const std::exception& e) {
Log::Warn("Caught exception: '{:s}'", e.what());
LOG("Caught exception: '%s'", e.what());
} catch (...) {
LOG("Caught unknown exception.");
}
#ifndef INCLUDE_BACKTRACE
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
Log::Warn("Encountered signal {:d}, creating crash dump {:s}", sig, fileName);
LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
if (Diagnostics::GetProduceMemoryDump()) {
GenerateDump();
}
@@ -143,7 +145,7 @@ void CatchUnhandled(int sig) {
FILE* file = fopen(fileName.c_str(), "w+");
if (file != NULL) {
fmt::println(file, "Error: signal {:d}:", sig);
fprintf(file, "Error: signal %d:\n", sig);
}
// Print the stack trace
for (size_t i = 0; i < size; i++) {
@@ -165,9 +167,9 @@ void CatchUnhandled(int sig) {
}
}
Log::Info("[{:02d}] {:s}", i, functionName);
LOG("[%02zu] %s", i, functionName.c_str());
if (file != NULL) {
fmt::println(file, "[{:02d}] {:s}", i, functionName);
fprintf(file, "[%02zu] %s\n", i, functionName.c_str());
}
}
# else // defined(__GNUG__)
@@ -208,7 +210,7 @@ void MakeBacktrace() {
sigaction(SIGFPE, &sigact, nullptr) != 0 ||
sigaction(SIGABRT, &sigact, nullptr) != 0 ||
sigaction(SIGILL, &sigact, nullptr) != 0) {
fmt::println(stderr, "error setting signal handler for {:d} ({:s})",
fprintf(stderr, "error setting signal handler for %d (%s)\n",
SIGSEGV,
strsignal(SIGSEGV));

View File

@@ -42,7 +42,7 @@ bool FdbToSqlite::Convert::ConvertDatabase(AssetStream& buffer) {
CDClientDatabase::ExecuteQuery("COMMIT;");
} catch (CppSQLite3Exception& e) {
Log::Warn("Encountered error {:s} converting FDB to SQLite", e.errorMessage());
LOG("Encountered error %s converting FDB to SQLite", e.errorMessage());
return false;
}

View File

@@ -8,23 +8,23 @@
#include <map>
template <typename T>
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
if (size == size_t(-1) || size > string.size()) {
static inline size_t MinSize(const size_t size, const std::basic_string_view<T> string) {
if (size == SIZE_MAX || size > string.size()) {
return string.size();
} else {
return size;
}
}
inline bool IsLeadSurrogate(char16_t c) {
inline bool IsLeadSurrogate(const char16_t c) {
return (0xD800 <= c) && (c <= 0xDBFF);
}
inline bool IsTrailSurrogate(char16_t c) {
inline bool IsTrailSurrogate(const char16_t c) {
return (0xDC00 <= c) && (c <= 0xDFFF);
}
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
inline void PushUTF8CodePoint(std::string& ret, const char32_t cp) {
if (cp <= 0x007F) {
ret.push_back(static_cast<uint8_t>(cp));
} else if (cp <= 0x07FF) {
@@ -46,16 +46,16 @@ inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
bool _IsSuffixChar(uint8_t c) {
bool static _IsSuffixChar(const uint8_t c) {
return (c & 0xC0) == 0x80;
}
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
size_t rem = slice.length();
bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
const size_t rem = slice.length();
if (slice.empty()) return false;
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
if (rem > 0) {
uint8_t first = bytes[0];
const uint8_t first = bytes[0];
if (first < 0x80) { // 1 byte character
out = static_cast<uint32_t>(first & 0x7F);
slice.remove_prefix(1);
@@ -64,7 +64,7 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
// middle byte, not valid at start, fall through
} else if (first < 0xE0) { // two byte character
if (rem > 1) {
uint8_t second = bytes[1];
const uint8_t second = bytes[1];
if (_IsSuffixChar(second)) {
out = (static_cast<uint32_t>(first & 0x1F) << 6)
+ static_cast<uint32_t>(second & 0x3F);
@@ -74,8 +74,8 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
}
} else if (first < 0xF0) { // three byte character
if (rem > 2) {
uint8_t second = bytes[1];
uint8_t third = bytes[2];
const uint8_t second = bytes[1];
const uint8_t third = bytes[2];
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
out = (static_cast<uint32_t>(first & 0x0F) << 12)
+ (static_cast<uint32_t>(second & 0x3F) << 6)
@@ -86,9 +86,9 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
}
} else if (first < 0xF8) { // four byte character
if (rem > 3) {
uint8_t second = bytes[1];
uint8_t third = bytes[2];
uint8_t fourth = bytes[3];
const uint8_t second = bytes[1];
const uint8_t third = bytes[2];
const uint8_t fourth = bytes[3];
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
out = (static_cast<uint32_t>(first & 0x07) << 18)
+ (static_cast<uint32_t>(second & 0x3F) << 12)
@@ -107,7 +107,7 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
}
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t size) {
if (output.length() >= size) return false;
if (U < 0x10000) {
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
@@ -120,7 +120,7 @@ bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
// U' must be less than or equal to 0xFFFFF. That is, U' can be
// represented in 20 bits.
uint32_t Ut = U - 0x10000;
const uint32_t Ut = U - 0x10000;
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
// 0xDC00, respectively. These integers each have 10 bits free to
@@ -141,25 +141,25 @@ bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
} else return false;
}
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view string, const size_t size) {
const size_t newSize = MinSize(size, string);
std::u16string output;
output.reserve(newSize);
std::string_view iterator = string;
uint32_t c;
while (_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
while (details::_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
return output;
}
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view string, const size_t size) {
const size_t newSize = MinSize(size, string);
std::u16string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) {
char c = string[i];
for (size_t i = 0; i < newSize; ++i) {
const char c = string[i];
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
}
@@ -169,18 +169,18 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view string, const size_t size) {
const size_t newSize = MinSize(size, string);
std::string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; i++) {
char16_t u = string[i];
for (size_t i = 0; i < newSize; ++i) {
const char16_t u = string[i];
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
char16_t next = string[i + 1];
const char16_t next = string[i + 1];
if (IsTrailSurrogate(next)) {
i += 1;
char32_t cp = 0x10000
const char32_t cp = 0x10000
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
+ (static_cast<char32_t>(next) - 0xDC00);
PushUTF8CodePoint(ret, cp);
@@ -195,40 +195,40 @@ std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t
return ret;
}
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& b) {
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b) {
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
}
// MARK: Bits
//! Sets a specific bit in a signed 64-bit integer
int64_t GeneralUtils::SetBit(int64_t value, uint32_t index) {
int64_t GeneralUtils::SetBit(int64_t value, const uint32_t index) {
return value |= 1ULL << index;
}
//! Clears a specific bit in a signed 64-bit integer
int64_t GeneralUtils::ClearBit(int64_t value, uint32_t index) {
int64_t GeneralUtils::ClearBit(int64_t value, const uint32_t index) {
return value &= ~(1ULL << index);
}
//! Checks a specific bit in a signed 64-bit integer
bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
bool GeneralUtils::CheckBit(int64_t value, const uint32_t index) {
return value & (1ULL << index);
}
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
bool GeneralUtils::ReplaceInString(std::string& str, const std::string_view from, const std::string_view to) {
const size_t start_pos = str.find(from);
if (start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
std::vector<std::wstring> GeneralUtils::SplitString(const std::wstring_view str, const wchar_t delimiter) {
std::vector<std::wstring> vector = std::vector<std::wstring>();
std::wstring current;
for (const auto& c : str) {
for (const wchar_t c : str) {
if (c == delimiter) {
vector.push_back(current);
current = L"";
@@ -237,15 +237,15 @@ std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t d
}
}
vector.push_back(current);
vector.push_back(std::move(current));
return vector;
}
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str, char16_t delimiter) {
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view str, const char16_t delimiter) {
std::vector<std::u16string> vector = std::vector<std::u16string>();
std::u16string current;
for (const auto& c : str) {
for (const char16_t c : str) {
if (c == delimiter) {
vector.push_back(current);
current = u"";
@@ -254,17 +254,15 @@ std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str,
}
}
vector.push_back(current);
vector.push_back(std::move(current));
return vector;
}
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, const char delimiter) {
std::vector<std::string> vector = std::vector<std::string>();
std::string current = "";
for (size_t i = 0; i < str.length(); i++) {
char c = str[i];
for (const char c : str) {
if (c == delimiter) {
vector.push_back(current);
current = "";
@@ -273,8 +271,7 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char
}
}
vector.push_back(current);
vector.push_back(std::move(current));
return vector;
}
@@ -283,7 +280,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
inStream.Read<uint32_t>(length);
std::u16string string;
for (auto i = 0; i < length; i++) {
for (uint32_t i = 0; i < length; ++i) {
uint16_t c;
inStream.Read(c);
string.push_back(c);
@@ -292,35 +289,35 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
return string;
}
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string_view folder) {
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
std::map<uint32_t, std::string> filenames{};
for (auto& t : std::filesystem::directory_iterator(folder)) {
auto filename = t.path().filename().string();
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
filenames.insert(std::make_pair(index, filename));
std::map<uint32_t, std::string> filenames{};
for (const auto& t : std::filesystem::directory_iterator(folder)) {
auto filename = t.path().filename().string();
const auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
filenames.emplace(index, std::move(filename));
}
// Now sort the map by the oldest migration.
std::vector<std::string> sortedFiles{};
auto fileIterator = filenames.begin();
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
auto fileIterator = filenames.cbegin();
auto oldest = filenames.cbegin();
while (!filenames.empty()) {
if (fileIterator == filenames.end()) {
if (fileIterator == filenames.cend()) {
sortedFiles.push_back(oldest->second);
filenames.erase(oldest);
fileIterator = filenames.begin();
oldest = filenames.begin();
fileIterator = filenames.cbegin();
oldest = filenames.cbegin();
continue;
}
if (oldest->first > fileIterator->first) oldest = fileIterator;
fileIterator++;
++fileIterator;
}
return sortedFiles;
}
#ifdef DARKFLAME_PLATFORM_MACOS
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
// MacOS floating-point parse function specializations
namespace GeneralUtils::details {

View File

@@ -3,17 +3,18 @@
// C++
#include <charconv>
#include <cstdint>
#include <random>
#include <ctime>
#include <functional>
#include <optional>
#include <random>
#include <span>
#include <stdexcept>
#include <string>
#include <string_view>
#include <optional>
#include <functional>
#include <type_traits>
#include <stdexcept>
#include "BitStream.h"
#include "NiPoint3.h"
#include "dPlatforms.h"
#include "Game.h"
#include "Logger.h"
@@ -32,29 +33,31 @@ namespace GeneralUtils {
//! Converts a plain ASCII string to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
std::u16string ASCIIToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
//! Converts a UTF-8 String to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
std::u16string UTF8ToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
namespace details {
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
}
//! Converts a UTF-16 string to a UTF-8 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
std::string UTF16ToWTF8(const std::u16string_view string, const size_t size = SIZE_MAX);
/**
* Compares two basic strings but does so ignoring case sensitivity
@@ -62,7 +65,7 @@ namespace GeneralUtils {
* \param b the second string to compare against the first string
* @return if the two strings are equal
*/
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
bool CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b);
// MARK: Bits
@@ -70,9 +73,9 @@ namespace GeneralUtils {
//! Sets a bit on a numerical value
template <typename T>
inline void SetBit(T& value, eObjectBits bits) {
inline void SetBit(T& value, const eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
const auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8) - 1) {
return;
}
@@ -82,9 +85,9 @@ namespace GeneralUtils {
//! Clears a bit on a numerical value
template <typename T>
inline void ClearBit(T& value, eObjectBits bits) {
inline void ClearBit(T& value, const eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
const auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8 - 1)) {
return;
}
@@ -97,14 +100,14 @@ namespace GeneralUtils {
\param value The value to set the bit for
\param index The index of the bit
*/
int64_t SetBit(int64_t value, uint32_t index);
int64_t SetBit(int64_t value, const uint32_t index);
//! Clears a specific bit in a signed 64-bit integer
/*!
\param value The value to clear the bit from
\param index The index of the bit
*/
int64_t ClearBit(int64_t value, uint32_t index);
int64_t ClearBit(int64_t value, const uint32_t index);
//! Checks a specific bit in a signed 64-bit integer
/*!
@@ -112,19 +115,19 @@ namespace GeneralUtils {
\param index The index of the bit
\return Whether or not the bit is set
*/
bool CheckBit(int64_t value, uint32_t index);
bool CheckBit(int64_t value, const uint32_t index);
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
bool ReplaceInString(std::string& str, const std::string_view from, const std::string_view to);
std::u16string ReadWString(RakNet::BitStream& inStream);
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
std::vector<std::wstring> SplitString(const std::wstring_view str, const wchar_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string_view str, const char16_t delimiter);
std::vector<std::string> SplitString(const std::string& str, char delimiter);
std::vector<std::string> SplitString(const std::string_view str, const char delimiter);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
// Concept constraining to enum types
template <typename T>
@@ -144,7 +147,7 @@ namespace GeneralUtils {
// If a boolean, present an alias to an intermediate integral type for parsing
template <Numeric T> requires std::same_as<T, bool>
struct numeric_parse<T> { using type = uint32_t; };
struct numeric_parse<T> { using type = uint8_t; };
// Shorthand type alias
template <Numeric T>
@@ -156,8 +159,9 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
[[nodiscard]] std::optional<T> TryParse(std::string_view str) {
numeric_parse_t<T> result;
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
const char* const strEnd = str.data() + str.size();
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
@@ -166,7 +170,7 @@ namespace GeneralUtils {
return isParsed ? static_cast<T>(result) : std::optional<T>{};
}
#ifdef DARKFLAME_PLATFORM_MACOS
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
// MacOS floating-point parse helper function specializations
namespace details {
@@ -181,8 +185,10 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
[[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
try {
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
size_t parseNum;
const T result = details::_parse<T>(str, parseNum);
const bool isParsed = str.length() == parseNum;
@@ -202,7 +208,7 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
const auto x = TryParse<float>(strX);
if (!x) return std::nullopt;
@@ -214,17 +220,17 @@ namespace GeneralUtils {
}
/**
* The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
* @param str The string vector representing the X, Y, and Xcoordinates
* The TryParse overload for handling NiPoint3 by passing a span of three strings
* @param str The string vector representing the X, Y, and Z coordinates
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
}
template <typename T>
std::u16string to_u16string(T value) {
std::u16string to_u16string(const T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
@@ -243,7 +249,7 @@ namespace GeneralUtils {
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
inline T GenerateRandomNumber(const std::size_t min, const std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
@@ -270,10 +276,10 @@ namespace GeneralUtils {
// on Windows we need to undef these or else they conflict with our numeric limits calls
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
#ifdef _WIN32
#undef min
#undef max
#endif
#ifdef _WIN32
#undef min
#undef max
#endif
template <typename T>
inline T GenerateRandomNumber() {

View File

@@ -48,7 +48,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
try {
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
} catch (std::exception) {
Log::Warn("Attempted to process invalid ldf type ({:s}) from string ({:s})", ldfTypeAndValue.first, format);
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
return nullptr;
}
@@ -63,7 +63,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
case LDF_TYPE_S32: {
const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
if (!data) {
Log::Warn("Attempted to process invalid int32 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<int32_t>(key, data.value());
@@ -74,7 +74,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
case LDF_TYPE_FLOAT: {
const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
if (!data) {
Log::Warn("Attempted to process invalid float value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<float>(key, data.value());
@@ -84,7 +84,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
case LDF_TYPE_DOUBLE: {
const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
if (!data) {
Log::Warn("Attempted to process invalid double value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<double>(key, data.value());
@@ -102,7 +102,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else {
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
if (!dataOptional) {
Log::Warn("Attempted to process invalid uint32 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
data = dataOptional.value();
@@ -122,7 +122,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else {
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
if (!dataOptional) {
Log::Warn("Attempted to process invalid bool value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
data = dataOptional.value();
@@ -135,7 +135,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
case LDF_TYPE_U64: {
const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
if (!data) {
Log::Warn("Attempted to process invalid uint64 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<uint64_t>(key, data.value());
@@ -145,7 +145,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
case LDF_TYPE_OBJID: {
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
if (!data) {
Log::Warn("Attempted to process invalid LWOOBJID value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr;
}
returnValue = new LDFData<LWOOBJID>(key, data.value());
@@ -159,12 +159,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
}
case LDF_TYPE_UNKNOWN: {
Log::Warn("Attempted to process invalid unknown value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
break;
}
default: {
Log::Warn("Attempted to process invalid LDF type ({:d}) from string ({:s})", GeneralUtils::ToUnderlying(type), format);
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
break;
}
}

View File

@@ -29,7 +29,7 @@ void Writer::Flush() {
FileWriter::FileWriter(const char* outpath) {
m_Outfile = fopen(outpath, "wt");
if (!m_Outfile) fmt::println("Couldn't open {:s} for writing!", outpath);
if (!m_Outfile) printf("Couldn't open %s for writing!\n", outpath);
m_Outpath = outpath;
m_IsConsoleWriter = false;
}

View File

@@ -1,14 +1,6 @@
#pragma once
// fmt includes:
#include <fmt/core.h>
#include <fmt/format.h>
#include <fmt/chrono.h>
// C++ includes:
#include <chrono>
#include <memory>
#include <source_location>
#include <string>
#include <vector>
@@ -23,88 +15,22 @@
// Calculate the filename at compile time from the path.
// We just do this by scanning the path for the last '/' or '\' character and returning the string after it.
constexpr const char* GetFileNameFromAbsolutePath(const char* path) {
const char* file = path;
while (*path) {
const char nextChar = *path++;
if (nextChar == '/' || nextChar == '\\') {
file = path;
}
}
return file;
}
/**
* Location wrapper class
* Used to implicitly forward source location information without adding a function parameter
*/
template <typename T>
class location_wrapper {
public:
// Constructor
template <typename U = T>
consteval location_wrapper(const U& val, const std::source_location& loc = std::source_location::current())
: m_File(GetFileNameFromAbsolutePath(loc.file_name()))
, m_Loc(loc)
, m_Obj(val) {
}
// Methods
[[nodiscard]] constexpr const char* file() const noexcept { return m_File; }
[[nodiscard]] constexpr const std::source_location& loc() const noexcept { return m_Loc; }
[[nodiscard]] constexpr const T& get() const noexcept { return m_Obj; }
protected:
const char* m_File{};
std::source_location m_Loc{};
T m_Obj{};
};
/**
* Logging functions (EXPERIMENTAL)
*/
namespace Log {
template <typename... Ts>
[[nodiscard]] inline tm Time() { // TODO: Move?
return fmt::localtime(std::time(nullptr));
}
template <typename... Ts>
using FormatString = location_wrapper<fmt::format_string<Ts...>>;
template <typename... Ts>
inline void Info(const FormatString<Ts...> fmt_str, Ts&&... args) {
fmt::print("[{:%d-%m-%y %H:%M:%S} {}:{}] ", Time(), fmt_str.file(), fmt_str.loc().line());
fmt::println(fmt_str.get(), std::forward<Ts>(args)...);
}
template <typename... Ts>
inline void Warn(const FormatString<Ts...> fmt_str, Ts&&... args) {
fmt::print("[{:%d-%m-%y %H:%M:%S} {}:{}] Warning: ", Time(), fmt_str.file(), fmt_str.loc().line());
fmt::println(fmt_str.get(), std::forward<Ts>(args)...);
}
template <typename... Ts>
inline void Debug(const FormatString<Ts...> fmt_str, Ts&&... args) {
// if (!m_logDebugStatements) return;
Log::Info(fmt_str, std::forward<Ts>(args)...);
}
const char* file = path;
while (*path) {
char nextChar = *path++;
if (nextChar == '/' || nextChar == '\\') {
file = path;
}
}
return file;
}
// These have to have a constexpr variable to store the filename_and_line result in a local variable otherwise
// they will not be valid constexpr and will be evaluated at runtime instead of compile time!
// The full string is still stored in the binary, however the offset of the filename in the absolute paths
// is used in the instruction instead of the start of the absolute path.
//#define LOG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->Log(str, message, ##__VA_ARGS__); } while(0)
//#define LOG(message, ...) do {\
const auto now = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now());\
fmt::println("[{:%d-%m-%y %H:%M:%S} {:s}] " message, now, FILENAME_AND_LINE, ##__VA_ARGS__);\
} while(0)
#define LOG(message, ...) Log::Info(message __VA_OPT__(,) __VA_ARGS__)
//#define LOG_DEBUG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->LogDebug(str, message, ##__VA_ARGS__); } while(0)
#define LOG_DEBUG(message, ...) Log::Debug(message __VA_OPT__(,) __VA_ARGS__)
#define LOG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->Log(str, message, ##__VA_ARGS__); } while(0)
#define LOG_DEBUG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->LogDebug(str, message, ##__VA_ARGS__); } while(0)
// Writer class for writing data to files.
class Writer {

View File

@@ -23,7 +23,7 @@ PackIndex::PackIndex(const std::filesystem::path& filePath) {
m_PackFileIndices.push_back(packFileIndex);
}
Log::Info("Loaded pack catalog with {:d} pack files and {:d} files", m_PackPaths.size(), m_PackFileIndices.size());
LOG("Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
for (auto& item : m_PackPaths) {
std::replace(item.begin(), item.end(), '\\', '/');

View File

@@ -6,10 +6,10 @@
namespace StringifiedEnum {
template<typename T>
constexpr std::string_view ToString(const T e) {
const std::string_view ToString(const T e) {
static_assert(std::is_enum_v<T>, "Not an enum"); // Check type
constexpr const auto& sv = magic_enum::enum_entries<T>();
constexpr auto& sv = magic_enum::enum_entries<T>();
const auto it = std::lower_bound(
sv.begin(), sv.end(), e,

View File

@@ -1,31 +0,0 @@
#ifndef __ECHATINTERNALMESSAGETYPE__H__
#define __ECHATINTERNALMESSAGETYPE__H__
#include <cstdint>
enum eChatInternalMessageType : uint32_t {
PLAYER_ADDED_NOTIFICATION = 0,
PLAYER_REMOVED_NOTIFICATION,
ADD_FRIEND,
ADD_BEST_FRIEND,
ADD_TO_TEAM,
ADD_BLOCK,
REMOVE_FRIEND,
REMOVE_BLOCK,
REMOVE_FROM_TEAM,
DELETE_TEAM,
REPORT,
PRIVATE_CHAT,
PRIVATE_CHAT_RESPONSE,
ANNOUNCEMENT,
MAIL_COUNT_UPDATE,
MAIL_SEND_NOTIFY,
REQUEST_USER_LIST,
FRIEND_LIST,
ROUTE_TO_PLAYER,
TEAM_UPDATE,
MUTE_UPDATE,
CREATE_TEAM,
};
#endif //!__ECHATINTERNALMESSAGETYPE__H__

View File

@@ -72,7 +72,9 @@ enum class eChatMessageType :uint32_t {
UPDATE_DONATION,
PRG_CSR_COMMAND,
HEARTBEAT_REQUEST_FROM_WORLD,
UPDATE_FREE_TRIAL_STATUS
UPDATE_FREE_TRIAL_STATUS,
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
CREATE_TEAM,
};
#endif //!__ECHATMESSAGETYPE__H__

View File

@@ -5,8 +5,7 @@ enum class eConnectionType : uint16_t {
SERVER = 0,
AUTH,
CHAT,
CHAT_INTERNAL,
WORLD,
WORLD = 4,
CLIENT,
MASTER
};

View File

@@ -790,9 +790,10 @@ enum class eGameMessageType : uint16_t {
GET_MISSION_TYPE_STATES = 853,
GET_TIME_PLAYED = 854,
SET_MISSION_VIEWED = 855,
SLASH_COMMAND_TEXT_FEEDBACK = 856,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 857,
HKX_VEHICLE_LOADED = 856,
SLASH_COMMAND_TEXT_FEEDBACK = 857,
BROADCAST_TEXT_TO_CHATBOX = 858,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 859,
OPEN_PROPERTY_MANAGEMENT = 860,
OPEN_PROPERTY_VENDOR = 861,
VOTE_ON_PROPERTY = 862,

View File

@@ -0,0 +1,59 @@
#ifndef __EWAYPOINTCOMMANDTYPES__H__
#define __EWAYPOINTCOMMANDTYPES__H__
#include <cstdint>
enum class eWaypointCommandType : uint32_t {
INVALID,
BOUNCE,
STOP,
GROUP_EMOTE,
SET_VARIABLE,
CAST_SKILL,
EQUIP_INVENTORY,
UNEQUIP_INVENTORY,
DELAY,
EMOTE,
TELEPORT,
PATH_SPEED,
REMOVE_NPC,
CHANGE_WAYPOINT,
DELETE_SELF,
KILL_SELF,
SPAWN_OBJECT,
PLAY_SOUND,
};
class WaypointCommandType {
public:
static eWaypointCommandType StringToWaypointCommandType(std::string commandString) {
const std::map<std::string, eWaypointCommandType> WaypointCommandTypeMap = {
{"bounce", eWaypointCommandType::BOUNCE},
{"stop", eWaypointCommandType::STOP},
{"groupemote", eWaypointCommandType::GROUP_EMOTE},
{"setvar", eWaypointCommandType::SET_VARIABLE},
{"castskill", eWaypointCommandType::CAST_SKILL},
{"eqInvent", eWaypointCommandType::EQUIP_INVENTORY},
{"unInvent", eWaypointCommandType::UNEQUIP_INVENTORY},
{"delay", eWaypointCommandType::DELAY},
{"femote", eWaypointCommandType::EMOTE},
{"emote", eWaypointCommandType::EMOTE},
{"teleport", eWaypointCommandType::TELEPORT},
{"pathspeed", eWaypointCommandType::PATH_SPEED},
{"removeNPC", eWaypointCommandType::REMOVE_NPC},
{"changeWP", eWaypointCommandType::CHANGE_WAYPOINT},
{"DeleteSelf", eWaypointCommandType::DELETE_SELF},
{"killself", eWaypointCommandType::KILL_SELF},
{"removeself", eWaypointCommandType::DELETE_SELF},
{"spawnOBJ", eWaypointCommandType::SPAWN_OBJECT},
{"playSound", eWaypointCommandType::PLAY_SOUND},
};
auto intermed = WaypointCommandTypeMap.find(commandString);
return (intermed != WaypointCommandTypeMap.end()) ? intermed->second : eWaypointCommandType::INVALID;
};
};
#endif //!__EWAYPOINTCOMMANDTYPES__H__

View File

@@ -29,8 +29,8 @@ enum class eWorldMessageType : uint32_t {
ROUTE_PACKET, // Social?
POSITION_UPDATE,
MAIL,
WORD_CHECK, // Whitelist word check
STRING_CHECK, // Whitelist string check
WORD_CHECK, // AllowList word check
STRING_CHECK, // AllowList string check
GET_PLAYERS_IN_ZONE,
REQUEST_UGC_MANIFEST_INFO,
BLUEPRINT_GET_ALL_DATA_REQUEST,

View File

@@ -25,6 +25,7 @@
#include "CDScriptComponentTable.h"
#include "CDSkillBehaviorTable.h"
#include "CDZoneTableTable.h"
#include "CDTamingBuildPuzzleTable.h"
#include "CDVendorComponentTable.h"
#include "CDActivitiesTable.h"
#include "CDPackageComponentTable.h"
@@ -41,8 +42,6 @@
#include "CDRewardCodesTable.h"
#include "CDPetComponentTable.h"
#include <exception>
#ifndef CDCLIENT_CACHE_ALL
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
// A vanilla CDClient takes about 46MB of memory + the regular world data.
@@ -55,13 +54,6 @@
#define CDCLIENT_DONT_CACHE_TABLE(x)
#endif
class CDClientConnectionException : public std::exception {
public:
virtual const char* what() const throw() {
return "CDClientDatabase is not connected!";
}
};
// Using a macro to reduce repetitive code and issues from copy and paste.
// As a note, ## in a macro is used to concatenate two tokens together.
@@ -108,11 +100,14 @@ DEFINE_TABLE_STORAGE(CDRewardCodesTable);
DEFINE_TABLE_STORAGE(CDRewardsTable);
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
DEFINE_TABLE_STORAGE(CDTamingBuildPuzzleTable);
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
DEFINE_TABLE_STORAGE(CDZoneTableTable);
void CDClientManager::LoadValuesFromDatabase() {
if (!CDClientDatabase::isConnected) throw CDClientConnectionException();
if (!CDClientDatabase::isConnected) {
throw std::runtime_error{ "CDClientDatabase is not connected!" };
}
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
CDActivitiesTable::Instance().LoadValuesFromDatabase();
@@ -152,12 +147,13 @@ void CDClientManager::LoadValuesFromDatabase() {
CDRewardsTable::Instance().LoadValuesFromDatabase();
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
CDTamingBuildPuzzleTable::Instance().LoadValuesFromDatabase();
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
CDZoneTableTable::Instance().LoadValuesFromDatabase();
}
void CDClientManager::LoadValuesFromDefaults() {
Log::Info("Loading default CDClient tables!");
LOG("Loading default CDClient tables!");
CDPetComponentTable::Instance().LoadValuesFromDefaults();
}

View File

@@ -50,14 +50,14 @@ void CDPetComponentTable::LoadValuesFromDatabase() {
}
void CDPetComponentTable::LoadValuesFromDefaults() {
GetEntriesMutable().insert(std::make_pair(defaultEntry.id, defaultEntry));
GetEntriesMutable().emplace(defaultEntry.id, defaultEntry);
}
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
auto& entries = GetEntriesMutable();
auto itr = entries.find(componentID);
if (itr == entries.end()) {
Log::Warn("Unable to load pet component (ID {:d}) values from database! Using default values instead.", componentID);
LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID);
return defaultEntry;
}
return itr->second;

View File

@@ -0,0 +1,35 @@
#include "CDTamingBuildPuzzleTable.h"
void CDTamingBuildPuzzleTable::LoadValuesFromDatabase() {
// First, get the size of the table
uint32_t size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM TamingBuildPuzzles");
while (!tableSize.eof()) {
size = tableSize.getIntField(0, 0);
tableSize.nextRow();
}
// Reserve the size
auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM TamingBuildPuzzles");
while (!tableData.eof()) {
const auto lot = static_cast<LOT>(tableData.getIntField("NPCLot", LOT_NULL));
entries.emplace(lot, CDTamingBuildPuzzle{
.puzzleModelLot = lot,
.validPieces{ tableData.getStringField("ValidPiecesLXF") },
.timeLimit = static_cast<float>(tableData.getFloatField("Timelimit", 30.0f)),
.numValidPieces = tableData.getIntField("NumValidPieces", 6),
.imaginationCost = tableData.getIntField("imagCostPerBuild", 10)
});
tableData.nextRow();
}
}
const CDTamingBuildPuzzle* CDTamingBuildPuzzleTable::GetByLOT(const LOT lot) const {
const auto& entries = GetEntries();
const auto itr = entries.find(lot);
return itr != entries.cend() ? &itr->second : nullptr;
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include "CDTable.h"
/**
* Information for the minigame to be completed
*/
struct CDTamingBuildPuzzle {
UNUSED_COLUMN(uint32_t id = 0;)
// The LOT of the object that is to be created
LOT puzzleModelLot = LOT_NULL;
// The LOT of the NPC
UNUSED_COLUMN(LOT npcLot = LOT_NULL;)
// The .lxfml file that contains the bricks required to build the model
std::string validPieces{};
// The .lxfml file that contains the bricks NOT required to build the model
UNUSED_COLUMN(std::string invalidPieces{};)
// Difficulty value
UNUSED_COLUMN(int32_t difficulty = 1;)
// The time limit to complete the build
float timeLimit = 30.0f;
// The number of pieces required to complete the minigame
int32_t numValidPieces = 6;
// Number of valid pieces
UNUSED_COLUMN(int32_t totalNumPieces = 16;)
// Model name
UNUSED_COLUMN(std::string modelName{};)
// The .lxfml file that contains the full model
UNUSED_COLUMN(std::string fullModel{};)
// The duration of the pet taming minigame
UNUSED_COLUMN(float duration = 45.0f;)
// The imagination cost for the tamer to start the minigame
int32_t imaginationCost = 10;
};
class CDTamingBuildPuzzleTable : public CDTable<CDTamingBuildPuzzleTable, std::unordered_map<LOT, CDTamingBuildPuzzle>> {
public:
/**
* Load values from the CD client database
*/
void LoadValuesFromDatabase();
/**
* Gets the pet ability table corresponding to the pet LOT
* @returns A pointer to the corresponding table, or nullptr if one cannot be found
*/
[[nodiscard]]
const CDTamingBuildPuzzle* GetByLOT(const LOT lot) const;
};

View File

@@ -36,5 +36,6 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
"CDRewardsTable.cpp"
"CDScriptComponentTable.cpp"
"CDSkillBehaviorTable.cpp"
"CDTamingBuildPuzzleTable.cpp"
"CDVendorComponentTable.cpp"
"CDZoneTableTable.cpp" PARENT_SCOPE)

View File

@@ -15,7 +15,7 @@ target_include_directories(dDatabaseCDClient PUBLIC "."
"${PROJECT_SOURCE_DIR}/dCommon"
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
)
target_link_libraries(dDatabaseCDClient PRIVATE fmt sqlite3)
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3)
if (${CDCLIENT_CACHE_ALL})
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})

View File

@@ -4,5 +4,4 @@ add_subdirectory(GameDatabase)
add_library(dDatabase STATIC "MigrationRunner.cpp")
target_include_directories(dDatabase PUBLIC ".")
target_link_libraries(dDatabase
PUBLIC dDatabaseCDClient dDatabaseGame
PRIVATE fmt)
PUBLIC dDatabaseCDClient dDatabaseGame)

View File

@@ -16,7 +16,6 @@ target_include_directories(dDatabaseGame PUBLIC "."
)
target_link_libraries(dDatabaseGame
PUBLIC MariaDB::ConnCpp
PRIVATE fmt
INTERFACE dCommon)
# Glob together all headers that need to be precompiled

View File

@@ -13,7 +13,7 @@ namespace {
void Database::Connect() {
if (database) {
Log::Warn("Tried to connect to database when it's already connected!");
LOG("Tried to connect to database when it's already connected!");
return;
}
@@ -23,7 +23,7 @@ void Database::Connect() {
GameDatabase* Database::Get() {
if (!database) {
Log::Warn("Tried to get database when it's not connected!");
LOG("Tried to get database when it's not connected!");
Connect();
}
return database;
@@ -35,6 +35,6 @@ void Database::Destroy(std::string source) {
delete database;
database = nullptr;
} else {
Log::Warn("Trying to destroy database when it's not connected!");
LOG("Trying to destroy database when it's not connected!");
}
}

View File

@@ -30,7 +30,7 @@ namespace sql {
};
#ifdef _DEBUG
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { Log::Warn("SQL Error: {:s}", ex.what()); throw; } } while(0)
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
#else
# define DLU_SQL_TRY_CATCH_RETHROW(x) x
#endif // _DEBUG

View File

@@ -53,8 +53,8 @@ void MySQLDatabase::Connect() {
void MySQLDatabase::Destroy(std::string source) {
if (!con) return;
if (source.empty()) Log::Info("Destroying MySQL connection!");
else Log::Info("Destroying MySQL connection from {:s}!", source);
if (source.empty()) LOG("Destroying MySQL connection!");
else LOG("Destroying MySQL connection from %s!", source.c_str());
con->close();
delete con;
@@ -68,7 +68,7 @@ void MySQLDatabase::ExecuteCustomQuery(const std::string_view query) {
sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& query) {
if (!con) {
Connect();
Log::Info("Trying to reconnect to MySQL");
LOG("Trying to reconnect to MySQL");
}
if (!con->isValid() || con->isClosed()) {
@@ -77,7 +77,7 @@ sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& quer
con = nullptr;
Connect();
Log::Info("Trying to reconnect to MySQL from invalid or closed connection");
LOG("Trying to reconnect to MySQL from invalid or closed connection");
}
return con->prepareStatement(sql::SQLString(query.c_str(), query.length()));

View File

@@ -147,91 +147,91 @@ private:
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
// Log::Info("{}", param);
// LOG("%s", param.data());
stmt->setString(index, param.data());
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
// Log::Info("{}", param);
// LOG("%s", param);
stmt->setString(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
// Log::Info("{}", param);
stmt->setString(index, param);
// LOG("%s", param.c_str());
stmt->setString(index, param.c_str());
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
// Log::Info("{}", param);
// LOG("%u", param);
stmt->setByte(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
// Log::Info("{}", param);
// LOG("%d", param);
stmt->setByte(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
// Log::Info("{}", param);
// LOG("%u", param);
stmt->setShort(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
// Log::Info("{}", param);
// LOG("%d", param);
stmt->setShort(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
// Log::Info("{}", param);
// LOG("%u", param);
stmt->setUInt(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
// Log::Info("{}", param);
// LOG("%d", param);
stmt->setInt(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
// Log::Info("{}", param);
// LOG("%llu", param);
stmt->setInt64(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
// Log::Info("{}", param);
// LOG("%llu", param);
stmt->setUInt64(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
// Log::Info({}", param);
// LOG("%f", param);
stmt->setFloat(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
// Log::Info("{}", param);
// LOG("%f", param);
stmt->setDouble(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
// Log::Info("{}", param);
// LOG("%d", param);
stmt->setBoolean(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
// Log::Info("Blob");
// LOG("Blob");
// This is the one time you will ever see me use const_cast.
stmt->setBlob(index, const_cast<std::istream*>(param));
}
@@ -239,10 +239,10 @@ inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istr
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
if (param) {
// Log::Info("{}", param.value());
// LOG("%d", param.value());
stmt->setInt(index, param.value());
} else {
// Log::Info("Null");
// LOG("Null");
stmt->setNull(index, sql::DataType::SQLNULL);
}
}

View File

@@ -38,8 +38,8 @@ void MySQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPr
0, // behavior 4. TODO implement this.
0 // behavior 5. TODO implement this.
);
} catch (const sql::SQLException& e) {
Log::Warn("Error inserting new property model: {:s}", e.what());
} catch (sql::SQLException& e) {
LOG("Error inserting new property model: %s", e.what());
}
}

View File

@@ -45,7 +45,7 @@ void MigrationRunner::RunMigrations() {
if (Database::Get()->IsMigrationRun(migration.name)) continue;
Log::Info("Running migration: {:s}", migration.name);
LOG("Running migration: %s", migration.name.c_str());
if (migration.name == "dlu/5_brick_model_sd0.sql") {
runSd0Migrations = true;
} else {
@@ -56,7 +56,7 @@ void MigrationRunner::RunMigrations() {
}
if (finalSQL.empty() && !runSd0Migrations) {
Log::Info("Server database is up to date.");
LOG("Server database is up to date.");
return;
}
@@ -67,7 +67,7 @@ void MigrationRunner::RunMigrations() {
if (query.empty()) continue;
Database::Get()->ExecuteCustomQuery(query.c_str());
} catch (sql::SQLException& e) {
Log::Info("Encountered error running migration: {:s}", e.what());
LOG("Encountered error running migration: %s", e.what());
}
}
}
@@ -75,9 +75,9 @@ void MigrationRunner::RunMigrations() {
// Do this last on the off chance none of the other migrations have been run yet.
if (runSd0Migrations) {
uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0();
Log::Info("{:d} models were updated from zlib to sd0.", numberOfUpdatedModels);
LOG("%i models were updated from zlib to sd0.", numberOfUpdatedModels);
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
Log::Info("{:d} models were truncated from the database.", numberOfTruncatedModels);
LOG("%i models were truncated from the database.", numberOfTruncatedModels);
}
}
@@ -111,14 +111,14 @@ void MigrationRunner::RunSQLiteMigrations() {
// Doing these 1 migration at a time since one takes a long time and some may think it is crashing.
// This will at the least guarentee that the full migration needs to be run in order to be counted as "migrated".
Log::Info("Executing migration: {:s}. This may take a while. Do not shut down server.", migration.name);
LOG("Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str());
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
for (const auto& dml : GeneralUtils::SplitString(migration.data, ';')) {
if (dml.empty()) continue;
try {
CDClientDatabase::ExecuteDML(dml.c_str());
} catch (CppSQLite3Exception& e) {
Log::Warn("Encountered error running DML command: ({:d}) : {:s}", e.errorCode(), e.errorMessage());
LOG("Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage());
}
}
@@ -129,5 +129,5 @@ void MigrationRunner::RunSQLiteMigrations() {
CDClientDatabase::ExecuteQuery("COMMIT;");
}
Log::Info("CDServer database is up to date.");
LOG("CDServer database is up to date.");
}

View File

@@ -27,12 +27,9 @@ Character::Character(uint32_t id, User* parentUser) {
m_ID = id;
m_ParentUser = parentUser;
m_OurEntity = nullptr;
m_Doc = nullptr;
}
Character::~Character() {
if (m_Doc) delete m_Doc;
m_Doc = nullptr;
m_OurEntity = nullptr;
m_ParentUser = nullptr;
}
@@ -55,8 +52,6 @@ void Character::UpdateInfoFromDatabase() {
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
m_ZoneCloneID = 0;
m_Doc = nullptr;
//Quickly and dirtly parse the xmlData to get the info we need:
DoQuickXMLDataParse();
@@ -70,28 +65,23 @@ void Character::UpdateInfoFromDatabase() {
}
void Character::UpdateFromDatabase() {
if (m_Doc) delete m_Doc;
UpdateInfoFromDatabase();
}
void Character::DoQuickXMLDataParse() {
if (m_XMLData.size() == 0) return;
delete m_Doc;
m_Doc = new tinyxml2::XMLDocument();
if (!m_Doc) return;
if (m_Doc->Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
Log::Info("Loaded xmlData for character {:s} ({:d})!", m_Name, m_ID);
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
} else {
Log::Warn("Failed to load xmlData!");
LOG("Failed to load xmlData!");
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
return;
}
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf");
tinyxml2::XMLElement* mf = m_Doc.FirstChildElement("obj")->FirstChildElement("mf");
if (!mf) {
Log::Warn("Failed to find mf tag!");
LOG("Failed to find mf tag!");
return;
}
@@ -108,16 +98,16 @@ void Character::DoQuickXMLDataParse() {
mf->QueryAttribute("ess", &m_Eyes);
mf->QueryAttribute("ms", &m_Mouth);
tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv");
tinyxml2::XMLElement* inv = m_Doc.FirstChildElement("obj")->FirstChildElement("inv");
if (!inv) {
Log::Warn("Char has no inv!");
LOG("Char has no inv!");
return;
}
tinyxml2::XMLElement* bag = inv->FirstChildElement("items")->FirstChildElement("in");
if (!bag) {
Log::Warn("Couldn't find bag0!");
LOG("Couldn't find bag0!");
return;
}
@@ -141,7 +131,7 @@ void Character::DoQuickXMLDataParse() {
}
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
if (character) {
character->QueryAttribute("cc", &m_Coins);
int32_t gm_level = 0;
@@ -205,7 +195,7 @@ void Character::DoQuickXMLDataParse() {
character->QueryAttribute("lzrw", &m_OriginalRotation.w);
}
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (flags) {
auto* currentChild = flags->FirstChildElement();
while (currentChild) {
@@ -239,12 +229,10 @@ void Character::SetBuildMode(bool buildMode) {
}
void Character::SaveXMLToDatabase() {
if (!m_Doc) return;
//For metrics, we'll record the time it took to save:
auto start = std::chrono::system_clock::now();
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
if (character) {
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
character->SetAttribute("cc", m_Coins);
@@ -266,11 +254,11 @@ void Character::SaveXMLToDatabase() {
}
auto emotes = character->FirstChildElement("ue");
if (!emotes) emotes = m_Doc->NewElement("ue");
if (!emotes) emotes = m_Doc.NewElement("ue");
emotes->DeleteChildren();
for (int emoteID : m_UnlockedEmotes) {
auto emote = m_Doc->NewElement("e");
auto emote = m_Doc.NewElement("e");
emote->SetAttribute("id", emoteID);
emotes->LinkEndChild(emote);
@@ -280,15 +268,15 @@ void Character::SaveXMLToDatabase() {
}
//Export our flags:
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (!flags) {
flags = m_Doc->NewElement("flag"); //Create a flags tag if we don't have one
m_Doc->FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time
flags = m_Doc.NewElement("flag"); //Create a flags tag if we don't have one
m_Doc.FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time
}
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
auto* f = m_Doc->NewElement("f");
auto* f = m_Doc.NewElement("f");
f->SetAttribute("id", flag.first);
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
@@ -301,7 +289,7 @@ void Character::SaveXMLToDatabase() {
// Prevents the news feed from showing up on world transfers
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
auto* s = m_Doc->NewElement("s");
auto* s = m_Doc.NewElement("s");
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
flags->LinkEndChild(s);
}
@@ -310,7 +298,7 @@ void Character::SaveXMLToDatabase() {
//Call upon the entity to update our xmlDoc:
if (!m_OurEntity) {
Log::Warn("{:d}:{:s} didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName());
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
return;
}
@@ -321,12 +309,12 @@ void Character::SaveXMLToDatabase() {
//For metrics, log the time it took to save:
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed = end - start;
Log::Info("{:d}:{:s} Saved character to Database in: {:f}s", this->GetID(), this->GetName(), elapsed.count());
LOG("%i:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count());
}
void Character::SetIsNewLogin() {
// If we dont have a flag element, then we cannot have a s element as a child of flag.
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (!flags) return;
auto* currentChild = flags->FirstChildElement();
@@ -334,7 +322,7 @@ void Character::SetIsNewLogin() {
auto* nextChild = currentChild->NextSiblingElement();
if (currentChild->Attribute("si")) {
flags->DeleteChild(currentChild);
Log::Info("Removed isLoggedIn flag from character {:d}:{:s}, saving character to database", GetID(), GetName());
LOG("Removed isLoggedIn flag from character %i:%s, saving character to database", GetID(), GetName().c_str());
WriteToDatabase();
}
currentChild = nextChild;
@@ -344,7 +332,7 @@ void Character::SetIsNewLogin() {
void Character::WriteToDatabase() {
//Dump our xml into m_XMLData:
tinyxml2::XMLPrinter printer(0, true, 0);
m_Doc->Print(&printer);
m_Doc.Print(&printer);
//Finally, save to db:
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
@@ -421,15 +409,15 @@ void Character::SetRetroactiveFlags() {
void Character::SaveXmlRespawnCheckpoints() {
//Export our respawn points:
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
if (!points) {
points = m_Doc->NewElement("res");
m_Doc->FirstChildElement("obj")->LinkEndChild(points);
points = m_Doc.NewElement("res");
m_Doc.FirstChildElement("obj")->LinkEndChild(points);
}
points->DeleteChildren();
for (const auto& point : m_WorldRespawnCheckpoints) {
auto* r = m_Doc->NewElement("r");
auto* r = m_Doc.NewElement("r");
r->SetAttribute("w", point.first);
r->SetAttribute("x", point.second.x);
@@ -443,7 +431,7 @@ void Character::SaveXmlRespawnCheckpoints() {
void Character::LoadXmlRespawnCheckpoints() {
m_WorldRespawnCheckpoints.clear();
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
if (!points) {
return;
}

View File

@@ -37,7 +37,7 @@ public:
void LoadXmlRespawnCheckpoints();
const std::string& GetXMLData() const { return m_XMLData; }
tinyxml2::XMLDocument* GetXMLDoc() const { return m_Doc; }
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
/**
* Out of abundance of safety and clarity of what this saves, this is its own function.
@@ -623,7 +623,7 @@ private:
/**
* The character XML belonging to this character
*/
tinyxml2::XMLDocument* m_Doc;
tinyxml2::XMLDocument m_Doc;
/**
* Title of an announcement this character made (reserved for GMs)

View File

@@ -138,11 +138,11 @@ Entity::Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser, Enti
Entity::~Entity() {
if (IsPlayer()) {
Log::Info("Deleted player");
LOG("Deleted player");
// Make sure the player exists first. Remove afterwards to prevent the OnPlayerExist functions from not being able to find the player.
if (!PlayerManager::RemovePlayer(this)) {
Log::Warn("Unable to find player to remove from manager.");
LOG("Unable to find player to remove from manager.");
return;
}
@@ -476,8 +476,7 @@ void Entity::Initialize() {
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr;
AddComponent<InventoryComponent>(xmlDoc);
AddComponent<InventoryComponent>();
}
// if this component exists, then we initialize it. it's value is always 0
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
@@ -731,15 +730,21 @@ void Entity::Initialize() {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName);
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>();
if (movementAIcomp){
// TODO: set path in existing movementAIComp
} else if (path->pathType == PathType::Movement) {
auto movementAIcomponent = GetComponent<MovementAIComponent>();
if (movementAIcomponent && combatAiId == 0) {
movementAIcomponent->SetPath(pathName);
} else {
// TODO: create movementAIcomp and set path
MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = "";
moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
AddComponent<MovementAIComponent>(moveInfo);
}
}*/
}
} else {
// else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
@@ -1238,7 +1243,7 @@ void Entity::WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType
outBitStream.Write0();
}
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument& doc) {
//This function should only ever be called from within Character, meaning doc should always exist when this is called.
//Naturally, we don't include any non-player components in this update function.
@@ -1629,10 +1634,8 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
for (CDObjectSkills skill : skills) {
CDSkillBehaviorTable* skillBehTable = CDClientManager::GetTable<CDSkillBehaviorTable>();
auto* skillComponent = GetComponent<SkillComponent>();
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID());
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
auto* missionComponent = GetComponent<MissionComponent>();

View File

@@ -174,7 +174,7 @@ public:
void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
void UpdateXMLDoc(tinyxml2::XMLDocument& doc);
void Update(float deltaTime);
// Events

View File

@@ -201,7 +201,7 @@ void EntityManager::KillEntities() {
auto* entity = GetEntity(toKill);
if (!entity) {
Log::Warn("Attempting to kill null entity {}", toKill);
LOG("Attempting to kill null entity %llu", toKill);
continue;
}
@@ -231,7 +231,7 @@ void EntityManager::DeleteEntities() {
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
} else {
Log::Warn("Attempted to delete non-existent entity {}", toDelete);
LOG("Attempted to delete non-existent entity %llu", toDelete);
}
m_Entities.erase(toDelete);
}
@@ -322,7 +322,7 @@ const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEnt
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
if (!entity) {
Log::Warn("Attempted to construct null entity");
LOG("Attempted to construct null entity");
return;
}

View File

@@ -236,7 +236,7 @@ void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t r
baseLookup += std::to_string(static_cast<uint32_t>(this->relatedPlayer));
}
baseLookup += " LIMIT 1";
Log::Debug("query is {:s}", baseLookup);
LOG_DEBUG("query is %s", baseLookup.c_str());
std::unique_ptr<sql::PreparedStatement> baseQuery(Database::Get()->CreatePreppedStmt(baseLookup));
baseQuery->setInt(1, this->gameID);
std::unique_ptr<sql::ResultSet> baseResult(baseQuery->executeQuery());
@@ -251,7 +251,7 @@ void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t r
int32_t res = snprintf(lookupBuffer.get(), STRING_LENGTH, queryBase.c_str(), orderBase.data(), filter.c_str(), resultStart, resultEnd);
DluAssert(res != -1);
std::unique_ptr<sql::PreparedStatement> query(Database::Get()->CreatePreppedStmt(lookupBuffer.get()));
Log::Debug("Query is {:s} vars are {:d} {:d} {:d}", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
LOG_DEBUG("Query is %s vars are %i %i %i", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
query->setInt(1, this->gameID);
if (this->infoType == InfoType::Friends) {
query->setInt(2, this->relatedPlayer);
@@ -358,7 +358,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi
}
case Leaderboard::Type::None:
default:
Log::Warn("Unknown leaderboard type {:d} for game {:d}. Cannot save score!", GeneralUtils::ToUnderlying(leaderboardType), activityId);
LOG("Unknown leaderboard type %i for game %i. Cannot save score!", leaderboardType, activityId);
return;
}
bool newHighScore = lowerScoreBetter ? newScore < oldScore : newScore > oldScore;
@@ -377,7 +377,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi
} else {
saveQuery = FormatInsert(leaderboardType, newScore, false);
}
Log::Info("save query {:s} {:d} {:d}", saveQuery, playerID, activityId);
LOG("save query %s %i %i", saveQuery.c_str(), playerID, activityId);
std::unique_ptr<sql::PreparedStatement> saveStatement(Database::Get()->CreatePreppedStmt(saveQuery));
saveStatement->setInt(1, playerID);
saveStatement->setInt(2, activityId);

View File

@@ -67,7 +67,7 @@ void Trade::SetAccepted(LWOOBJID participant, bool value) {
if (participant == m_ParticipantA) {
m_AcceptedA = !value;
Log::Info("Accepted from A ({}), B: ({})", value, m_AcceptedB);
LOG("Accepted from A (%d), B: (%d)", value, m_AcceptedB);
auto* entityB = GetParticipantBEntity();
@@ -77,7 +77,7 @@ void Trade::SetAccepted(LWOOBJID participant, bool value) {
} else if (participant == m_ParticipantB) {
m_AcceptedB = !value;
Log::Info("Accepted from B ({}), A: ({})", value, m_AcceptedA);
LOG("Accepted from B (%d), A: (%d)", value, m_AcceptedA);
auto* entityA = GetParticipantAEntity();
@@ -125,7 +125,7 @@ void Trade::Complete() {
// First verify both players have the coins and items requested for the trade.
if (characterA->GetCoins() < m_CoinsA || characterB->GetCoins() < m_CoinsB) {
Log::Warn("Possible coin trade cheating attempt! Aborting trade.");
LOG("Possible coin trade cheating attempt! Aborting trade.");
return;
}
@@ -133,11 +133,11 @@ void Trade::Complete() {
auto* itemToRemove = inventoryA->FindItemById(tradeItem.itemId);
if (itemToRemove) {
if (itemToRemove->GetCount() < tradeItem.itemCount) {
Log::Warn("Possible cheating attempt from {:s} in trading!!! Aborting trade", characterA->GetName());
LOG("Possible cheating attempt from %s in trading!!! Aborting trade", characterA->GetName().c_str());
return;
}
} else {
Log::Warn("Possible cheating attempt from {:s} in trading due to item not being available!!!", characterA->GetName());
LOG("Possible cheating attempt from %s in trading due to item not being available!!!", characterA->GetName().c_str());
return;
}
}
@@ -146,11 +146,11 @@ void Trade::Complete() {
auto* itemToRemove = inventoryB->FindItemById(tradeItem.itemId);
if (itemToRemove) {
if (itemToRemove->GetCount() < tradeItem.itemCount) {
Log::Warn("Possible cheating attempt from {:s} in trading!!! Aborting trade", characterB->GetName());
LOG("Possible cheating attempt from %s in trading!!! Aborting trade", characterB->GetName().c_str());
return;
}
} else {
Log::Warn("Possible cheating attempt from {:s} in trading due to item not being available!!! Aborting trade", characterB->GetName());
LOG("Possible cheating attempt from %s in trading due to item not being available!!! Aborting trade", characterB->GetName().c_str());
return;
}
}
@@ -194,7 +194,7 @@ void Trade::SendUpdateToOther(LWOOBJID participant) {
uint64_t coins;
std::vector<TradeItem> itemIds;
Log::Info("Attempting to send trade update");
LOG("Attempting to send trade update");
if (participant == m_ParticipantA) {
other = GetParticipantBEntity();
@@ -228,7 +228,7 @@ void Trade::SendUpdateToOther(LWOOBJID participant) {
items.push_back(tradeItem);
}
Log::Info("Sending trade update");
LOG("Sending trade update");
GameMessages::SendServerTradeUpdate(other->GetObjectID(), coins, items, other->GetSystemAddress());
}
@@ -281,7 +281,7 @@ Trade* TradingManager::NewTrade(LWOOBJID participantA, LWOOBJID participantB) {
trades[tradeId] = trade;
Log::Info("Created new trade between ({}) <-> ({})", participantA, participantB);
LOG("Created new trade between (%llu) <-> (%llu)", participantA, participantB);
return trade;
}

View File

@@ -38,7 +38,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
Character* character = new Character(lastUsedCharacterId, this);
character->UpdateFromDatabase();
m_Characters.push_back(character);
Log::Info("Loaded {:d} as it is the last used char", lastUsedCharacterId);
LOG("Loaded %i as it is the last used char", lastUsedCharacterId);
}
}
}
@@ -106,7 +106,7 @@ void User::UserOutOfSync() {
m_AmountOfTimesOutOfSync++;
if (m_AmountOfTimesOutOfSync > m_MaxDesyncAllowed) {
//YEET
Log::Warn("User {:s} was out of sync {:d} times out of {:d}, disconnecting for suspected speedhacking.", m_Username, m_AmountOfTimesOutOfSync, m_MaxDesyncAllowed);
LOG("User %s was out of sync %i times out of %i, disconnecting for suspected speedhacking.", m_Username.c_str(), m_AmountOfTimesOutOfSync, m_MaxDesyncAllowed);
Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE);
}
}

View File

@@ -26,7 +26,7 @@
#include "eCharacterCreationResponse.h"
#include "eRenameResponse.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "eChatMessageType.h"
#include "BitStreamUtils.h"
#include "CheatDetection.h"
@@ -45,7 +45,7 @@ void UserManager::Initialize() {
auto fnStream = Game::assetManager->GetFile("names/minifigname_first.txt");
if (!fnStream) {
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string());
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
}
@@ -57,7 +57,7 @@ void UserManager::Initialize() {
auto mnStream = Game::assetManager->GetFile("names/minifigname_middle.txt");
if (!mnStream) {
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string());
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
}
@@ -69,7 +69,7 @@ void UserManager::Initialize() {
auto lnStream = Game::assetManager->GetFile("names/minifigname_last.txt");
if (!lnStream) {
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string());
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
}
@@ -82,8 +82,8 @@ void UserManager::Initialize() {
// Load our pre-approved names:
auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt");
if (!chatListStream) {
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string());
throw std::runtime_error("Aborting initialization due to missing chat whitelist file.");
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing chat allowlist file.");
}
while (std::getline(chatListStream, line, '\n')) {
@@ -145,7 +145,7 @@ bool UserManager::DeleteUser(const SystemAddress& sysAddr) {
void UserManager::DeletePendingRemovals() {
for (auto* user : m_UsersToDelete) {
Log::Info("Deleted user {:d}", user->GetAccountID());
LOG("Deleted user %i", user->GetAccountID());
delete user;
}
@@ -306,27 +306,27 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
LOT pantsLOT = FindCharPantsID(pantsColor);
if (!name.empty() && Database::Get()->GetCharacterInfo(name)) {
Log::Info("AccountID: {:d} chose unavailable name: {:s}", u->GetAccountID(), name);
LOG("AccountID: %i chose unavailable name: %s", u->GetAccountID(), name.c_str());
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::CUSTOM_NAME_IN_USE);
return;
}
if (Database::Get()->GetCharacterInfo(predefinedName)) {
Log::Info("AccountID: {:d} chose unavailable predefined name: {:s}", u->GetAccountID(), predefinedName);
LOG("AccountID: %i chose unavailable predefined name: %s", u->GetAccountID(), predefinedName.c_str());
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::PREDEFINED_NAME_IN_USE);
return;
}
if (name.empty()) {
Log::Info("AccountID: {:d} is creating a character with predefined name: {:s}", u->GetAccountID(), predefinedName);
LOG("AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
} else {
Log::Info("AccountID: {:d} is creating a character with name: {:s} (temporary: {:s})", u->GetAccountID(), name, predefinedName);
LOG("AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
}
//Now that the name is ok, we can get an objectID from Master:
ObjectIDManager::RequestPersistentID([=, this](uint32_t objectID) mutable {
if (Database::Get()->GetCharacterInfo(objectID)) {
Log::Warn("Character object id unavailable, check object_id_tracker!");
LOG("Character object id unavailable, check object_id_tracker!");
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);
return;
}
@@ -397,7 +397,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr);
if (!u) {
Log::Warn("Couldn't get user to delete character");
LOG("Couldn't get user to delete character");
return;
}
@@ -406,7 +406,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
inStream.Read(objectID);
uint32_t charID = static_cast<uint32_t>(objectID);
Log::Info("Received char delete req for ID: {:d} ({:d})", objectID, charID);
LOG("Received char delete req for ID: %llu (%u)", objectID, charID);
bool hasCharacter = CheatDetection::VerifyLwoobjidIsSender(
objectID,
@@ -418,11 +418,11 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
if (!hasCharacter) {
WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
} else {
Log::Info("Deleting character {:d}", charID);
LOG("Deleting character %i", charID);
Database::Get()->DeleteCharacter(charID);
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
bitStream.Write(objectID);
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
@@ -433,7 +433,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) {
User* u = GetUser(sysAddr);
if (!u) {
Log::Warn("Couldn't get user to delete character");
LOG("Couldn't get user to delete character");
return;
}
@@ -444,7 +444,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT);
uint32_t charID = static_cast<uint32_t>(objectID);
Log::Info("Received char rename request for ID: {:d} ({:d})", objectID, charID);
LOG("Received char rename request for ID: %llu (%u)", objectID, charID);
LUWString LUWStringName;
inStream.Read(LUWStringName);
@@ -479,12 +479,12 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
if (!Database::Get()->GetCharacterInfo(newName)) {
if (IsNamePreapproved(newName)) {
Database::Get()->SetCharacterName(charID, newName);
Log::Info("Character {:s} now known as {:s}", character->GetName(), newName);
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
UserManager::RequestCharacterList(sysAddr);
} else {
Database::Get()->SetPendingCharacterName(charID, newName);
Log::Info("Character {:s} has been renamed to {:s} and is pending approval by a moderator.", character->GetName(), newName);
LOG("Character %s has been renamed to %s and is pending approval by a moderator.", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
UserManager::RequestCharacterList(sysAddr);
}
@@ -492,7 +492,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_IN_USE);
}
} else {
Log::Warn("Unknown error occurred when renaming character, either hasCharacter or character variable != true.");
LOG("Unknown error occurred when renaming character, either hasCharacter or character variable != true.");
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
}
}
@@ -500,7 +500,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID) {
User* u = GetUser(sysAddr);
if (!u) {
Log::Warn("Couldn't get user to log in character");
LOG("Couldn't get user to log in character");
return;
}
@@ -519,7 +519,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
if (zoneID == LWOZONEID_INVALID) zoneID = 1000; //Send char to VE
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneID, character->GetZoneClone(), false, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
Log::Info("Transferring {:s} to Zone {:d} (Instance {:d} | Clone {:d} | Mythran Shift: {:s}) with IP {:s} and Port {:d}", character->GetName(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP, serverPort);
LOG("Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i", character->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort);
if (character) {
character->SetZoneID(zoneID);
character->SetZoneInstance(zoneInstance);
@@ -529,24 +529,24 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
return;
});
} else {
Log::Warn("Unknown error occurred when logging in a character, either hasCharacter or character variable != true.");
LOG("Unknown error occurred when logging in a character, either hasCharacter or character variable != true.");
}
}
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
try {
auto stmt = CDClientDatabase::CreatePreppedStmt(
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
"select obj.id as objectId from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
);
stmt.bind(1, "character create shirt");
stmt.bind(2, static_cast<int>(shirtColor));
stmt.bind(3, static_cast<int>(shirtStyle));
auto tableData = stmt.execQuery();
auto shirtLOT = tableData.getIntField(0, 4069);
auto shirtLOT = tableData.getIntField("objectId", 4069);
tableData.finalize();
return shirtLOT;
} catch (const std::exception& ex) {
Log::Warn("Could not look up shirt {:d} {:d}: {:s}", shirtColor, shirtStyle, ex.what());
LOG("Could not look up shirt %i %i: %s", shirtColor, shirtStyle, ex.what());
// in case of no shirt found in CDServer, return problematic red vest.
return 4069;
}
@@ -555,16 +555,16 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
uint32_t FindCharPantsID(uint32_t pantsColor) {
try {
auto stmt = CDClientDatabase::CreatePreppedStmt(
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
"select obj.id as objectId from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
);
stmt.bind(1, "cc pants");
stmt.bind(2, static_cast<int>(pantsColor));
auto tableData = stmt.execQuery();
auto pantsLOT = tableData.getIntField(0, 2508);
auto pantsLOT = tableData.getIntField("objectId", 2508);
tableData.finalize();
return pantsLOT;
} catch (const std::exception& ex) {
Log::Warn("Could not look up pants {:d}: {:s}", pantsColor, ex.what());
LOG("Could not look up pants %i: %s", pantsColor, ex.what());
// in case of no pants color found in CDServer, return red pants.
return 2508;
}

View File

@@ -9,7 +9,7 @@ void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bi
uint32_t handle{};
if (!bitStream.Read(handle)) {
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -26,14 +26,14 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bitS
uint32_t behaviorId{};
if (!bitStream.Read(behaviorId)) {
Log::Warn("Unable to read behaviorId from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read behaviorId from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
return;
}
LWOOBJID target{};
if (!bitStream.Read(target)) {
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
return;
}

View File

@@ -16,7 +16,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream& b
uint32_t targetCount{};
if (!bitStream.Read(targetCount)) {
Log::Warn("Unable to read targetCount from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read targetCount from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -28,7 +28,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream& b
}
if (targetCount > this->m_maxTargets) {
Log::Warn("Serialized size is greater than max targets! Size: {:d}, Max: {:d}", targetCount, this->m_maxTargets);
LOG("Serialized size is greater than max targets! Size: %i, Max: %i", targetCount, this->m_maxTargets);
return;
}
@@ -41,7 +41,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream& b
for (auto i = 0u; i < targetCount; ++i) {
LWOOBJID target{};
if (!bitStream.Read(target)) {
Log::Warn("failed to read in target {:d} from bitStream, aborting target Handle!", i);
LOG("failed to read in target %i from bitStream, aborting target Handle!", i);
};
targets.push_back(target);
}

View File

@@ -8,7 +8,7 @@ void AttackDelayBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bi
uint32_t handle{};
if (!bitStream.Read(handle)) {
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};

View File

@@ -34,10 +34,10 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bi
uint16_t allocatedBits{};
if (!bitStream.Read(allocatedBits) || allocatedBits == 0) {
Log::Debug("No allocated bits");
LOG_DEBUG("No allocated bits");
return;
}
Log::Debug("Number of allocated bits {:d}", allocatedBits);
LOG_DEBUG("Number of allocated bits %i", allocatedBits);
const auto baseAddress = bitStream.GetReadOffset();
DoHandleBehavior(context, bitStream, branch);
@@ -48,13 +48,13 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bi
void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* targetEntity = Game::entityManager->GetEntity(branch.target);
if (!targetEntity) {
Log::Warn("Target targetEntity {:d} not found.", branch.target);
LOG("Target targetEntity %llu not found.", branch.target);
return;
}
auto* destroyableComponent = targetEntity->GetComponent<DestroyableComponent>();
if (!destroyableComponent) {
Log::Warn("No destroyable found on the obj/lot {:d}/{:d}", branch.target, targetEntity->GetLOT());
LOG("No destroyable found on the obj/lot %llu/%i", branch.target, targetEntity->GetLOT());
return;
}
@@ -63,7 +63,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
bool isSuccess{};
if (!bitStream.Read(isBlocked)) {
Log::Warn("Unable to read isBlocked");
LOG("Unable to read isBlocked");
return;
}
@@ -75,31 +75,31 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
}
if (!bitStream.Read(isImmune)) {
Log::Warn("Unable to read isImmune");
LOG("Unable to read isImmune");
return;
}
if (isImmune) {
Log::Debug("Target targetEntity {} is immune!", branch.target);
LOG_DEBUG("Target targetEntity %llu is immune!", branch.target);
this->m_OnFailImmune->Handle(context, bitStream, branch);
return;
}
if (!bitStream.Read(isSuccess)) {
Log::Warn("failed to read success from bitstream");
LOG("failed to read success from bitstream");
return;
}
if (isSuccess) {
uint32_t armorDamageDealt{};
if (!bitStream.Read(armorDamageDealt)) {
Log::Warn("Unable to read armorDamageDealt");
LOG("Unable to read armorDamageDealt");
return;
}
uint32_t healthDamageDealt{};
if (!bitStream.Read(healthDamageDealt)) {
Log::Warn("Unable to read healthDamageDealt");
LOG("Unable to read healthDamageDealt");
return;
}
@@ -112,7 +112,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
bool died{};
if (!bitStream.Read(died)) {
Log::Warn("Unable to read died");
LOG("Unable to read died");
return;
}
auto previousArmor = destroyableComponent->GetArmor();
@@ -123,7 +123,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
uint8_t successState{};
if (!bitStream.Read(successState)) {
Log::Warn("Unable to read success state");
LOG("Unable to read success state");
return;
}
@@ -136,7 +136,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
break;
default:
if (static_cast<eBasicAttackSuccessTypes>(successState) != eBasicAttackSuccessTypes::FAILIMMUNE) {
Log::Warn("Unknown success state ({})!", successState);
LOG("Unknown success state (%i)!", successState);
return;
}
this->m_OnFailImmune->Handle(context, bitStream, branch);
@@ -166,13 +166,13 @@ void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream&
void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* targetEntity = Game::entityManager->GetEntity(branch.target);
if (!targetEntity) {
Log::Warn("Target entity {} is null!", branch.target);
LOG("Target entity %llu is null!", branch.target);
return;
}
auto* destroyableComponent = targetEntity->GetComponent<DestroyableComponent>();
if (!destroyableComponent || !destroyableComponent->GetParent()) {
Log::Warn("No destroyable component on {}", branch.target);
LOG("No destroyable component on %llu", branch.target);
return;
}
@@ -191,7 +191,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
bitStream.Write(isImmune);
if (isImmune) {
Log::Debug("Target targetEntity {} is immune!", branch.target);
LOG_DEBUG("Target targetEntity %llu is immune!", branch.target);
this->m_OnFailImmune->Calculate(context, bitStream, branch);
return;
}
@@ -222,7 +222,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
if (healthDamageDealt >= 1) {
successState = eBasicAttackSuccessTypes::SUCCESS;
} else if (armorDamageDealt >= 1) {
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
}
bitStream.Write(armorDamageDealt);
@@ -241,7 +241,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
break;
default:
if (static_cast<eBasicAttackSuccessTypes>(successState) != eBasicAttackSuccessTypes::FAILIMMUNE) {
Log::Warn("Unknown success state ({})!", GeneralUtils::ToUnderlying(successState));
LOG("Unknown success state (%i)!", successState);
break;
}
this->m_OnFailImmune->Calculate(context, bitStream, branch);

View File

@@ -5,7 +5,7 @@
#include "CDActivitiesTable.h"
#include "Game.h"
#include "Logger.h"
#include "BehaviorTemplates.h"
#include "BehaviorTemplate.h"
#include "BehaviorBranchContext.h"
#include <unordered_map>
@@ -110,183 +110,183 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
Behavior* behavior = nullptr;
switch (templateId) {
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
case BehaviorTemplate::EMPTY: break;
case BehaviorTemplate::BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
case BehaviorTemplate::TAC_ARC:
behavior = new TacArcBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AND:
case BehaviorTemplate::AND:
behavior = new AndBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
case BehaviorTemplate::PROJECTILE_ATTACK:
behavior = new ProjectileAttackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_HEAL:
case BehaviorTemplate::HEAL:
behavior = new HealBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
case BehaviorTemplate::MOVEMENT_SWITCH:
behavior = new MovementSwitchBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
case BehaviorTemplate::AREA_OF_EFFECT:
behavior = new AreaOfEffectBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
case BehaviorTemplate::PLAY_EFFECT:
behavior = new PlayEffectBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
case BehaviorTemplate::IMMUNITY:
behavior = new ImmunityBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
case BehaviorTemplate::DAMAGE_BUFF: break;
case BehaviorTemplate::DAMAGE_ABSORBTION:
behavior = new DamageAbsorptionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
case BehaviorTemplate::OVER_TIME:
behavior = new OverTimeBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
case BehaviorTemplate::IMAGINATION:
behavior = new ImaginationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
case BehaviorTemplate::TARGET_CASTER:
behavior = new TargetCasterBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_STUN:
case BehaviorTemplate::STUN:
behavior = new StunBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DURATION:
case BehaviorTemplate::DURATION:
behavior = new DurationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
case BehaviorTemplate::KNOCKBACK:
behavior = new KnockbackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
case BehaviorTemplate::ATTACK_DELAY:
behavior = new AttackDelayBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
case BehaviorTemplate::CAR_BOOST:
behavior = new CarBoostBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
case BehaviorTemplate::FALL_SPEED:
behavior = new FallSpeedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
case BehaviorTemplate::SHIELD: break;
case BehaviorTemplate::REPAIR_ARMOR:
behavior = new RepairBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPEED:
case BehaviorTemplate::SPEED:
behavior = new SpeedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
case BehaviorTemplate::DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
case BehaviorTemplate::LOOT_BUFF:
behavior = new LootBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION:
case BehaviorTemplate::VENTURE_VISION:
behavior = new VentureVisionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
case BehaviorTemplate::SPAWN_OBJECT:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
case BehaviorTemplates::BEHAVIOR_SWITCH:
case BehaviorTemplate::LAY_BRICK: break;
case BehaviorTemplate::SWITCH:
behavior = new SwitchBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_BUFF:
case BehaviorTemplate::BUFF:
behavior = new BuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_JETPACK:
case BehaviorTemplate::JETPACK:
behavior = new JetPackBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
case BehaviorTemplate::SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM:
case BehaviorTemplate::CONSUME_ITEM:
behavior = new ConsumeItemBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
case BehaviorTemplate::SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS:
case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
case BehaviorTemplate::CHANGE_IDLE_FLAGS:
behavior = new ChangeIdleFlagsBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
case BehaviorTemplate::APPLY_BUFF:
behavior = new ApplyBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CHAIN:
case BehaviorTemplate::CHAIN:
behavior = new ChainBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
case BehaviorTemplate::CHANGE_ORIENTATION:
behavior = new ChangeOrientationBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
case BehaviorTemplate::FORCE_MOVEMENT:
behavior = new ForceMovementBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
case BehaviorTemplate::INTERRUPT:
behavior = new InterruptBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
case BehaviorTemplate::ALTER_COOLDOWN: break;
case BehaviorTemplate::CHARGE_UP:
behavior = new ChargeUpBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
case BehaviorTemplate::SWITCH_MULTIPLE:
behavior = new SwitchMultipleBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_START:
case BehaviorTemplate::START:
behavior = new StartBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_END:
case BehaviorTemplate::END:
behavior = new EndBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF:
case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
case BehaviorTemplate::CAMERA: break;
case BehaviorTemplate::REMOVE_BUFF:
behavior = new RemoveBuffBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_GRAB: break;
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
case BehaviorTemplate::GRAB: break;
case BehaviorTemplate::MODULAR_BUILD: break;
case BehaviorTemplate::NPC_COMBAT_SKILL:
behavior = new NpcCombatSkillBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_BLOCK:
case BehaviorTemplate::BLOCK:
behavior = new BlockBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_VERIFY:
case BehaviorTemplate::VERIFY:
behavior = new VerifyBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAUNT:
case BehaviorTemplate::TAUNT:
behavior = new TauntBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
case BehaviorTemplate::AIR_MOVEMENT:
behavior = new AirMovementBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
case BehaviorTemplate::SPAWN_QUICKBUILD:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
case BehaviorTemplate::PULL_TO_POINT:
behavior = new PullToPointBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
case BehaviorTemplate::PROPERTY_ROTATE: break;
case BehaviorTemplate::DAMAGE_REDUCTION:
behavior = new DamageReductionBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT:
case BehaviorTemplate::PROPERTY_TELEPORT:
behavior = new PropertyTeleportBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
behavior = new ClearTargetBehavior(behaviorId);
break;
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
case BehaviorTemplate::TAKE_PICTURE: break;
case BehaviorTemplate::MOUNT: break;
case BehaviorTemplate::SKILL_SET: break;
default:
//Log::Warn("Failed to load behavior with invalid template id ({:d})!", templateId);
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
break;
}
if (behavior == nullptr) {
//Log::Warn("Failed to load unimplemented template id ({:d})!", templateId);
//LOG("Failed to load unimplemented template id (%i)!", templateId);
behavior = new EmptyBehavior(behaviorId);
}
@@ -296,20 +296,20 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
return behavior;
}
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY;
BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
// Find behavior template by its behavior id. Default to 0.
if (behaviorTemplateTable) {
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
if (templateEntry.behaviorID == behaviorId) {
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID);
templateID = static_cast<BehaviorTemplate>(templateEntry.templateID);
}
}
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
Log::Warn("Failed to load behavior template with id ({:d})!", behaviorId);
if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
LOG("Failed to load behavior template with id (%i)!", behaviorId);
}
return templateID;
@@ -335,26 +335,22 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
if (m_effectNames == nullptr) {
m_effectNames = new std::unordered_map<std::string, std::string>();
} else {
const auto pair = m_effectNames->find(typeString);
const auto itr = m_effectNames.find(typeString);
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
}
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(m_effectType);
}
if (pair != m_effectNames->end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
return;
}
renderComponent->PlayEffect(effectId, type, pair->second, secondary);
if (itr != m_effectNames.end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true);
return;
}
renderComponent->PlayEffect(effectId, type, itr->second, secondary);
return;
}
// The SQlite result object becomes invalid if the query object leaves scope.
@@ -381,19 +377,19 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
return;
}
const auto name = std::string(result.getStringField(0));
const auto name = std::string(result.getStringField("effectName"));
if (type.empty()) {
const auto typeResult = result.getStringField(1);
const auto typeResult = result.getStringField("effectType");
type = GeneralUtils::ASCIIToUTF16(typeResult);
m_effectType = new std::string(typeResult);
m_effectType = typeResult;
}
result.finalize();
m_effectNames->insert_or_assign(typeString, name);
m_effectNames.insert_or_assign(typeString, name);
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
@@ -423,26 +419,24 @@ Behavior::Behavior(const uint32_t behaviorId) {
if (behaviorId == 0) {
this->m_effectId = 0;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
this->m_templateId = BehaviorTemplate::EMPTY;
}
// Make sure we do not proceed if we are trying to load an invalid behavior
if (templateInDatabase.behaviorID == 0) {
Log::Warn("Failed to load behavior with id ({:d})!", behaviorId);
LOG("Failed to load behavior with id (%i)!", behaviorId);
this->m_effectId = 0;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
this->m_templateId = BehaviorTemplate::EMPTY;
return;
}
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID);
this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
this->m_effectId = templateInDatabase.effectID;
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
this->m_effectHandle = *templateInDatabase.effectHandle;
}
@@ -507,9 +501,3 @@ void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream,
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
}
Behavior::~Behavior() {
delete m_effectNames;
delete m_effectType;
delete m_effectHandle;
}

View File

@@ -6,7 +6,7 @@
#include <unordered_map>
#include "BitStream.h"
#include "BehaviorTemplates.h"
#include "BehaviorTemplate.h"
#include "dCommonVars.h"
struct BehaviorContext;
@@ -26,7 +26,7 @@ public:
static Behavior* CreateBehavior(uint32_t behaviorId);
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
/*
* Utilities
@@ -39,11 +39,11 @@ public:
*/
uint32_t m_behaviorId;
BehaviorTemplates m_templateId;
BehaviorTemplate m_templateId;
uint32_t m_effectId;
std::string* m_effectHandle = nullptr;
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
std::string* m_effectType = nullptr;
std::string m_effectHandle;
std::unordered_map<std::string, std::string> m_effectNames;
std::string m_effectType;
/*
* Behavior parameters
@@ -88,5 +88,11 @@ public:
*/
explicit Behavior(uint32_t behaviorId);
virtual ~Behavior();
virtual ~Behavior() = default;
Behavior(const Behavior& other) = default;
Behavior(Behavior&& other) = default;
Behavior& operator=(const Behavior& other) = default;
Behavior& operator=(Behavior&& other) = default;
};

View File

@@ -31,7 +31,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const {
auto* entity = Game::entityManager->GetEntity(this->originator);
if (entity == nullptr) {
Log::Warn("Invalid entity for ({})!", this->originator);
LOG("Invalid entity for (%llu)!", this->originator);
return 0;
}
@@ -39,7 +39,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const {
auto* component = entity->GetComponent<SkillComponent>();
if (component == nullptr) {
Log::Warn("No skill component attached to ({})!", this->originator);;
LOG("No skill component attached to (%llu)!", this->originator);;
return 0;
}
@@ -126,7 +126,7 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
}
if (!found) {
Log::Warn("Failed to find behavior sync entry with sync id ({})!", syncId);
LOG("Failed to find behavior sync entry with sync id (%i)!", syncId);
return;
}
@@ -135,7 +135,7 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
const auto branch = entry.branchContext;
if (behavior == nullptr) {
Log::Warn("Invalid behavior for sync id ({})!", syncId);
LOG("Invalid behavior for sync id (%i)!", syncId);
return;
}
@@ -317,7 +317,7 @@ void BehaviorContext::FilterTargets(std::vector<Entity*>& targets, std::forward_
// if the caster is not there, return empty targets list
auto* caster = Game::entityManager->GetEntity(this->caster);
if (!caster) {
Log::Debug("Invalid caster for ({})!", this->originator);
LOG_DEBUG("Invalid caster for (%llu)!", this->originator);
targets.clear();
return;
}

View File

@@ -0,0 +1,70 @@
#pragma once
enum class BehaviorTemplate : unsigned int {
EMPTY, // Not a real behavior, indicates invalid behaviors
BASIC_ATTACK,
TAC_ARC,
AND,
PROJECTILE_ATTACK,
HEAL,
MOVEMENT_SWITCH,
AREA_OF_EFFECT,
PLAY_EFFECT,
IMMUNITY,
DAMAGE_BUFF,
DAMAGE_ABSORBTION,
OVER_TIME,
IMAGINATION,
TARGET_CASTER,
STUN,
DURATION,
KNOCKBACK,
ATTACK_DELAY,
CAR_BOOST,
FALL_SPEED,
SHIELD,
REPAIR_ARMOR,
SPEED,
DARK_INSPIRATION,
LOOT_BUFF,
VENTURE_VISION,
SPAWN_OBJECT,
LAY_BRICK,
SWITCH,
BUFF,
JETPACK,
SKILL_EVENT,
CONSUME_ITEM,
SKILL_CAST_FAILED,
IMITATION_SKUNK_STINK,
CHANGE_IDLE_FLAGS,
APPLY_BUFF,
CHAIN,
CHANGE_ORIENTATION,
FORCE_MOVEMENT,
INTERRUPT,
ALTER_COOLDOWN,
CHARGE_UP,
SWITCH_MULTIPLE,
START,
END,
ALTER_CHAIN_DELAY,
CAMERA,
REMOVE_BUFF,
GRAB,
MODULAR_BUILD,
NPC_COMBAT_SKILL,
BLOCK,
VERIFY,
TAUNT,
AIR_MOVEMENT,
SPAWN_QUICKBUILD,
PULL_TO_POINT,
PROPERTY_ROTATE,
DAMAGE_REDUCTION,
PROPERTY_TELEPORT,
PROPERTY_CLEAR_TARGET,
TAKE_PICTURE,
MOUNT,
SKILL_SET
};

View File

@@ -1 +0,0 @@
#include "BehaviorTemplates.h"

View File

@@ -1,70 +0,0 @@
#pragma once
enum class BehaviorTemplates : unsigned int {
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors
BEHAVIOR_BASIC_ATTACK,
BEHAVIOR_TAC_ARC,
BEHAVIOR_AND,
BEHAVIOR_PROJECTILE_ATTACK,
BEHAVIOR_HEAL,
BEHAVIOR_MOVEMENT_SWITCH,
BEHAVIOR_AREA_OF_EFFECT,
BEHAVIOR_PLAY_EFFECT,
BEHAVIOR_IMMUNITY,
BEHAVIOR_DAMAGE_BUFF,
BEHAVIOR_DAMAGE_ABSORBTION,
BEHAVIOR_OVER_TIME,
BEHAVIOR_IMAGINATION,
BEHAVIOR_TARGET_CASTER,
BEHAVIOR_STUN,
BEHAVIOR_DURATION,
BEHAVIOR_KNOCKBACK,
BEHAVIOR_ATTACK_DELAY,
BEHAVIOR_CAR_BOOST,
BEHAVIOR_FALL_SPEED,
BEHAVIOR_SHIELD,
BEHAVIOR_REPAIR_ARMOR,
BEHAVIOR_SPEED,
BEHAVIOR_DARK_INSPIRATION,
BEHAVIOR_LOOT_BUFF,
BEHAVIOR_VENTURE_VISION,
BEHAVIOR_SPAWN_OBJECT,
BEHAVIOR_LAY_BRICK,
BEHAVIOR_SWITCH,
BEHAVIOR_BUFF,
BEHAVIOR_JETPACK,
BEHAVIOR_SKILL_EVENT,
BEHAVIOR_CONSUME_ITEM,
BEHAVIOR_SKILL_CAST_FAILED,
BEHAVIOR_IMITATION_SKUNK_STINK,
BEHAVIOR_CHANGE_IDLE_FLAGS,
BEHAVIOR_APPLY_BUFF,
BEHAVIOR_CHAIN,
BEHAVIOR_CHANGE_ORIENTATION,
BEHAVIOR_FORCE_MOVEMENT,
BEHAVIOR_INTERRUPT,
BEHAVIOR_ALTER_COOLDOWN,
BEHAVIOR_CHARGE_UP,
BEHAVIOR_SWITCH_MULTIPLE,
BEHAVIOR_START,
BEHAVIOR_END,
BEHAVIOR_ALTER_CHAIN_DELAY,
BEHAVIOR_CAMERA,
BEHAVIOR_REMOVE_BUFF,
BEHAVIOR_GRAB,
BEHAVIOR_MODULAR_BUILD,
BEHAVIOR_NPC_COMBAT_SKILL,
BEHAVIOR_BLOCK,
BEHAVIOR_VERIFY,
BEHAVIOR_TAUNT,
BEHAVIOR_AIR_MOVEMENT,
BEHAVIOR_SPAWN_QUICKBUILD,
BEHAVIOR_PULL_TO_POINT,
BEHAVIOR_PROPERTY_ROTATE,
BEHAVIOR_DAMAGE_REDUCTION,
BEHAVIOR_PROPERTY_TELEPORT,
BEHAVIOR_PROPERTY_CLEAR_TARGET,
BEHAVIOR_TAKE_PICTURE,
BEHAVIOR_MOUNT,
BEHAVIOR_SKILL_SET
};

View File

@@ -13,7 +13,7 @@ void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -43,7 +43,7 @@ void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branc
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}

View File

@@ -13,7 +13,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
Log::Warn("Invalid target ({})!", target);
LOG("Invalid target (%llu)!", target);
return;
}
@@ -21,7 +21,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream
auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) {
Log::Warn("Invalid target, no destroyable component ({})!", target);
LOG("Invalid target, no destroyable component (%llu)!", target);
return;
}
@@ -47,7 +47,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
Log::Warn("Invalid target ({})!", target);
LOG("Invalid target (%llu)!", target);
return;
}
@@ -55,7 +55,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) {
Log::Warn("Invalid target, no destroyable component ({})!", target);
LOG("Invalid target, no destroyable component (%llu)!", target);
return;
}

View File

@@ -7,7 +7,6 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
"Behavior.cpp"
"BehaviorBranchContext.cpp"
"BehaviorContext.cpp"
"BehaviorTemplates.cpp"
"BlockBehavior.cpp"
"BuffBehavior.cpp"
"CarBoostBehavior.cpp"

View File

@@ -17,7 +17,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitSt
return;
}
Log::Info("Activating car boost!");
LOG("Activating car boost!");
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
if (possessableComponent != nullptr) {
@@ -27,7 +27,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitSt
auto* characterComponent = possessor->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
Log::Info("Tracking car boost!");
LOG("Tracking car boost!");
characterComponent->UpdatePlayerStatistic(RacingCarBoostsActivated);
}
}

View File

@@ -7,7 +7,7 @@ void ChainBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
uint32_t chainIndex{};
if (!bitStream.Read(chainIndex)) {
Log::Warn("Unable to read chainIndex from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read chainIndex from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -16,7 +16,7 @@ void ChainBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
if (chainIndex < this->m_behaviors.size()) {
this->m_behaviors.at(chainIndex)->Handle(context, bitStream, branch);
} else {
Log::Warn("chainIndex out of bounds, aborting handle of chain {:d} bits unread {:d}", chainIndex, bitStream.GetNumberOfUnreadBits());
LOG("chainIndex out of bounds, aborting handle of chain %i bits unread %i", chainIndex, bitStream.GetNumberOfUnreadBits());
}
}

View File

@@ -8,7 +8,7 @@ void ChargeUpBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitSt
uint32_t handle{};
if (!bitStream.Read(handle)) {
Log::Warn("Unable to read handle from bitStream, aborting Handle! variable_type");
LOG("Unable to read handle from bitStream, aborting Handle! variable_type");
return;
};

View File

@@ -11,7 +11,7 @@ void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
auto* target = Game::entityManager->GetEntity(branch.target);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -37,7 +37,7 @@ void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchCon
auto* target = Game::entityManager->GetEntity(second);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", second);
LOG("Failed to find target (%llu)!", second);
return;
}

View File

@@ -11,7 +11,7 @@ void DamageReductionBehavior::Handle(BehaviorContext* context, RakNet::BitStream
auto* target = Game::entityManager->GetEntity(branch.target);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -35,7 +35,7 @@ void DamageReductionBehavior::Timer(BehaviorContext* context, BehaviorBranchCont
auto* target = Game::entityManager->GetEntity(second);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", second);
LOG("Failed to find target (%llu)!", second);
return;
}

View File

@@ -7,13 +7,13 @@
#include "Logger.h"
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}
uint32_t handle{};
if (!bitStream.Read(handle)) {
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
}
context->RegisterSyncBehavior(handle, this, branch, this->m_Duration);
@@ -22,13 +22,13 @@ void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
uint32_t next{};
if (!bitStream.Read(next)) {
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
return;
}
LWOOBJID target{};
if (!bitStream.Read(target)) {
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -38,7 +38,7 @@ void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bi
}
void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}

View File

@@ -11,7 +11,7 @@ void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit_strea
auto* entity = Game::entityManager->GetEntity(branch.target);
if (entity == nullptr) {
Log::Warn("Failed to find entity for ({})!", branch.target);
LOG("Failed to find entity for (%llu)!", branch.target);
return;
}
@@ -19,7 +19,7 @@ void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit_strea
auto* destroyable = static_cast<DestroyableComponent*>(entity->GetComponent(eReplicaComponentType::DESTROYABLE));
if (destroyable == nullptr) {
Log::Warn("Failed to find destroyable component for ({})!", branch.target);
LOG("Failed to find destroyable component for %(llu)!", branch.target);
return;
}

View File

@@ -13,7 +13,7 @@ void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitSt
auto* target = Game::entityManager->GetEntity(branch.target);
if (!target) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -59,7 +59,7 @@ void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext bra
auto* target = Game::entityManager->GetEntity(second);
if (!target) {
Log::Warn("Failed to find target ({})!", second);
LOG("Failed to find target (%llu)!", second);
return;
}

View File

@@ -8,36 +8,50 @@
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (branch.target != context->originator) {
bool unknown = false;
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown1 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
if (usedTarget != context->originator) {
bool isTargetImmuneStuns = false;
if (!bitStream.Read(isTargetImmuneStuns)) {
LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (unknown) return;
if (isTargetImmuneStuns) return;
}
if (!this->m_interruptBlock) {
bool unknown = false;
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown2 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
bool isBlockingInterrupts = false;
if (!bitStream.Read(isBlockingInterrupts)) {
LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (unknown) return;
if (isBlockingInterrupts) return;
}
if (this->m_target) // Guess...
{
bool unknown = false;
bool hasInterruptedStatusEffects = false;
if (!bitStream.Read(hasInterruptedStatusEffects)) {
LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown3 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
if (hasInterruptedStatusEffects) {
bool hasMoreInterruptedStatusEffects = false;
int32_t loopLimit = 0;
while (bitStream.Read(hasMoreInterruptedStatusEffects) && hasMoreInterruptedStatusEffects) {
int32_t statusEffectID = 0;
bitStream.Read(statusEffectID);
// nothing happens with this data yes. I have no idea why or what it was used for, but the client literally just reads it and does nothing with it.
// 0x004faca4 for a reference. it also has a hard loop limit of 100 soo,
loopLimit++;
if (loopLimit > 100) {
// if this is hit you have a problem
LOG("Loop limit reached for interrupted status effects, aborting Handle due to bad bitstream! %i", bitStream.GetNumberOfUnreadBits());
break;
}
LOG_DEBUG("Interrupted status effect ID: %i", statusEffectID);
}
}
if (branch.target == context->originator) return;
@@ -55,7 +69,8 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (branch.target != context->originator) {
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (usedTarget != context->originator) {
bitStream.Write(false);
}

View File

@@ -13,7 +13,7 @@ void KnockbackBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
bool unknown{};
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read unknown from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
}

View File

@@ -6,16 +6,16 @@
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
uint32_t movementType{};
if (!bitStream.Read(movementType)) {
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) {
return;
}
Log::Warn("Unable to read movementType from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -47,7 +47,7 @@ void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) {
float actionValue = GetFloat(movementType, -1.0f);
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) {
loadedBehavior = this->m_groundAction;
}
return loadedBehavior;

View File

@@ -12,14 +12,14 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
LWOOBJID target{};
if (!bitStream.Read(target)) {
Log::Warn("Unable to read target from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read target from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
auto* entity = Game::entityManager->GetEntity(context->originator);
if (entity == nullptr) {
Log::Warn("Failed to find originator ({:d})!", context->originator);
LOG("Failed to find originator (%llu)!", context->originator);
return;
}
@@ -27,7 +27,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent == nullptr) {
Log::Warn("Failed to find skill component for ({:d})!", -context->originator);
LOG("Failed to find skill component for (%llu)!", -context->originator);
return;
}
@@ -35,7 +35,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
if (m_useMouseposit && !branch.isSync) {
NiPoint3 targetPosition = NiPoint3Constant::ZERO;
if (!bitStream.Read(targetPosition)) {
Log::Warn("Unable to read targetPosition from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read targetPosition from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
}
@@ -46,7 +46,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
LWOOBJID projectileId{};
if (!bitStream.Read(projectileId)) {
Log::Warn("Unable to read projectileId from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read projectileId from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -64,7 +64,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
auto* entity = Game::entityManager->GetEntity(context->originator);
if (entity == nullptr) {
Log::Warn("Failed to find originator ({})!", context->originator);
LOG("Failed to find originator (%llu)!", context->originator);
return;
}
@@ -72,7 +72,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent == nullptr) {
Log::Warn("Failed to find skill component for ({})!", context->originator);
LOG("Failed to find skill component for (%llu)!", context->originator);
return;
@@ -81,7 +81,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
auto* other = Game::entityManager->GetEntity(branch.target);
if (other == nullptr) {
Log::Warn("Invalid projectile target ({})!", branch.target);
LOG("Invalid projectile target (%llu)!", branch.target);
return;
}

View File

@@ -40,7 +40,7 @@ void PropertyTeleportBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
if (zoneClone != 0) ChatPackets::SendSystemMessage(sysAddr, u"Transfering to your property!");
else ChatPackets::SendSystemMessage(sysAddr, u"Transfering back to previous world!");
Log::Info("Transferring {:s} to Zone {:d} (Instance {:d} | Clone {:d} | Mythran Shift: {:s}) with IP {:s} and Port {:d}", sysAddr.ToString(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP, serverPort);
LOG("Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i", sysAddr.ToString(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort);
if (entity->GetCharacter()) {
entity->GetCharacter()->SetZoneID(zoneID);
entity->GetCharacter()->SetZoneInstance(zoneInstance);

View File

@@ -11,7 +11,7 @@ void RepairBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit_str
auto* entity = Game::entityManager->GetEntity(branch.target);
if (entity == nullptr) {
Log::Warn("Failed to find entity for ({})!", branch.target);
LOG("Failed to find entity for (%llu)!", branch.target);
return;
}
@@ -19,7 +19,7 @@ void RepairBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit_str
auto* destroyable = static_cast<DestroyableComponent*>(entity->GetComponent(eReplicaComponentType::DESTROYABLE));
if (destroyable == nullptr) {
Log::Warn("Failed to find destroyable component for ({})!", branch.target);
LOG("Failed to find destroyable component for %(llu)!", branch.target);
return;
}

View File

@@ -9,17 +9,16 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
}
}
void
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
void SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
}
}

View File

@@ -15,7 +15,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
auto* origin = Game::entityManager->GetEntity(context->originator);
if (origin == nullptr) {
Log::Warn("Failed to find self entity ({})!", context->originator);
LOG("Failed to find self entity (%llu)!", context->originator);
return;
}
@@ -45,7 +45,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
);
if (entity == nullptr) {
Log::Warn("Failed to spawn entity ({})!", this->m_lot);
LOG("Failed to spawn entity (%i)!", this->m_lot);
return;
}
@@ -82,7 +82,7 @@ void SpawnBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext
auto* entity = Game::entityManager->GetEntity(second);
if (entity == nullptr) {
Log::Warn("Failed to find spawned entity ({})!", second);
LOG("Failed to find spawned entity (%llu)!", second);
return;
}

View File

@@ -17,14 +17,14 @@ void StunBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream
bool blocked{};
if (!bitStream.Read(blocked)) {
Log::Warn("Unable to read blocked from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read blocked from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
auto* target = Game::entityManager->GetEntity(branch.target);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -47,7 +47,7 @@ void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStr
auto* self = Game::entityManager->GetEntity(context->originator);
if (self == nullptr) {
Log::Warn("Invalid self entity ({})!", context->originator);
LOG("Invalid self entity (%llu)!", context->originator);
return;
}
@@ -82,7 +82,7 @@ void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStr
bitStream.Write(blocked);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}

View File

@@ -7,60 +7,70 @@
#include "BuffComponent.h"
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
auto state = true;
bool state = true;
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
if (!bitStream.Read(state)) {
Log::Warn("Unable to read state from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
}
auto* entity = Game::entityManager->GetEntity(context->originator);
if (entity == nullptr) {
return;
}
if (!entity) return;
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr) {
return;
if (destroyableComponent) {
if (m_isEnemyFaction) {
auto* target = Game::entityManager->GetEntity(branch.target);
if (target) state = destroyableComponent->IsEnemy(target);
}
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
}
Log::Debug("[{}] State: ({}), imagination: ({}) / ({})", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
if (state) {
this->m_actionTrue->Handle(context, bitStream, branch);
} else {
this->m_actionFalse->Handle(context, bitStream, branch);
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Handle(context, bitStream, branch);
}
void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto state = true;
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
bool state = true;
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
auto* entity = Game::entityManager->GetEntity(branch.target);
state = entity != nullptr;
if (state && m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (state) {
if (m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
state = false;
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
state = false;
}
} else if (m_imagination > 0) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent && destroyableComponent->GetImagination() < m_imagination) {
state = false;
}
} else if (m_Distance > -1.0f) {
auto* originator = Game::entityManager->GetEntity(context->originator);
if (originator) {
const auto distance = (originator->GetPosition() - entity->GetPosition()).Length();
state = distance <= m_Distance;
}
}
}
bitStream.Write(state);
}
if (state) {
this->m_actionTrue->Calculate(context, bitStream, branch);
} else {
this->m_actionFalse->Calculate(context, bitStream, branch);
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Calculate(context, bitStream, branch);
}
void SwitchBehavior::Load() {
@@ -72,5 +82,7 @@ void SwitchBehavior::Load() {
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
this->m_targetHasBuff = GetInt("target_has_buff");
this->m_targetHasBuff = GetInt("target_has_buff", -1);
this->m_Distance = GetFloat("distance", -1.0f);
}

View File

@@ -14,6 +14,8 @@ public:
int32_t m_targetHasBuff;
float m_Distance;
/*
* Inherited
*/

View File

@@ -13,7 +13,7 @@ void SwitchMultipleBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
float value{};
if (!bitStream.Read(value)) {
Log::Warn("Unable to read value from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read value from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -47,11 +47,11 @@ void SwitchMultipleBehavior::Load() {
auto result = query.execQuery();
while (!result.eof()) {
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));
const auto behavior_id = static_cast<uint32_t>(result.getFloatField("behavior"));
auto* behavior = CreateBehavior(behavior_id);
auto value = result.getFloatField(2);
auto value = result.getFloatField("value");
this->m_behaviors.emplace_back(value, behavior);

View File

@@ -16,7 +16,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
if (this->m_usePickedTarget && branch.target != LWOOBJID_EMPTY) {
auto target = Game::entityManager->GetEntity(branch.target);
if (!target) Log::Warn("target {} is null", branch.target);
if (!target) LOG("target %llu is null", branch.target);
else {
targets.push_back(target);
context->FilterTargets(targets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
@@ -29,7 +29,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
bool hasTargets = false;
if (!bitStream.Read(hasTargets)) {
Log::Warn("Unable to read hasTargets from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read hasTargets from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -37,7 +37,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
bool blocked = false;
if (!bitStream.Read(blocked)) {
Log::Warn("Unable to read blocked from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read blocked from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -50,12 +50,12 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
if (hasTargets) {
uint32_t count = 0;
if (!bitStream.Read(count)) {
Log::Warn("Unable to read count from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read count from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (count > m_maxTargets) {
Log::Warn("Bitstream has too many targets Max:{} Recv:{}", this->m_maxTargets, count);
LOG("Bitstream has too many targets Max:%i Recv:%i", this->m_maxTargets, count);
return;
}
@@ -63,7 +63,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
LWOOBJID id{};
if (!bitStream.Read(id)) {
Log::Warn("Unable to read id from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read id from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -71,7 +71,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
auto* canidate = Game::entityManager->GetEntity(id);
if (canidate) targets.push_back(canidate);
} else {
Log::Warn("Bitstream has LWOOBJID_EMPTY as a target!");
LOG("Bitstream has LWOOBJID_EMPTY as a target!");
}
}
@@ -85,7 +85,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* self = Game::entityManager->GetEntity(context->originator);
if (self == nullptr) {
Log::Warn("Invalid self for ({})!", context->originator);
LOG("Invalid self for (%llu)!", context->originator);
return;
}

View File

@@ -10,7 +10,7 @@ void TauntBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
auto* target = Game::entityManager->GetEntity(branch.target);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}
@@ -26,7 +26,7 @@ void TauntBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitSt
auto* target = Game::entityManager->GetEntity(branch.target);
if (target == nullptr) {
Log::Warn("Failed to find target ({})!", branch.target);
LOG("Failed to find target (%llu)!", branch.target);
return;
}

View File

@@ -18,7 +18,7 @@ void VerifyBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitS
auto* self = Game::entityManager->GetEntity(context->originator);
if (self == nullptr) {
Log::Warn("Invalid self for ({})", context->originator);
LOG("Invalid self for (%llu)", context->originator);
return;
}

View File

@@ -21,7 +21,7 @@
#include "eMissionTaskType.h"
#include "eMatchUpdate.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "eChatMessageType.h"
#include "CDCurrencyTableTable.h"
#include "CDActivityRewardsTable.h"
@@ -273,7 +273,7 @@ void ActivityComponent::Update(float deltaTime) {
// The timer has elapsed, start the instance
if (lobby->timer <= 0.0f) {
Log::Info("Setting up instance.");
LOG("Setting up instance.");
ActivityInstance* instance = NewInstance();
LoadPlayersIntoInstance(instance, lobby->players);
instance->StartZone();
@@ -501,7 +501,7 @@ void ActivityInstance::StartZone() {
// only make a team if we have more than one participant
if (participants.size() > 1) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::CREATE_TEAM);
bitStream.Write(leader->GetObjectID());
bitStream.Write(m_Participants.size());
@@ -524,7 +524,7 @@ void ActivityInstance::StartZone() {
if (player == nullptr)
return;
Log::Info("Transferring {:s} to Zone {:d} (Instance {:d} | Clone {:d} | Mythran Shift: {:s}) with IP {:s} and Port {:d}", player->GetCharacter()->GetName(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP, serverPort);
LOG("Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i", player->GetCharacter()->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort);
if (player->GetCharacter()) {
player->GetCharacter()->SetZoneID(zoneID);
player->GetCharacter()->SetZoneInstance(zoneInstance);

View File

@@ -45,20 +45,20 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
auto componentResult = componentQuery.execQuery();
if (!componentResult.eof()) {
if (!componentResult.fieldIsNull(0))
m_AggroRadius = componentResult.getFloatField(0);
if (!componentResult.fieldIsNull("aggroRadius"))
m_AggroRadius = componentResult.getFloatField("aggroRadius");
if (!componentResult.fieldIsNull(1))
m_TetherSpeed = componentResult.getFloatField(1);
if (!componentResult.fieldIsNull("tetherSpeed"))
m_TetherSpeed = componentResult.getFloatField("tetherSpeed");
if (!componentResult.fieldIsNull(2))
m_PursuitSpeed = componentResult.getFloatField(2);
if (!componentResult.fieldIsNull("pursuitSpeed"))
m_PursuitSpeed = componentResult.getFloatField("pursuitSpeed");
if (!componentResult.fieldIsNull(3))
m_SoftTetherRadius = componentResult.getFloatField(3);
if (!componentResult.fieldIsNull("softTetherRadius"))
m_SoftTetherRadius = componentResult.getFloatField("softTetherRadius");
if (!componentResult.fieldIsNull(4))
m_HardTetherRadius = componentResult.getFloatField(4);
if (!componentResult.fieldIsNull("hardTetherRadius"))
m_HardTetherRadius = componentResult.getFloatField("hardTetherRadius");
}
componentResult.finalize();
@@ -82,11 +82,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
auto result = skillQuery.execQuery();
while (!result.eof()) {
const auto skillId = static_cast<uint32_t>(result.getIntField(0));
const auto skillId = static_cast<uint32_t>(result.getIntField("skillID"));
const auto abilityCooldown = static_cast<float>(result.getFloatField(1));
const auto abilityCooldown = static_cast<float>(result.getFloatField("cooldown"));
const auto behaviorId = static_cast<uint32_t>(result.getIntField(2));
const auto behaviorId = static_cast<uint32_t>(result.getIntField("behaviorID"));
auto* behavior = Behavior::CreateBehavior(behaviorId);
@@ -150,19 +150,18 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
//Process enter events
for (auto en : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(en->GetObjectID());
for (const auto id : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(id);
}
//Process exit events
for (auto en : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
for (const auto id : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(id);
}
// Check if we should stop the tether effect
if (m_TetherEffectActive) {
m_TetherTime -= deltaTime;
const auto& info = m_MovementAI->GetInfo();
if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared(
m_StartPosition,
m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0)
@@ -540,7 +539,7 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
Log::Warn("Invalid entity for checking validity ({})!", target);
LOG("Invalid entity for checking validity (%llu)!", target);
return false;
}
@@ -554,7 +553,7 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
auto* referenceDestroyable = m_Parent->GetComponent<DestroyableComponent>();
if (referenceDestroyable == nullptr) {
Log::Warn("Invalid reference destroyable component on ({})!", m_Parent->GetObjectID());
LOG("Invalid reference destroyable component on (%llu)!", m_Parent->GetObjectID());
return false;
}

View File

@@ -81,13 +81,13 @@ void BouncerComponent::LookupPetSwitch() {
Game::entityManager->SerializeEntity(m_Parent);
Log::Info("Loaded pet bouncer");
LOG("Loaded pet bouncer");
}
}
}
if (!m_PetSwitchLoaded) {
Log::Warn("Failed to load pet bouncer");
LOG("Failed to load pet bouncer");
m_Parent->AddCallbackTimer(0.5f, [this]() {
LookupPetSwitch();

View File

@@ -110,7 +110,7 @@ void BuffComponent::Update(float deltaTime) {
const std::string& GetFxName(const std::string& buffname) {
const auto& toReturn = BuffFx[buffname];
if (toReturn.empty()) {
Log::Debug("No fx name for {:s}", buffname);
LOG_DEBUG("No fx name for %s", buffname.c_str());
}
return toReturn;
}
@@ -122,7 +122,7 @@ void BuffComponent::ApplyBuffFx(uint32_t buffId, const BuffParameter& buff) {
if (buffName.empty()) return;
fxToPlay += std::to_string(buffId);
Log::Debug("Playing {:s} {:d}", fxToPlay, buff.effectId);
LOG_DEBUG("Playing %s %i", fxToPlay.c_str(), buff.effectId);
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), buff.effectId, u"cast", fxToPlay, LWOOBJID_EMPTY, 1.07f, 1.0f, false);
}
@@ -133,7 +133,7 @@ void BuffComponent::RemoveBuffFx(uint32_t buffId, const BuffParameter& buff) {
if (buffName.empty()) return;
fxToPlay += std::to_string(buffId);
Log::Debug("Stopping {:s}", fxToPlay);
LOG_DEBUG("Stopping %s", fxToPlay.c_str());
GameMessages::SendStopFXEffect(m_Parent, false, fxToPlay);
}
@@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
return m_Parent;
}
void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
// Load buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
@@ -386,15 +386,15 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
}
void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
// Save buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
if (buffElement == nullptr) {
buffElement = doc->NewElement("buff");
buffElement = doc.NewElement("buff");
dest->LinkEndChild(buffElement);
} else {
@@ -402,7 +402,7 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
}
for (const auto& [id, buff] : m_Buffs) {
auto* buffEntry = doc->NewElement("b");
auto* buffEntry = doc.NewElement("b");
// TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout.
if (buff.cancelOnZone) continue;
@@ -450,7 +450,7 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
param.value = result.getFloatField("NumberValue");
param.effectId = result.getIntField("EffectID");
if (!result.fieldIsNull(3)) {
if (!result.fieldIsNull("StringValue")) {
std::istringstream stream(result.getStringField("StringValue"));
std::string token;
@@ -460,7 +460,7 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
param.values.push_back(value);
} catch (std::invalid_argument& exception) {
Log::Warn("Failed to parse value ({:s}): ({:s})!", token, exception.what());
LOG("Failed to parse value (%s): (%s)!", token.c_str(), exception.what());
}
}
}

View File

@@ -57,9 +57,9 @@ public:
Entity* GetParent() const;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -24,7 +24,7 @@ void BuildBorderComponent::OnUse(Entity* originator) {
if (!entities.empty()) {
buildArea = entities[0]->GetObjectID();
Log::Info("Using PropertyPlaque");
LOG("Using PropertyPlaque");
}
auto* inventoryComponent = originator->GetComponent<InventoryComponent>();
@@ -41,7 +41,7 @@ void BuildBorderComponent::OnUse(Entity* originator) {
inventoryComponent->PushEquippedItems();
Log::Info("Starting with {}", buildArea);
LOG("Starting with %llu", buildArea);
if (PropertyManagementComponent::Instance() != nullptr) {
GameMessages::SendStartArrangingWithItem(

View File

@@ -186,11 +186,11 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel;
}
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
Log::Warn("Failed to find char tag while loading XML!");
LOG("Failed to find char tag while loading XML!");
return;
}
if (character->QueryAttribute("rpt", &m_Reputation) == tinyxml2::XML_NO_ATTRIBUTE) {
@@ -299,10 +299,10 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
}
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* minifig = doc->FirstChildElement("obj")->FirstChildElement("mf");
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* minifig = doc.FirstChildElement("obj")->FirstChildElement("mf");
if (!minifig) {
Log::Warn("Failed to find mf tag while updating XML!");
LOG("Failed to find mf tag while updating XML!");
return;
}
@@ -320,9 +320,9 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// done with minifig
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
Log::Warn("Failed to find char tag while updating XML!");
LOG("Failed to find char tag while updating XML!");
return;
}
@@ -338,11 +338,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// Set the zone statistics of the form <zs><s/> ... <s/></zs>
auto zoneStatistics = character->FirstChildElement("zs");
if (!zoneStatistics) zoneStatistics = doc->NewElement("zs");
if (!zoneStatistics) zoneStatistics = doc.NewElement("zs");
zoneStatistics->DeleteChildren();
for (auto pair : m_ZoneStatistics) {
auto zoneStatistic = doc->NewElement("s");
auto zoneStatistic = doc.NewElement("s");
zoneStatistic->SetAttribute("map", pair.first);
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);
@@ -375,7 +375,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
//
auto newUpdateTimestamp = std::time(nullptr);
Log::Warn("Time since last save: {:d}", newUpdateTimestamp - m_LastUpdateTimestamp);
LOG("Time since last save: %d", newUpdateTimestamp - m_LastUpdateTimestamp);
m_TotalTimePlayed += newUpdateTimestamp - m_LastUpdateTimestamp;
character->SetAttribute("time", m_TotalTimePlayed);
@@ -405,7 +405,7 @@ Item* CharacterComponent::GetRocket(Entity* player) {
}
if (!rocket) {
Log::Warn("Unable to find rocket to equip!");
LOG("Unable to find rocket to equip!");
return rocket;
}
return rocket;
@@ -772,7 +772,7 @@ void CharacterComponent::AwardClaimCodes() {
auto* cdrewardCodes = CDClientManager::GetTable<CDRewardCodesTable>();
for (auto const rewardCode : rewardCodes) {
Log::Debug("Processing RewardCode {:d}", rewardCode);
LOG_DEBUG("Processing RewardCode %i", rewardCode);
const uint32_t rewardCodeIndex = rewardCode >> 6;
const uint32_t bitIndex = rewardCode % 64;
if (GeneralUtils::CheckBit(m_ClaimCodes[rewardCodeIndex], bitIndex)) continue;

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