Compare commits

..

10 Commits

Author SHA1 Message Date
jadebenn
4c4ea2ae71 replaced a few more macro instances 2024-03-13 20:47:41 -05:00
jadebenn
cfb0826d22 updated more logs 2024-03-12 21:10:01 -05:00
jadebenn
3164bad9af cmake fix 2024-03-12 20:35:17 -05:00
jadebenn
ceb1d5d82a converting more format strings 2024-03-09 03:09:17 -06:00
jadebenn
494c2b5784 fix cmake 2024-03-08 15:44:59 -06:00
jadebenn
0bcae8e555 Merge branch 'fmtlib-experiment' of https://github.com/DarkflameUniverse/DarkflameServer into fmtlib-experiment 2024-03-08 15:44:05 -06:00
jadebenn
7250aa51f6 experimenting; not looking to pr 2024-03-08 15:44:02 -06:00
jadebenn
ac6c68ecff cmake 2024-03-07 22:52:11 -06:00
jadebenn
642c86a449 Merge remote-tracking branch 'upstream/main' into fmtlib-experiment 2024-03-06 23:47:34 -06:00
jadebenn
73312cb948 add fmtlib 2024-03-06 22:15:54 -06:00
209 changed files with 4350 additions and 5841 deletions

3
.gitmodules vendored
View File

@@ -17,3 +17,6 @@
[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,12 +1,11 @@
cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.18)
project(Darkflame)
include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
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_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_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file
@@ -73,8 +72,7 @@ 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
# Also disable non-portable MSVC volatile behavior
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
add_compile_options("/wd4267" "/utf-8")
elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
@@ -96,7 +94,6 @@ 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)
@@ -105,7 +102,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" "blocklist.dcf")
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
message(STATUS "Checking resource file integrity")
include(Utils)
@@ -216,29 +213,29 @@ if (APPLE)
endif()
# Load all of our third party directories
add_subdirectory(thirdparty SYSTEM)
add_subdirectory(thirdparty)
# Create our list of include directories
include_directories(
set(INCLUDED_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)
@@ -247,9 +244,14 @@ 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} -Wold-style-cast -Werror") # Warning flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
file(
GLOB HEADERS_DZONEMANAGER
@@ -285,7 +287,7 @@ add_subdirectory(dPhysics)
add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "MariaDB::ConnCpp" "magic_enum" "nlohmann_json::nlohmann_json")
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "fmt" "raknet" "MariaDB::ConnCpp" "magic_enum")
# 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.25**</font> or later!).
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</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.25**</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.18**</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

View File

@@ -1,20 +0,0 @@
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 SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
target_include_directories(MariaDB::ConnCpp 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("Starting Auth server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
Log::Info("Starting Auth server...");
Log::Info("Version: {:s}", PROJECT_VERSION);
Log::Info("Compiled on: {:s}", __TIMESTAMP__);
try {
Database::Connect();
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Log::Info("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("Master is at %s:%d", masterIP.c_str(), masterPort);
Log::Info("Master is at {:s}:{:d}", masterIP, masterPort);
Game::randomEngine = std::mt19937(time(0));
@@ -110,7 +110,7 @@ int main(int argc, char** argv) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= authFramerate) {
LOG("No connection to master!");
Log::Info("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("Exited Main Loop! (signal %d)", Game::lastSignal);
Log::Info("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 ${COMMON_LIBRARIES} dServer)
target_link_libraries(AuthServer PRIVATE ${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("blocklist.dcf")) {
ReadWordlistDCF("blocklist.dcf", false);
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
ReadWordlistDCF("blacklist.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 allowList) {
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
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 (allowList) m_ApprovedWords.push_back(CalculateHash(line));
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
else m_DeniedWords.push_back(CalculateHash(line));
}
}
}
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath, std::ios::binary);
if (file) {
fileHeader hdr;
@@ -70,13 +70,13 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead);
if (allowList) m_ApprovedWords.reserve(wordsToRead);
if (whiteList) 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 (allowList) m_ApprovedWords.push_back(word);
if (whiteList) m_ApprovedWords.push_back(word);
else m_DeniedWords.push_back(word);
}
@@ -90,14 +90,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
return false;
}
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowList) {
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
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(allowList ? m_ApprovedWords.size() : m_DeniedWords.size()));
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
for (size_t word : allowList ? m_ApprovedWords : m_DeniedWords) {
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
BinaryIO::BinaryWrite(file, word);
}
@@ -105,10 +105,10 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowLis
}
}
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList) {
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
if (message.empty()) return { };
if (!allowList && m_DeniedWords.empty()) return { { 0, message.length() } };
if (!whiteList && 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() && allowList) {
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && allowList) {
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !allowList) {
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
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 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);
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);
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 ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)
target_link_libraries(dChatServer PRIVATE ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer PRIVATE ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)

View File

@@ -1,6 +1,6 @@
#include "ChatIgnoreList.h"
#include "PlayerContainer.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
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("Tried to get ignore list, but player %llu not found in container", playerId);
Log::Info("Tried to get ignore list, but player {:d} not found in container", playerId);
return;
}
if (!receiver.ignoredPlayers.empty()) {
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
Log::Debug("Player {:d} 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 %llu has no ignores", playerId);
Log::Debug("Player {:d} has no ignores", playerId);
return;
}
@@ -69,13 +69,13 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
Log::Info("Tried to get ignore list, but player {:d} not found in container", playerId);
return;
}
constexpr int32_t MAX_IGNORES = 32;
if (receiver.ignoredPlayers.size() > MAX_IGNORES) {
LOG_DEBUG("Player %llu has too many ignores", playerId);
Log::Debug("Player {:d} 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 %llu tried to ignore themselves", playerId);
Log::Debug("Player {:d} 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 %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
Log::Debug("Player {:d} is already ignoring {:s}", playerId, toIgnoreStr);
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.c_str());
Log::Debug("Player {:s} not found", toIgnoreStr);
} 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 %llu is ignoring %s", playerId, toIgnoreStr.c_str());
Log::Debug("Player {:d} is ignoring {:s}", playerId, toIgnoreStr);
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
} else {
@@ -141,7 +141,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
Log::Info("Tried to get ignore list, but player {:d} 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 %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
Log::Debug("Player {:d} is not ignoring {:s}", playerId, removedIgnoreStr);
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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
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("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
Log::Info("No requestor player {:d} sent to {:s} found.", requestorPlayerID, playerName);
return;
}
@@ -355,67 +355,6 @@ 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) {
@@ -437,7 +376,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
LUWString message(size);
inStream.Read(message);
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
Log::Info("Got a message from ({:s}) via [{:s}]: {:s}", sender.playerName, StringifiedEnum::ToString(channel), message.GetAsString());
switch (channel) {
case eChatChannel::TEAM: {
@@ -452,7 +391,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
break;
}
default:
LOG("Unhandled Chat channel [%s]", StringifiedEnum::ToString(channel).data());
Log::Info("Unhandled Chat channel [{:s}]", StringifiedEnum::ToString(channel));
break;
}
}
@@ -473,7 +412,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
inStream.IgnoreBytes(4);
inStream.Read(channel);
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
if (channel != eChatChannel::PRIVATE_CHAT) Log::Info("WARNING: Received Private chat with the wrong channel!");
inStream.Read(size);
inStream.IgnoreBytes(77);
@@ -485,7 +424,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
LUWString message(size);
inStream.Read(message);
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());
Log::Info("Got a message from ({:s}) via [{:s}]: {:s} to {:s}", sender.playerName, StringifiedEnum::ToString(channel), message.GetAsString(), receiverName);
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
if (!receiver) {
@@ -515,7 +454,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(routeTo.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
@@ -567,13 +506,13 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
if (team->memberIDs.size() > 3) {
// no more teams greater than 4
LOG("Someone tried to invite a 5th player to a team");
Log::Info("Someone tried to invite a 5th player to a team");
return;
}
SendTeamInvite(other, player);
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.GetAsString().c_str());
Log::Info("Got team invite: {:d} -> {:s}", playerID, invitedPlayer.GetAsString());
}
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
@@ -587,7 +526,7 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
LWOOBJID leaderID = LWOOBJID_EMPTY;
inStream.Read(leaderID);
LOG("Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
Log::Info("Accepted invite: {:d} -> {:d} ({:d})", playerID, leaderID, declined);
if (declined) {
return;
@@ -596,13 +535,13 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
auto* team = Game::playerContainer.GetTeam(leaderID);
if (team == nullptr) {
LOG("Failed to find team for leader (%llu)", leaderID);
Log::Info("Failed to find team for leader ({:d})", leaderID);
team = Game::playerContainer.GetTeam(playerID);
}
if (team == nullptr) {
LOG("Failed to find team for player (%llu)", playerID);
Log::Info("Failed to find team for player ({:d})", playerID);
return;
}
@@ -618,7 +557,7 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
auto* team = Game::playerContainer.GetTeam(playerID);
LOG("(%llu) leaving team", playerID);
Log::Info("({:d}) leaving team", playerID);
if (team != nullptr) {
Game::playerContainer.RemoveMember(team, playerID, false, false, true);
@@ -636,7 +575,7 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
inStream.Read(kickedPlayer);
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.GetAsString().c_str());
Log::Info("({:d}) kicking ({:s}) from team", playerID, kickedPlayer.GetAsString());
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer.GetAsString());
@@ -669,7 +608,7 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
inStream.IgnoreBytes(4);
inStream.Read(promotedPlayer);
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.GetAsString().c_str());
Log::Info("({:d}) promoting ({:s}) to team leader", playerID, promotedPlayer.GetAsString());
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer.GetAsString());
@@ -757,7 +696,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -772,7 +711,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -799,7 +738,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -824,7 +763,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -841,7 +780,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -870,7 +809,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -896,7 +835,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -930,7 +869,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
[bool] - is FTP*/
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(friendData.playerID);
//portion that will get routed:
@@ -967,7 +906,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
}
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -981,7 +920,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
// Portion that will get routed:
@@ -1004,7 +943,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, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:

View File

@@ -50,8 +50,6 @@ 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,6 +17,7 @@
#include "PlayerContainer.h"
#include "ChatPacketHandler.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "ChatIgnoreList.h"
#include "StringifiedEnum.h"
@@ -59,9 +60,9 @@ int main(int argc, char** argv) {
//Read our config:
LOG("Starting Chat server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
Log::Info("Starting Chat server...");
Log::Info("Version: {:s}", PROJECT_VERSION);
Log::Info("Compiled on: {:s}", __TIMESTAMP__);
try {
std::string clientPathStr = Game::config->GetValue("client_location");
@@ -73,7 +74,7 @@ int main(int argc, char** argv) {
Game::assetManager = new AssetManager(clientPath);
} catch (std::runtime_error& ex) {
LOG("Got an error while setting up assets: %s", ex.what());
Log::Info("Got an error while setting up assets: {:s}", ex.what());
return EXIT_FAILURE;
}
@@ -82,7 +83,7 @@ int main(int argc, char** argv) {
try {
Database::Connect();
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Log::Info("Got an error while connecting to the database: {:s}", ex.what());
Database::Destroy("ChatServer");
delete Game::server;
delete Game::logger;
@@ -180,30 +181,48 @@ int main(int argc, char** argv) {
void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
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
Log::Info("A server has disconnected, erasing their connected players from the list.");
}
CINSTREAM;
inStream.SetReadOffset(BYTES_TO_BITS(1));
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
Log::Info("A server is connecting, awaiting user list.");
}
eConnectionType connection;
eChatMessageType chatMessageID;
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
inStream.Read(connection);
if (connection != eConnectionType::CHAT) return;
inStream.Read(chatMessageID);
switch (chatMessageID) {
case eChatMessageType::GM_MUTE:
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:
Game::playerContainer.MuteUpdate(packet);
break;
case eChatMessageType::CREATE_TEAM:
case eChatInternalMessageType::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;
@@ -277,23 +296,6 @@ 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:
@@ -306,6 +308,7 @@ 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:
@@ -320,6 +323,7 @@ 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:
@@ -328,18 +332,33 @@ 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("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
Log::Info("Unhandled CHAT Message id: {:s} {:d}", StringifiedEnum::ToString(chat_message_type), GeneralUtils::ToUnderlying(chat_message_type));
break;
default:
LOG("Unknown CHAT Message id: %i", chatMessageID);
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]));
}
}
}

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

View File

@@ -71,9 +71,6 @@ 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);
@@ -96,7 +93,5 @@ 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("Encountered unwritable AMFType %i!", type);
Log::Warn("Encountered unwritable AMFType {:d}!", GeneralUtils::ToUnderlying(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("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
Log::Warn("Failed to inflate chunk {} for model %llu. Error: {}", chunkCount, model.id, err);
break;
}
chunkCount++;
}
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
if (!document) {
LOG("Failed to initialize tinyxml document. Aborting.");
Log::Warn("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("Brick-by-brick model %llu will be deleted!", model.id);
Log::Info("Brick-by-brick model {} will be deleted!", model.id);
Database::Get()->DeleteUgcModelData(model.id);
modelsTruncated++;
}
}
} else {
LOG("Brick-by-brick model %llu will be deleted!", model.id);
Log::Info("Brick-by-brick model {} 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("Updated model %i to sd0", model.id);
Log::Info("Updated model {} to sd0", model.id);
updatedModels++;
} catch (sql::SQLException exception) {
LOG("Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", model.id, exception.what());
Log::Warn("Failed to update model {}. This model should be inspected manually to see why."
"The database error is {}", model.id, exception.what());
}
}
}

View File

@@ -70,5 +70,6 @@ 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("Creating crash dump %s", name);
Log::Info("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("backtrace is enabled, crash dump located at %s", fileName.c_str());
Log::Info("backtrace is enabled, crash dump located at {:s}", fileName);
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;
fprintf(stderr, "ERROR: %s (%d)", msg, errnum);
fmt::print(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) {
fprintf(file, "ERROR: %s (%d)", msg, errnum);
fmt::print(file, "ERROR: {:s} ({:d})", msg, errnum);
fclose(file);
}
}
@@ -119,15 +119,13 @@ void CatchUnhandled(int sig) {
try {
if (eptr) std::rethrow_exception(eptr);
} catch(const std::exception& e) {
LOG("Caught exception: '%s'", e.what());
} catch (...) {
LOG("Caught unknown exception.");
Log::Warn("Caught exception: '{:s}'", e.what());
}
#ifndef INCLUDE_BACKTRACE
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
Log::Warn("Encountered signal {:d}, creating crash dump {:s}", sig, fileName);
if (Diagnostics::GetProduceMemoryDump()) {
GenerateDump();
}
@@ -145,7 +143,7 @@ void CatchUnhandled(int sig) {
FILE* file = fopen(fileName.c_str(), "w+");
if (file != NULL) {
fprintf(file, "Error: signal %d:\n", sig);
fmt::println(file, "Error: signal {:d}:", sig);
}
// Print the stack trace
for (size_t i = 0; i < size; i++) {
@@ -167,9 +165,9 @@ void CatchUnhandled(int sig) {
}
}
LOG("[%02zu] %s", i, functionName.c_str());
Log::Info("[{:02d}] {:s}", i, functionName);
if (file != NULL) {
fprintf(file, "[%02zu] %s\n", i, functionName.c_str());
fmt::println(file, "[{:02d}] {:s}", i, functionName);
}
}
# else // defined(__GNUG__)
@@ -210,7 +208,7 @@ void MakeBacktrace() {
sigaction(SIGFPE, &sigact, nullptr) != 0 ||
sigaction(SIGABRT, &sigact, nullptr) != 0 ||
sigaction(SIGILL, &sigact, nullptr) != 0) {
fprintf(stderr, "error setting signal handler for %d (%s)\n",
fmt::println(stderr, "error setting signal handler for {:d} ({:s})",
SIGSEGV,
strsignal(SIGSEGV));

View File

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

View File

@@ -8,23 +8,23 @@
#include <map>
template <typename T>
static inline size_t MinSize(const size_t size, const std::basic_string_view<T> string) {
if (size == SIZE_MAX || size > string.size()) {
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
if (size == size_t(-1) || size > string.size()) {
return string.size();
} else {
return size;
}
}
inline bool IsLeadSurrogate(const char16_t c) {
inline bool IsLeadSurrogate(char16_t c) {
return (0xD800 <= c) && (c <= 0xDBFF);
}
inline bool IsTrailSurrogate(const char16_t c) {
inline bool IsTrailSurrogate(char16_t c) {
return (0xDC00 <= c) && (c <= 0xDFFF);
}
inline void PushUTF8CodePoint(std::string& ret, const char32_t cp) {
inline void PushUTF8CodePoint(std::string& ret, 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, const char32_t cp) {
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
bool static _IsSuffixChar(const uint8_t c) {
bool _IsSuffixChar(uint8_t c) {
return (c & 0xC0) == 0x80;
}
bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
const size_t rem = slice.length();
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
size_t rem = slice.length();
if (slice.empty()) return false;
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
if (rem > 0) {
const uint8_t first = bytes[0];
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::details::_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) {
const uint8_t second = bytes[1];
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::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
}
} else if (first < 0xF0) { // three byte character
if (rem > 2) {
const uint8_t second = bytes[1];
const uint8_t third = bytes[2];
uint8_t second = bytes[1];
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::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
}
} else if (first < 0xF8) { // four byte character
if (rem > 3) {
const uint8_t second = bytes[1];
const uint8_t third = bytes[2];
const uint8_t fourth = bytes[3];
uint8_t second = bytes[1];
uint8_t third = bytes[2];
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::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
}
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t size) {
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, 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, const uint32_t U, const size_t s
// 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.
const uint32_t Ut = U - 0x10000;
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, const uint32_t U, const size_t s
} else return false;
}
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view string, const size_t size) {
const size_t newSize = MinSize(size, string);
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string output;
output.reserve(newSize);
std::string_view iterator = string;
uint32_t c;
while (details::_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
while (_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, const size_t size) {
const size_t newSize = MinSize(size, string);
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::u16string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; ++i) {
const char c = string[i];
for (size_t i = 0; i < newSize; i++) {
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, const s
//! 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, const size_t size) {
const size_t newSize = MinSize(size, string);
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
size_t newSize = MinSize(size, string);
std::string ret;
ret.reserve(newSize);
for (size_t i = 0; i < newSize; ++i) {
const char16_t u = string[i];
for (size_t i = 0; i < newSize; i++) {
char16_t u = string[i];
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
const char16_t next = string[i + 1];
char16_t next = string[i + 1];
if (IsTrailSurrogate(next)) {
i += 1;
const char32_t cp = 0x10000
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, const si
return ret;
}
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b) {
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& 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, const uint32_t index) {
int64_t GeneralUtils::SetBit(int64_t value, uint32_t index) {
return value |= 1ULL << index;
}
//! Clears a specific bit in a signed 64-bit integer
int64_t GeneralUtils::ClearBit(int64_t value, const uint32_t index) {
int64_t GeneralUtils::ClearBit(int64_t value, uint32_t index) {
return value &= ~(1ULL << index);
}
//! Checks a specific bit in a signed 64-bit integer
bool GeneralUtils::CheckBit(int64_t value, const uint32_t index) {
bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
return value & (1ULL << index);
}
bool GeneralUtils::ReplaceInString(std::string& str, const std::string_view from, const std::string_view to) {
const size_t start_pos = str.find(from);
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
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(const std::wstring_view str, const wchar_t delimiter) {
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
std::vector<std::wstring> vector = std::vector<std::wstring>();
std::wstring current;
for (const wchar_t c : str) {
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = L"";
@@ -237,15 +237,15 @@ std::vector<std::wstring> GeneralUtils::SplitString(const std::wstring_view str,
}
}
vector.push_back(std::move(current));
vector.push_back(current);
return vector;
}
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view str, const char16_t delimiter) {
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str, char16_t delimiter) {
std::vector<std::u16string> vector = std::vector<std::u16string>();
std::u16string current;
for (const char16_t c : str) {
for (const auto& c : str) {
if (c == delimiter) {
vector.push_back(current);
current = u"";
@@ -254,15 +254,17 @@ std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view
}
}
vector.push_back(std::move(current));
vector.push_back(current);
return vector;
}
std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, const char delimiter) {
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
std::vector<std::string> vector = std::vector<std::string>();
std::string current = "";
for (const char c : str) {
for (size_t i = 0; i < str.length(); i++) {
char c = str[i];
if (c == delimiter) {
vector.push_back(current);
current = "";
@@ -271,7 +273,8 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, c
}
}
vector.push_back(std::move(current));
vector.push_back(current);
return vector;
}
@@ -280,7 +283,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
inStream.Read<uint32_t>(length);
std::u16string string;
for (uint32_t i = 0; i < length; ++i) {
for (auto i = 0; i < length; i++) {
uint16_t c;
inStream.Read(c);
string.push_back(c);
@@ -289,35 +292,35 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
return string;
}
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string_view folder) {
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& 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 (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));
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));
}
// Now sort the map by the oldest migration.
std::vector<std::string> sortedFiles{};
auto fileIterator = filenames.cbegin();
auto oldest = filenames.cbegin();
auto fileIterator = filenames.begin();
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
while (!filenames.empty()) {
if (fileIterator == filenames.cend()) {
if (fileIterator == filenames.end()) {
sortedFiles.push_back(oldest->second);
filenames.erase(oldest);
fileIterator = filenames.cbegin();
oldest = filenames.cbegin();
fileIterator = filenames.begin();
oldest = filenames.begin();
continue;
}
if (oldest->first > fileIterator->first) oldest = fileIterator;
++fileIterator;
fileIterator++;
}
return sortedFiles;
}
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
#ifdef DARKFLAME_PLATFORM_MACOS
// MacOS floating-point parse function specializations
namespace GeneralUtils::details {

View File

@@ -3,18 +3,17 @@
// C++
#include <charconv>
#include <cstdint>
#include <ctime>
#include <functional>
#include <optional>
#include <random>
#include <span>
#include <stdexcept>
#include <ctime>
#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"
@@ -33,31 +32,29 @@ 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 SIZE_MAX (No trimming)
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string ASCIIToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
//! 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 SIZE_MAX (No trimming)
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string UTF8ToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
namespace details {
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
}
//! 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 SIZE_MAX (No trimming)
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string_view string, const size_t size = SIZE_MAX);
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
/**
* Compares two basic strings but does so ignoring case sensitivity
@@ -65,7 +62,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_view a, const std::string_view b);
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
// MARK: Bits
@@ -73,9 +70,9 @@ namespace GeneralUtils {
//! Sets a bit on a numerical value
template <typename T>
inline void SetBit(T& value, const eObjectBits bits) {
inline void SetBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
const auto index = static_cast<size_t>(bits);
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8) - 1) {
return;
}
@@ -85,9 +82,9 @@ namespace GeneralUtils {
//! Clears a bit on a numerical value
template <typename T>
inline void ClearBit(T& value, const eObjectBits bits) {
inline void ClearBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
const auto index = static_cast<size_t>(bits);
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8 - 1)) {
return;
}
@@ -100,14 +97,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, const uint32_t index);
int64_t SetBit(int64_t value, 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, const uint32_t index);
int64_t ClearBit(int64_t value, uint32_t index);
//! Checks a specific bit in a signed 64-bit integer
/*!
@@ -115,19 +112,19 @@ namespace GeneralUtils {
\param index The index of the bit
\return Whether or not the bit is set
*/
bool CheckBit(int64_t value, const uint32_t index);
bool CheckBit(int64_t value, uint32_t index);
bool ReplaceInString(std::string& str, const std::string_view from, const std::string_view to);
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
std::u16string ReadWString(RakNet::BitStream& inStream);
std::vector<std::wstring> SplitString(const std::wstring_view str, const wchar_t delimiter);
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string_view str, const char16_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
std::vector<std::string> SplitString(const std::string_view str, const char delimiter);
std::vector<std::string> SplitString(const std::string& str, char delimiter);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
// Concept constraining to enum types
template <typename T>
@@ -147,7 +144,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 = uint8_t; };
struct numeric_parse<T> { using type = uint32_t; };
// Shorthand type alias
template <Numeric T>
@@ -159,9 +156,8 @@ 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(std::string_view str) {
[[nodiscard]] std::optional<T> TryParse(const 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);
@@ -170,7 +166,7 @@ namespace GeneralUtils {
return isParsed ? static_cast<T>(result) : std::optional<T>{};
}
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
#ifdef DARKFLAME_PLATFORM_MACOS
// MacOS floating-point parse helper function specializations
namespace details {
@@ -185,10 +181,8 @@ 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(std::string_view str) noexcept
[[nodiscard]] std::optional<T> TryParse(const 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;
@@ -208,7 +202,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_view strX, const std::string_view strY, const std::string_view strZ) {
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
const auto x = TryParse<float>(strX);
if (!x) return std::nullopt;
@@ -220,17 +214,17 @@ namespace GeneralUtils {
}
/**
* 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
* 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
* @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::span<const std::string> str) {
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
}
template <typename T>
std::u16string to_u16string(const T value) {
std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
@@ -249,7 +243,7 @@ namespace GeneralUtils {
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(const std::size_t min, const std::size_t max) {
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
@@ -276,10 +270,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("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
Log::Warn("Attempted to process invalid ldf type ({:s}) from string ({:s})", ldfTypeAndValue.first, format);
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("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid int32 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid float value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid double value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid uint32 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid bool value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid uint64 value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid LWOOBJID value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
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("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
Log::Warn("Attempted to process invalid unknown value ({:s}) from string ({:s})", ldfTypeAndValue.second, format);
break;
}
default: {
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
Log::Warn("Attempted to process invalid LDF type ({:d}) from string ({:s})", GeneralUtils::ToUnderlying(type), format);
break;
}
}

View File

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

View File

@@ -1,6 +1,14 @@
#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>
@@ -15,22 +23,88 @@
// 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) {
char nextChar = *path++;
if (nextChar == '/' || nextChar == '\\') {
file = path;
}
}
return file;
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)...);
}
}
// 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_DEBUG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->LogDebug(str, message, ##__VA_ARGS__); } while(0)
//#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__)
// 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("Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
Log::Info("Loaded pack catalog with {:d} pack files and {:d} 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>
const std::string_view ToString(const T e) {
constexpr std::string_view ToString(const T e) {
static_assert(std::is_enum_v<T>, "Not an enum"); // Check type
constexpr auto& sv = magic_enum::enum_entries<T>();
constexpr const auto& sv = magic_enum::enum_entries<T>();
const auto it = std::lower_bound(
sv.begin(), sv.end(), e,

View File

@@ -0,0 +1,31 @@
#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,9 +72,7 @@ enum class eChatMessageType :uint32_t {
UPDATE_DONATION,
PRG_CSR_COMMAND,
HEARTBEAT_REQUEST_FROM_WORLD,
UPDATE_FREE_TRIAL_STATUS,
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
CREATE_TEAM,
UPDATE_FREE_TRIAL_STATUS
};
#endif //!__ECHATMESSAGETYPE__H__

View File

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

View File

@@ -790,10 +790,9 @@ enum class eGameMessageType : uint16_t {
GET_MISSION_TYPE_STATES = 853,
GET_TIME_PLAYED = 854,
SET_MISSION_VIEWED = 855,
HKX_VEHICLE_LOADED = 856,
SLASH_COMMAND_TEXT_FEEDBACK = 857,
SLASH_COMMAND_TEXT_FEEDBACK = 856,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 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

@@ -1,59 +0,0 @@
#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, // AllowList word check
STRING_CHECK, // AllowList string check
WORD_CHECK, // Whitelist word check
STRING_CHECK, // Whitelist string check
GET_PLAYERS_IN_ZONE,
REQUEST_UGC_MANIFEST_INFO,
BLUEPRINT_GET_ALL_DATA_REQUEST,

View File

@@ -25,7 +25,6 @@
#include "CDScriptComponentTable.h"
#include "CDSkillBehaviorTable.h"
#include "CDZoneTableTable.h"
#include "CDTamingBuildPuzzleTable.h"
#include "CDVendorComponentTable.h"
#include "CDActivitiesTable.h"
#include "CDPackageComponentTable.h"
@@ -42,6 +41,8 @@
#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.
@@ -54,6 +55,13 @@
#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.
@@ -100,14 +108,11 @@ 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 std::runtime_error{ "CDClientDatabase is not connected!" };
}
if (!CDClientDatabase::isConnected) throw CDClientConnectionException();
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
CDActivitiesTable::Instance().LoadValuesFromDatabase();
@@ -147,13 +152,12 @@ 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("Loading default CDClient tables!");
Log::Info("Loading default CDClient tables!");
CDPetComponentTable::Instance().LoadValuesFromDefaults();
}

View File

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

View File

@@ -1,35 +0,0 @@
#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

@@ -1,60 +0,0 @@
#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,6 +36,5 @@ 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 sqlite3)
target_link_libraries(dDatabaseCDClient PRIVATE fmt sqlite3)
if (${CDCLIENT_CACHE_ALL})
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})

View File

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

View File

@@ -16,6 +16,7 @@ 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("Tried to connect to database when it's already connected!");
Log::Warn("Tried to connect to database when it's already connected!");
return;
}
@@ -23,7 +23,7 @@ void Database::Connect() {
GameDatabase* Database::Get() {
if (!database) {
LOG("Tried to get database when it's not connected!");
Log::Warn("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("Trying to destroy database when it's not connected!");
Log::Warn("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("SQL Error: %s", ex.what()); throw; } } while(0)
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { Log::Warn("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("Destroying MySQL connection!");
else LOG("Destroying MySQL connection from %s!", source.c_str());
if (source.empty()) Log::Info("Destroying MySQL connection!");
else Log::Info("Destroying MySQL connection from {:s}!", source);
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("Trying to reconnect to MySQL");
Log::Info("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("Trying to reconnect to MySQL from invalid or closed connection");
Log::Info("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("%s", param.data());
// Log::Info("{}", param);
stmt->setString(index, param.data());
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
// LOG("%s", param);
// Log::Info("{}", param);
stmt->setString(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
// LOG("%s", param.c_str());
stmt->setString(index, param.c_str());
// Log::Info("{}", param);
stmt->setString(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
// LOG("%u", param);
// Log::Info("{}", param);
stmt->setByte(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
// LOG("%d", param);
// Log::Info("{}", param);
stmt->setByte(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
// LOG("%u", param);
// Log::Info("{}", param);
stmt->setShort(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
// LOG("%d", param);
// Log::Info("{}", param);
stmt->setShort(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
// LOG("%u", param);
// Log::Info("{}", param);
stmt->setUInt(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
// LOG("%d", param);
// Log::Info("{}", param);
stmt->setInt(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
// LOG("%llu", param);
// Log::Info("{}", param);
stmt->setInt64(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
// LOG("%llu", param);
// Log::Info("{}", param);
stmt->setUInt64(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
// LOG("%f", param);
// Log::Info({}", param);
stmt->setFloat(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
// LOG("%f", param);
// Log::Info("{}", param);
stmt->setDouble(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
// LOG("%d", param);
// Log::Info("{}", param);
stmt->setBoolean(index, param);
}
template<>
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
// LOG("Blob");
// Log::Info("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("%d", param.value());
// Log::Info("{}", param.value());
stmt->setInt(index, param.value());
} else {
// LOG("Null");
// Log::Info("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 (sql::SQLException& e) {
LOG("Error inserting new property model: %s", e.what());
} catch (const sql::SQLException& e) {
Log::Warn("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("Running migration: %s", migration.name.c_str());
Log::Info("Running migration: {:s}", migration.name);
if (migration.name == "dlu/5_brick_model_sd0.sql") {
runSd0Migrations = true;
} else {
@@ -56,7 +56,7 @@ void MigrationRunner::RunMigrations() {
}
if (finalSQL.empty() && !runSd0Migrations) {
LOG("Server database is up to date.");
Log::Info("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("Encountered error running migration: %s", e.what());
Log::Info("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("%i models were updated from zlib to sd0.", numberOfUpdatedModels);
Log::Info("{:d} models were updated from zlib to sd0.", numberOfUpdatedModels);
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
LOG("%i models were truncated from the database.", numberOfTruncatedModels);
Log::Info("{:d} 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("Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str());
Log::Info("Executing migration: {:s}. This may take a while. Do not shut down server.", migration.name);
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("Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage());
Log::Warn("Encountered error running DML command: ({:d}) : {:s}", e.errorCode(), e.errorMessage());
}
}
@@ -129,5 +129,5 @@ void MigrationRunner::RunSQLiteMigrations() {
CDClientDatabase::ExecuteQuery("COMMIT;");
}
LOG("CDServer database is up to date.");
Log::Info("CDServer database is up to date.");
}

View File

@@ -27,9 +27,12 @@ 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;
}
@@ -52,6 +55,8 @@ 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();
@@ -65,23 +70,28 @@ void Character::UpdateInfoFromDatabase() {
}
void Character::UpdateFromDatabase() {
if (m_Doc) delete m_Doc;
UpdateInfoFromDatabase();
}
void Character::DoQuickXMLDataParse() {
if (m_XMLData.size() == 0) return;
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);
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);
} else {
LOG("Failed to load xmlData!");
Log::Warn("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("Failed to find mf tag!");
Log::Warn("Failed to find mf tag!");
return;
}
@@ -98,16 +108,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("Char has no inv!");
Log::Warn("Char has no inv!");
return;
}
tinyxml2::XMLElement* bag = inv->FirstChildElement("items")->FirstChildElement("in");
if (!bag) {
LOG("Couldn't find bag0!");
Log::Warn("Couldn't find bag0!");
return;
}
@@ -131,7 +141,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;
@@ -195,7 +205,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) {
@@ -229,10 +239,12 @@ 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);
@@ -254,11 +266,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);
@@ -268,15 +280,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.
@@ -289,7 +301,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);
}
@@ -298,7 +310,7 @@ void Character::SaveXMLToDatabase() {
//Call upon the entity to update our xmlDoc:
if (!m_OurEntity) {
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
Log::Warn("{:d}:{:s} didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName());
return;
}
@@ -309,12 +321,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("%i:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count());
Log::Info("{:d}:{:s} Saved character to Database in: {:f}s", this->GetID(), this->GetName(), 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();
@@ -322,7 +334,7 @@ void Character::SetIsNewLogin() {
auto* nextChild = currentChild->NextSiblingElement();
if (currentChild->Attribute("si")) {
flags->DeleteChild(currentChild);
LOG("Removed isLoggedIn flag from character %i:%s, saving character to database", GetID(), GetName().c_str());
Log::Info("Removed isLoggedIn flag from character {:d}:{:s}, saving character to database", GetID(), GetName());
WriteToDatabase();
}
currentChild = nextChild;
@@ -332,7 +344,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());
@@ -409,15 +421,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);
@@ -431,7 +443,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; }
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
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("Deleted player");
Log::Info("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("Unable to find player to remove from manager.");
Log::Warn("Unable to find player to remove from manager.");
return;
}
@@ -476,7 +476,8 @@ void Entity::Initialize() {
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
AddComponent<InventoryComponent>();
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr;
AddComponent<InventoryComponent>(xmlDoc);
}
// 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) {
@@ -730,21 +731,15 @@ 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 (path->pathType == PathType::Movement) {
auto movementAIcomponent = GetComponent<MovementAIComponent>();
if (movementAIcomponent && combatAiId == 0) {
movementAIcomponent->SetPath(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 {
MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = "";
moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
AddComponent<MovementAIComponent>(moveInfo);
// TODO: create movementAIcomp and set path
}
}
}*/
} 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);
@@ -1243,7 +1238,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.
@@ -1634,8 +1629,10 @@ 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(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID());
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("Attempting to kill null entity %llu", toKill);
Log::Warn("Attempting to kill null entity {}", toKill);
continue;
}
@@ -231,7 +231,7 @@ void EntityManager::DeleteEntities() {
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
} else {
LOG("Attempted to delete non-existent entity %llu", toDelete);
Log::Warn("Attempted to delete non-existent entity {}", 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("Attempted to construct null entity");
Log::Warn("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.c_str());
Log::Debug("query is {:s}", baseLookup);
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 %i %i %i", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
Log::Debug("Query is {:s} vars are {:d} {:d} {:d}", 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("Unknown leaderboard type %i for game %i. Cannot save score!", leaderboardType, activityId);
Log::Warn("Unknown leaderboard type {:d} for game {:d}. Cannot save score!", GeneralUtils::ToUnderlying(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("save query %s %i %i", saveQuery.c_str(), playerID, activityId);
Log::Info("save query {:s} {:d} {:d}", saveQuery, 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("Accepted from A (%d), B: (%d)", value, m_AcceptedB);
Log::Info("Accepted from A ({}), B: ({})", 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("Accepted from B (%d), A: (%d)", value, m_AcceptedA);
Log::Info("Accepted from B ({}), A: ({})", 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("Possible coin trade cheating attempt! Aborting trade.");
Log::Warn("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("Possible cheating attempt from %s in trading!!! Aborting trade", characterA->GetName().c_str());
Log::Warn("Possible cheating attempt from {:s} in trading!!! Aborting trade", characterA->GetName());
return;
}
} else {
LOG("Possible cheating attempt from %s in trading due to item not being available!!!", characterA->GetName().c_str());
Log::Warn("Possible cheating attempt from {:s} in trading due to item not being available!!!", characterA->GetName());
return;
}
}
@@ -146,11 +146,11 @@ void Trade::Complete() {
auto* itemToRemove = inventoryB->FindItemById(tradeItem.itemId);
if (itemToRemove) {
if (itemToRemove->GetCount() < tradeItem.itemCount) {
LOG("Possible cheating attempt from %s in trading!!! Aborting trade", characterB->GetName().c_str());
Log::Warn("Possible cheating attempt from {:s} in trading!!! Aborting trade", characterB->GetName());
return;
}
} else {
LOG("Possible cheating attempt from %s in trading due to item not being available!!! Aborting trade", characterB->GetName().c_str());
Log::Warn("Possible cheating attempt from {:s} in trading due to item not being available!!! Aborting trade", characterB->GetName());
return;
}
}
@@ -194,7 +194,7 @@ void Trade::SendUpdateToOther(LWOOBJID participant) {
uint64_t coins;
std::vector<TradeItem> itemIds;
LOG("Attempting to send trade update");
Log::Info("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("Sending trade update");
Log::Info("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("Created new trade between (%llu) <-> (%llu)", participantA, participantB);
Log::Info("Created new trade between ({}) <-> ({})", 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("Loaded %i as it is the last used char", lastUsedCharacterId);
Log::Info("Loaded {:d} as it is the last used char", lastUsedCharacterId);
}
}
}
@@ -106,7 +106,7 @@ void User::UserOutOfSync() {
m_AmountOfTimesOutOfSync++;
if (m_AmountOfTimesOutOfSync > m_MaxDesyncAllowed) {
//YEET
LOG("User %s was out of sync %i times out of %i, disconnecting for suspected speedhacking.", m_Username.c_str(), m_AmountOfTimesOutOfSync, m_MaxDesyncAllowed);
Log::Warn("User {:s} was out of sync {:d} times out of {:d}, disconnecting for suspected speedhacking.", m_Username, 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 "eChatMessageType.h"
#include "eChatInternalMessageType.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("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string().c_str());
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string());
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("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string().c_str());
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string());
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("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string().c_str());
Log::Warn("Failed to load {:s}", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string());
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("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.");
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.");
}
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("Deleted user %i", user->GetAccountID());
Log::Info("Deleted user {:d}", 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("AccountID: %i chose unavailable name: %s", u->GetAccountID(), name.c_str());
Log::Info("AccountID: {:d} chose unavailable name: {:s}", u->GetAccountID(), name);
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::CUSTOM_NAME_IN_USE);
return;
}
if (Database::Get()->GetCharacterInfo(predefinedName)) {
LOG("AccountID: %i chose unavailable predefined name: %s", u->GetAccountID(), predefinedName.c_str());
Log::Info("AccountID: {:d} chose unavailable predefined name: {:s}", u->GetAccountID(), predefinedName);
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::PREDEFINED_NAME_IN_USE);
return;
}
if (name.empty()) {
LOG("AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
Log::Info("AccountID: {:d} is creating a character with predefined name: {:s}", u->GetAccountID(), predefinedName);
} else {
LOG("AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
Log::Info("AccountID: {:d} is creating a character with name: {:s} (temporary: {:s})", u->GetAccountID(), name, predefinedName);
}
//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("Character object id unavailable, check object_id_tracker!");
Log::Warn("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("Couldn't get user to delete character");
Log::Warn("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("Received char delete req for ID: %llu (%u)", objectID, charID);
Log::Info("Received char delete req for ID: {:d} ({:d})", 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("Deleting character %i", charID);
Log::Info("Deleting character {:d}", charID);
Database::Get()->DeleteCharacter(charID);
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
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("Couldn't get user to delete character");
Log::Warn("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("Received char rename request for ID: %llu (%u)", objectID, charID);
Log::Info("Received char rename request for ID: {:d} ({:d})", 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("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
Log::Info("Character {:s} now known as {:s}", character->GetName(), newName);
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
UserManager::RequestCharacterList(sysAddr);
} else {
Database::Get()->SetPendingCharacterName(charID, newName);
LOG("Character %s has been renamed to %s and is pending approval by a moderator.", character->GetName().c_str(), newName.c_str());
Log::Info("Character {:s} has been renamed to {:s} and is pending approval by a moderator.", character->GetName(), newName);
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("Unknown error occurred when renaming character, either hasCharacter or character variable != true.");
Log::Warn("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("Couldn't get user to log in character");
Log::Warn("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("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);
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);
if (character) {
character->SetZoneID(zoneID);
character->SetZoneInstance(zoneInstance);
@@ -529,24 +529,24 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
return;
});
} else {
LOG("Unknown error occurred when logging in a character, either hasCharacter or character variable != true.");
Log::Warn("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 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 == ?"
"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 == ?"
);
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("objectId", 4069);
auto shirtLOT = tableData.getIntField(0, 4069);
tableData.finalize();
return shirtLOT;
} catch (const std::exception& ex) {
LOG("Could not look up shirt %i %i: %s", shirtColor, shirtStyle, ex.what());
Log::Warn("Could not look up shirt {:d} {:d}: {: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 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 == ?"
"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 == ?"
);
stmt.bind(1, "cc pants");
stmt.bind(2, static_cast<int>(pantsColor));
auto tableData = stmt.execQuery();
auto pantsLOT = tableData.getIntField("objectId", 2508);
auto pantsLOT = tableData.getIntField(0, 2508);
tableData.finalize();
return pantsLOT;
} catch (const std::exception& ex) {
LOG("Could not look up pants %i: %s", pantsColor, ex.what());
Log::Warn("Could not look up pants {:d}: {: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("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -26,14 +26,14 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bitS
uint32_t behaviorId{};
if (!bitStream.Read(behaviorId)) {
LOG("Unable to read behaviorId from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read behaviorId from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
return;
}
LWOOBJID target{};
if (!bitStream.Read(target)) {
LOG("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", 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("Unable to read targetCount from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read targetCount from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
}
@@ -28,7 +28,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream& b
}
if (targetCount > this->m_maxTargets) {
LOG("Serialized size is greater than max targets! Size: %i, Max: %i", targetCount, this->m_maxTargets);
Log::Warn("Serialized size is greater than max targets! Size: {:d}, Max: {:d}", 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("failed to read in target %i from bitStream, aborting target Handle!", i);
Log::Warn("failed to read in target {:d} 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("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", 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 %i", allocatedBits);
Log::Debug("Number of allocated bits {:d}", 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("Target targetEntity %llu not found.", branch.target);
Log::Warn("Target targetEntity {:d} not found.", branch.target);
return;
}
auto* destroyableComponent = targetEntity->GetComponent<DestroyableComponent>();
if (!destroyableComponent) {
LOG("No destroyable found on the obj/lot %llu/%i", branch.target, targetEntity->GetLOT());
Log::Warn("No destroyable found on the obj/lot {:d}/{:d}", branch.target, targetEntity->GetLOT());
return;
}
@@ -63,7 +63,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
bool isSuccess{};
if (!bitStream.Read(isBlocked)) {
LOG("Unable to read isBlocked");
Log::Warn("Unable to read isBlocked");
return;
}
@@ -75,31 +75,31 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
}
if (!bitStream.Read(isImmune)) {
LOG("Unable to read isImmune");
Log::Warn("Unable to read isImmune");
return;
}
if (isImmune) {
LOG_DEBUG("Target targetEntity %llu is immune!", branch.target);
Log::Debug("Target targetEntity {} is immune!", branch.target);
this->m_OnFailImmune->Handle(context, bitStream, branch);
return;
}
if (!bitStream.Read(isSuccess)) {
LOG("failed to read success from bitstream");
Log::Warn("failed to read success from bitstream");
return;
}
if (isSuccess) {
uint32_t armorDamageDealt{};
if (!bitStream.Read(armorDamageDealt)) {
LOG("Unable to read armorDamageDealt");
Log::Warn("Unable to read armorDamageDealt");
return;
}
uint32_t healthDamageDealt{};
if (!bitStream.Read(healthDamageDealt)) {
LOG("Unable to read healthDamageDealt");
Log::Warn("Unable to read healthDamageDealt");
return;
}
@@ -112,7 +112,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
bool died{};
if (!bitStream.Read(died)) {
LOG("Unable to read died");
Log::Warn("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("Unable to read success state");
Log::Warn("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("Unknown success state (%i)!", successState);
Log::Warn("Unknown success state ({})!", 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("Target entity %llu is null!", branch.target);
Log::Warn("Target entity {} is null!", branch.target);
return;
}
auto* destroyableComponent = targetEntity->GetComponent<DestroyableComponent>();
if (!destroyableComponent || !destroyableComponent->GetParent()) {
LOG("No destroyable component on %llu", branch.target);
Log::Warn("No destroyable component on {}", branch.target);
return;
}
@@ -191,7 +191,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
bitStream.Write(isImmune);
if (isImmune) {
LOG_DEBUG("Target targetEntity %llu is immune!", branch.target);
Log::Debug("Target targetEntity {} 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 == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_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("Unknown success state (%i)!", successState);
Log::Warn("Unknown success state ({})!", GeneralUtils::ToUnderlying(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 "BehaviorTemplate.h"
#include "BehaviorTemplates.h"
#include "BehaviorBranchContext.h"
#include <unordered_map>
@@ -110,183 +110,183 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
Behavior* behavior = nullptr;
switch (templateId) {
case BehaviorTemplate::EMPTY: break;
case BehaviorTemplate::BASIC_ATTACK:
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId);
break;
case BehaviorTemplate::TAC_ARC:
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
behavior = new TacArcBehavior(behaviorId);
break;
case BehaviorTemplate::AND:
case BehaviorTemplates::BEHAVIOR_AND:
behavior = new AndBehavior(behaviorId);
break;
case BehaviorTemplate::PROJECTILE_ATTACK:
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
behavior = new ProjectileAttackBehavior(behaviorId);
break;
case BehaviorTemplate::HEAL:
case BehaviorTemplates::BEHAVIOR_HEAL:
behavior = new HealBehavior(behaviorId);
break;
case BehaviorTemplate::MOVEMENT_SWITCH:
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
behavior = new MovementSwitchBehavior(behaviorId);
break;
case BehaviorTemplate::AREA_OF_EFFECT:
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
behavior = new AreaOfEffectBehavior(behaviorId);
break;
case BehaviorTemplate::PLAY_EFFECT:
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
behavior = new PlayEffectBehavior(behaviorId);
break;
case BehaviorTemplate::IMMUNITY:
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
behavior = new ImmunityBehavior(behaviorId);
break;
case BehaviorTemplate::DAMAGE_BUFF: break;
case BehaviorTemplate::DAMAGE_ABSORBTION:
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
behavior = new DamageAbsorptionBehavior(behaviorId);
break;
case BehaviorTemplate::OVER_TIME:
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
behavior = new OverTimeBehavior(behaviorId);
break;
case BehaviorTemplate::IMAGINATION:
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
behavior = new ImaginationBehavior(behaviorId);
break;
case BehaviorTemplate::TARGET_CASTER:
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
behavior = new TargetCasterBehavior(behaviorId);
break;
case BehaviorTemplate::STUN:
case BehaviorTemplates::BEHAVIOR_STUN:
behavior = new StunBehavior(behaviorId);
break;
case BehaviorTemplate::DURATION:
case BehaviorTemplates::BEHAVIOR_DURATION:
behavior = new DurationBehavior(behaviorId);
break;
case BehaviorTemplate::KNOCKBACK:
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
behavior = new KnockbackBehavior(behaviorId);
break;
case BehaviorTemplate::ATTACK_DELAY:
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
behavior = new AttackDelayBehavior(behaviorId);
break;
case BehaviorTemplate::CAR_BOOST:
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
behavior = new CarBoostBehavior(behaviorId);
break;
case BehaviorTemplate::FALL_SPEED:
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
behavior = new FallSpeedBehavior(behaviorId);
break;
case BehaviorTemplate::SHIELD: break;
case BehaviorTemplate::REPAIR_ARMOR:
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
behavior = new RepairBehavior(behaviorId);
break;
case BehaviorTemplate::SPEED:
case BehaviorTemplates::BEHAVIOR_SPEED:
behavior = new SpeedBehavior(behaviorId);
break;
case BehaviorTemplate::DARK_INSPIRATION:
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId);
break;
case BehaviorTemplate::LOOT_BUFF:
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
behavior = new LootBuffBehavior(behaviorId);
break;
case BehaviorTemplate::VENTURE_VISION:
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION:
behavior = new VentureVisionBehavior(behaviorId);
break;
case BehaviorTemplate::SPAWN_OBJECT:
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplate::LAY_BRICK: break;
case BehaviorTemplate::SWITCH:
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
case BehaviorTemplates::BEHAVIOR_SWITCH:
behavior = new SwitchBehavior(behaviorId);
break;
case BehaviorTemplate::BUFF:
case BehaviorTemplates::BEHAVIOR_BUFF:
behavior = new BuffBehavior(behaviorId);
break;
case BehaviorTemplate::JETPACK:
case BehaviorTemplates::BEHAVIOR_JETPACK:
behavior = new JetPackBehavior(behaviorId);
break;
case BehaviorTemplate::SKILL_EVENT:
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId);
break;
case BehaviorTemplate::CONSUME_ITEM:
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM:
behavior = new ConsumeItemBehavior(behaviorId);
break;
case BehaviorTemplate::SKILL_CAST_FAILED:
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId);
break;
case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
case BehaviorTemplate::CHANGE_IDLE_FLAGS:
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS:
behavior = new ChangeIdleFlagsBehavior(behaviorId);
break;
case BehaviorTemplate::APPLY_BUFF:
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
behavior = new ApplyBuffBehavior(behaviorId);
break;
case BehaviorTemplate::CHAIN:
case BehaviorTemplates::BEHAVIOR_CHAIN:
behavior = new ChainBehavior(behaviorId);
break;
case BehaviorTemplate::CHANGE_ORIENTATION:
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
behavior = new ChangeOrientationBehavior(behaviorId);
break;
case BehaviorTemplate::FORCE_MOVEMENT:
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
behavior = new ForceMovementBehavior(behaviorId);
break;
case BehaviorTemplate::INTERRUPT:
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
behavior = new InterruptBehavior(behaviorId);
break;
case BehaviorTemplate::ALTER_COOLDOWN: break;
case BehaviorTemplate::CHARGE_UP:
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
behavior = new ChargeUpBehavior(behaviorId);
break;
case BehaviorTemplate::SWITCH_MULTIPLE:
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
behavior = new SwitchMultipleBehavior(behaviorId);
break;
case BehaviorTemplate::START:
case BehaviorTemplates::BEHAVIOR_START:
behavior = new StartBehavior(behaviorId);
break;
case BehaviorTemplate::END:
case BehaviorTemplates::BEHAVIOR_END:
behavior = new EndBehavior(behaviorId);
break;
case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
case BehaviorTemplate::CAMERA: break;
case BehaviorTemplate::REMOVE_BUFF:
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF:
behavior = new RemoveBuffBehavior(behaviorId);
break;
case BehaviorTemplate::GRAB: break;
case BehaviorTemplate::MODULAR_BUILD: break;
case BehaviorTemplate::NPC_COMBAT_SKILL:
case BehaviorTemplates::BEHAVIOR_GRAB: break;
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
behavior = new NpcCombatSkillBehavior(behaviorId);
break;
case BehaviorTemplate::BLOCK:
case BehaviorTemplates::BEHAVIOR_BLOCK:
behavior = new BlockBehavior(behaviorId);
break;
case BehaviorTemplate::VERIFY:
case BehaviorTemplates::BEHAVIOR_VERIFY:
behavior = new VerifyBehavior(behaviorId);
break;
case BehaviorTemplate::TAUNT:
case BehaviorTemplates::BEHAVIOR_TAUNT:
behavior = new TauntBehavior(behaviorId);
break;
case BehaviorTemplate::AIR_MOVEMENT:
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
behavior = new AirMovementBehavior(behaviorId);
break;
case BehaviorTemplate::SPAWN_QUICKBUILD:
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplate::PULL_TO_POINT:
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
behavior = new PullToPointBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_ROTATE: break;
case BehaviorTemplate::DAMAGE_REDUCTION:
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
behavior = new DamageReductionBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_TELEPORT:
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT:
behavior = new PropertyTeleportBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
behavior = new ClearTargetBehavior(behaviorId);
break;
case BehaviorTemplate::TAKE_PICTURE: break;
case BehaviorTemplate::MOUNT: break;
case BehaviorTemplate::SKILL_SET: break;
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
default:
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
//Log::Warn("Failed to load behavior with invalid template id ({:d})!", templateId);
break;
}
if (behavior == nullptr) {
//LOG("Failed to load unimplemented template id (%i)!", templateId);
//Log::Warn("Failed to load unimplemented template id ({:d})!", templateId);
behavior = new EmptyBehavior(behaviorId);
}
@@ -296,20 +296,20 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
return behavior;
}
BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_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<BehaviorTemplate>(templateEntry.templateID);
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID);
}
}
if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
LOG("Failed to load behavior template with id (%i)!", behaviorId);
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
Log::Warn("Failed to load behavior template with id ({:d})!", behaviorId);
}
return templateID;
@@ -335,22 +335,26 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
const auto itr = m_effectNames.find(typeString);
if (m_effectNames == nullptr) {
m_effectNames = new std::unordered_map<std::string, std::string>();
} else {
const auto pair = m_effectNames->find(typeString);
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(m_effectType);
}
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
}
if (itr != m_effectNames.end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true);
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);
return;
}
renderComponent->PlayEffect(effectId, type, itr->second, secondary);
return;
}
// The SQlite result object becomes invalid if the query object leaves scope.
@@ -377,19 +381,19 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
return;
}
const auto name = std::string(result.getStringField("effectName"));
const auto name = std::string(result.getStringField(0));
if (type.empty()) {
const auto typeResult = result.getStringField("effectType");
const auto typeResult = result.getStringField(1);
type = GeneralUtils::ASCIIToUTF16(typeResult);
m_effectType = typeResult;
m_effectType = new std::string(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);
@@ -419,24 +423,26 @@ Behavior::Behavior(const uint32_t behaviorId) {
if (behaviorId == 0) {
this->m_effectId = 0;
this->m_templateId = BehaviorTemplate::EMPTY;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
}
// Make sure we do not proceed if we are trying to load an invalid behavior
if (templateInDatabase.behaviorID == 0) {
LOG("Failed to load behavior with id (%i)!", behaviorId);
Log::Warn("Failed to load behavior with id ({:d})!", behaviorId);
this->m_effectId = 0;
this->m_templateId = BehaviorTemplate::EMPTY;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
return;
}
this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID);
this->m_effectId = templateInDatabase.effectID;
this->m_effectHandle = *templateInDatabase.effectHandle;
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
}
@@ -501,3 +507,9 @@ 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 "BehaviorTemplate.h"
#include "BehaviorTemplates.h"
#include "dCommonVars.h"
struct BehaviorContext;
@@ -26,7 +26,7 @@ public:
static Behavior* CreateBehavior(uint32_t behaviorId);
static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
/*
* Utilities
@@ -39,11 +39,11 @@ public:
*/
uint32_t m_behaviorId;
BehaviorTemplate m_templateId;
BehaviorTemplates m_templateId;
uint32_t m_effectId;
std::string m_effectHandle;
std::unordered_map<std::string, std::string> m_effectNames;
std::string m_effectType;
std::string* m_effectHandle = nullptr;
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
std::string* m_effectType = nullptr;
/*
* Behavior parameters
@@ -88,11 +88,5 @@ public:
*/
explicit Behavior(uint32_t behaviorId);
virtual ~Behavior() = default;
Behavior(const Behavior& other) = default;
Behavior(Behavior&& other) = default;
Behavior& operator=(const Behavior& other) = default;
Behavior& operator=(Behavior&& other) = default;
virtual ~Behavior();
};

View File

@@ -31,7 +31,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const {
auto* entity = Game::entityManager->GetEntity(this->originator);
if (entity == nullptr) {
LOG("Invalid entity for (%llu)!", this->originator);
Log::Warn("Invalid entity for ({})!", this->originator);
return 0;
}
@@ -39,7 +39,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const {
auto* component = entity->GetComponent<SkillComponent>();
if (component == nullptr) {
LOG("No skill component attached to (%llu)!", this->originator);;
Log::Warn("No skill component attached to ({})!", this->originator);;
return 0;
}
@@ -126,7 +126,7 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
}
if (!found) {
LOG("Failed to find behavior sync entry with sync id (%i)!", syncId);
Log::Warn("Failed to find behavior sync entry with sync id ({})!", 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("Invalid behavior for sync id (%i)!", syncId);
Log::Warn("Invalid behavior for sync id ({})!", 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 (%llu)!", this->originator);
Log::Debug("Invalid caster for ({})!", this->originator);
targets.clear();
return;
}

View File

@@ -1,70 +0,0 @@
#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

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

View File

@@ -0,0 +1,70 @@
#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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", branch.target);
return;
}
@@ -43,7 +43,7 @@ void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branc
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
LOG("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", 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("Invalid target (%llu)!", target);
Log::Warn("Invalid target ({})!", target);
return;
}
@@ -21,7 +21,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream
auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) {
LOG("Invalid target, no destroyable component (%llu)!", target);
Log::Warn("Invalid target, no destroyable component ({})!", target);
return;
}
@@ -47,7 +47,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
LOG("Invalid target (%llu)!", target);
Log::Warn("Invalid target ({})!", target);
return;
}
@@ -55,7 +55,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
auto* component = entity->GetComponent<DestroyableComponent>();
if (component == nullptr) {
LOG("Invalid target, no destroyable component (%llu)!", target);
Log::Warn("Invalid target, no destroyable component ({})!", target);
return;
}

View File

@@ -7,6 +7,7 @@ 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("Activating car boost!");
Log::Info("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("Tracking car boost!");
Log::Info("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("Unable to read chainIndex from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read chainIndex from bitStream, aborting Handle! {:d}", 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("chainIndex out of bounds, aborting handle of chain %i bits unread %i", chainIndex, bitStream.GetNumberOfUnreadBits());
Log::Warn("chainIndex out of bounds, aborting handle of chain {:d} bits unread {:d}", 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("Unable to read handle from bitStream, aborting Handle! variable_type");
Log::Warn("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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", branch.target);
return;
}
@@ -37,7 +37,7 @@ void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchCon
auto* target = Game::entityManager->GetEntity(second);
if (target == nullptr) {
LOG("Failed to find target (%llu)!", second);
Log::Warn("Failed to find target ({})!", 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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", branch.target);
return;
}
@@ -35,7 +35,7 @@ void DamageReductionBehavior::Timer(BehaviorContext* context, BehaviorBranchCont
auto* target = Game::entityManager->GetEntity(second);
if (target == nullptr) {
LOG("Failed to find target (%llu)!", second);
Log::Warn("Failed to find target ({})!", 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 == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
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) {
return;
}
uint32_t handle{};
if (!bitStream.Read(handle)) {
LOG("Unable to read handle from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read handle from bitStream, aborting Handle! {:d}", 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("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", bitStream.GetNumberOfUnreadBits());
return;
}
LWOOBJID target{};
if (!bitStream.Read(target)) {
LOG("Unable to read target from bitStream, aborting Sync! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read target from bitStream, aborting Sync! {:d}", 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 == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
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) {
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("Failed to find entity for (%llu)!", branch.target);
Log::Warn("Failed to find entity for ({})!", 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("Failed to find destroyable component for %(llu)!", branch.target);
Log::Warn("Failed to find destroyable component for ({})!", 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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", branch.target);
return;
}
@@ -59,7 +59,7 @@ void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext bra
auto* target = Game::entityManager->GetEntity(second);
if (!target) {
LOG("Failed to find target (%llu)!", second);
Log::Warn("Failed to find target ({})!", second);
return;
}

View File

@@ -8,50 +8,36 @@
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (branch.target != context->originator) {
bool unknown = false;
if (usedTarget != context->originator) {
bool isTargetImmuneStuns = false;
if (!bitStream.Read(isTargetImmuneStuns)) {
LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown1 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
if (isTargetImmuneStuns) return;
if (unknown) return;
}
if (!this->m_interruptBlock) {
bool isBlockingInterrupts = false;
if (!bitStream.Read(isBlockingInterrupts)) {
LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
bool unknown = false;
if (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown2 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
if (isBlockingInterrupts) return;
if (unknown) return;
}
bool hasInterruptedStatusEffects = false;
if (!bitStream.Read(hasInterruptedStatusEffects)) {
LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (this->m_target) // Guess...
{
bool unknown = false;
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 (!bitStream.Read(unknown)) {
Log::Warn("Unable to read unknown3 from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
}
if (branch.target == context->originator) return;
@@ -69,8 +55,7 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (usedTarget != context->originator) {
if (branch.target != 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("Unable to read unknown from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read unknown from bitStream, aborting Handle! {:d}", 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 == 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) {
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) {
return;
}
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read movementType from bitStream, aborting Handle! {:d}", 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 == BehaviorTemplate::EMPTY) {
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_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("Unable to read target from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read target from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
auto* entity = Game::entityManager->GetEntity(context->originator);
if (entity == nullptr) {
LOG("Failed to find originator (%llu)!", context->originator);
Log::Warn("Failed to find originator ({:d})!", context->originator);
return;
}
@@ -27,7 +27,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent == nullptr) {
LOG("Failed to find skill component for (%llu)!", -context->originator);
Log::Warn("Failed to find skill component for ({:d})!", -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("Unable to read targetPosition from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read targetPosition from bitStream, aborting Handle! {:d}", bitStream.GetNumberOfUnreadBits());
return;
};
}
@@ -46,7 +46,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
LWOOBJID projectileId{};
if (!bitStream.Read(projectileId)) {
LOG("Unable to read projectileId from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read projectileId from bitStream, aborting Handle! {:d}", 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("Failed to find originator (%llu)!", context->originator);
Log::Warn("Failed to find originator ({})!", context->originator);
return;
}
@@ -72,7 +72,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent == nullptr) {
LOG("Failed to find skill component for (%llu)!", context->originator);
Log::Warn("Failed to find skill component for ({})!", 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("Invalid projectile target (%llu)!", branch.target);
Log::Warn("Invalid projectile target ({})!", 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("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);
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);
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("Failed to find entity for (%llu)!", branch.target);
Log::Warn("Failed to find entity for ({})!", 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("Failed to find destroyable component for %(llu)!", branch.target);
Log::Warn("Failed to find destroyable component for ({})!", branch.target);
return;
}

View File

@@ -9,16 +9,17 @@ 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.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
if (caster != nullptr && target != nullptr && this->m_effectHandle != 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.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
if (caster != nullptr && target != nullptr && this->m_effectHandle != 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("Failed to find self entity (%llu)!", context->originator);
Log::Warn("Failed to find self entity ({})!", context->originator);
return;
}
@@ -45,7 +45,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
);
if (entity == nullptr) {
LOG("Failed to spawn entity (%i)!", this->m_lot);
Log::Warn("Failed to spawn entity ({})!", 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("Failed to find spawned entity (%llu)!", second);
Log::Warn("Failed to find spawned entity ({})!", second);
return;
}

View File

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

View File

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

View File

@@ -14,8 +14,6 @@ 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("Unable to read value from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read value from bitStream, aborting Handle! {}", 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("behavior"));
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));
auto* behavior = CreateBehavior(behavior_id);
auto value = result.getFloatField("value");
auto value = result.getFloatField(2);
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("target %llu is null", branch.target);
if (!target) Log::Warn("target {} 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("Unable to read hasTargets from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read hasTargets from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
return;
};
@@ -37,7 +37,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
bool blocked = false;
if (!bitStream.Read(blocked)) {
LOG("Unable to read blocked from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read blocked from bitStream, aborting Handle! {}", 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("Unable to read count from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read count from bitStream, aborting Handle! {}", bitStream.GetNumberOfUnreadBits());
return;
};
if (count > m_maxTargets) {
LOG("Bitstream has too many targets Max:%i Recv:%i", this->m_maxTargets, count);
Log::Warn("Bitstream has too many targets Max:{} Recv:{}", this->m_maxTargets, count);
return;
}
@@ -63,7 +63,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
LWOOBJID id{};
if (!bitStream.Read(id)) {
LOG("Unable to read id from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
Log::Warn("Unable to read id from bitStream, aborting Handle! {}", 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("Bitstream has LWOOBJID_EMPTY as a target!");
Log::Warn("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("Invalid self for (%llu)!", context->originator);
Log::Warn("Invalid self for ({})!", 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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", 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("Failed to find target (%llu)!", branch.target);
Log::Warn("Failed to find target ({})!", 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("Invalid self for (%llu)", context->originator);
Log::Warn("Invalid self for ({})", context->originator);
return;
}

View File

@@ -21,7 +21,7 @@
#include "eMissionTaskType.h"
#include "eMatchUpdate.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.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("Setting up instance.");
Log::Info("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, eChatMessageType::CREATE_TEAM);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM);
bitStream.Write(leader->GetObjectID());
bitStream.Write(m_Participants.size());
@@ -524,7 +524,7 @@ void ActivityInstance::StartZone() {
if (player == nullptr)
return;
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);
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);
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("aggroRadius"))
m_AggroRadius = componentResult.getFloatField("aggroRadius");
if (!componentResult.fieldIsNull(0))
m_AggroRadius = componentResult.getFloatField(0);
if (!componentResult.fieldIsNull("tetherSpeed"))
m_TetherSpeed = componentResult.getFloatField("tetherSpeed");
if (!componentResult.fieldIsNull(1))
m_TetherSpeed = componentResult.getFloatField(1);
if (!componentResult.fieldIsNull("pursuitSpeed"))
m_PursuitSpeed = componentResult.getFloatField("pursuitSpeed");
if (!componentResult.fieldIsNull(2))
m_PursuitSpeed = componentResult.getFloatField(2);
if (!componentResult.fieldIsNull("softTetherRadius"))
m_SoftTetherRadius = componentResult.getFloatField("softTetherRadius");
if (!componentResult.fieldIsNull(3))
m_SoftTetherRadius = componentResult.getFloatField(3);
if (!componentResult.fieldIsNull("hardTetherRadius"))
m_HardTetherRadius = componentResult.getFloatField("hardTetherRadius");
if (!componentResult.fieldIsNull(4))
m_HardTetherRadius = componentResult.getFloatField(4);
}
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("skillID"));
const auto skillId = static_cast<uint32_t>(result.getIntField(0));
const auto abilityCooldown = static_cast<float>(result.getFloatField("cooldown"));
const auto abilityCooldown = static_cast<float>(result.getFloatField(1));
const auto behaviorId = static_cast<uint32_t>(result.getIntField("behaviorID"));
const auto behaviorId = static_cast<uint32_t>(result.getIntField(2));
auto* behavior = Behavior::CreateBehavior(behaviorId);
@@ -150,18 +150,19 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
//Process enter events
for (const auto id : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(id);
for (auto en : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(en->GetObjectID());
}
//Process exit events
for (const auto id : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(id);
for (auto en : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
}
// 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)
@@ -539,7 +540,7 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
auto* entity = Game::entityManager->GetEntity(target);
if (entity == nullptr) {
LOG("Invalid entity for checking validity (%llu)!", target);
Log::Warn("Invalid entity for checking validity ({})!", target);
return false;
}
@@ -553,7 +554,7 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
auto* referenceDestroyable = m_Parent->GetComponent<DestroyableComponent>();
if (referenceDestroyable == nullptr) {
LOG("Invalid reference destroyable component on (%llu)!", m_Parent->GetObjectID());
Log::Warn("Invalid reference destroyable component on ({})!", m_Parent->GetObjectID());
return false;
}

View File

@@ -81,13 +81,13 @@ void BouncerComponent::LookupPetSwitch() {
Game::entityManager->SerializeEntity(m_Parent);
LOG("Loaded pet bouncer");
Log::Info("Loaded pet bouncer");
}
}
}
if (!m_PetSwitchLoaded) {
LOG("Failed to load pet bouncer");
Log::Warn("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.c_str());
Log::Debug("No fx name for {:s}", buffname);
}
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 %i", fxToPlay.c_str(), buff.effectId);
Log::Debug("Playing {:s} {:d}", fxToPlay, 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.c_str());
Log::Debug("Stopping {:s}", fxToPlay);
GameMessages::SendStopFXEffect(m_Parent, false, fxToPlay);
}
@@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
return m_Parent;
}
void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
void BuffComponent::LoadFromXml(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(const 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("StringValue")) {
if (!result.fieldIsNull(3)) {
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("Failed to parse value (%s): (%s)!", token.c_str(), exception.what());
Log::Warn("Failed to parse value ({:s}): ({:s})!", token, exception.what());
}
}
}

View File

@@ -57,9 +57,9 @@ public:
Entity* GetParent() const;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void LoadFromXml(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("Using PropertyPlaque");
Log::Info("Using PropertyPlaque");
}
auto* inventoryComponent = originator->GetComponent<InventoryComponent>();
@@ -41,7 +41,7 @@ void BuildBorderComponent::OnUse(Entity* originator) {
inventoryComponent->PushEquippedItems();
LOG("Starting with %llu", buildArea);
Log::Info("Starting with {}", buildArea);
if (PropertyManagementComponent::Instance() != nullptr) {
GameMessages::SendStartArrangingWithItem(

View File

@@ -186,11 +186,11 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel;
}
void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while loading XML!");
Log::Warn("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(const 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("Failed to find mf tag while updating XML!");
Log::Warn("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("Failed to find char tag while updating XML!");
Log::Warn("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("Time since last save: %d", newUpdateTimestamp - m_LastUpdateTimestamp);
Log::Warn("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("Unable to find rocket to equip!");
Log::Warn("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 %i", rewardCode);
Log::Debug("Processing RewardCode {:d}", 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