From 66edf57b025196b31fc89906f3cc616f827ecb0f Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Jul 2022 15:27:20 -0700 Subject: [PATCH 01/18] Wait for world to shutdown (#624) We need to wait for the message that the world has shutdown before shutting it down. --- dMasterServer/MasterServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index ac49b1a1..94e0d5b6 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -303,7 +303,6 @@ int main(int argc, char** argv) { if (affirmTimeout == 1000) { instance->Shutdown(); - instance->SetShutdownComplete(true); Game::im->RedirectPendingRequests(instance); } From 325dc5a5711fbd5bbff66024820fb392d9e0a599 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Jul 2022 15:57:45 -0700 Subject: [PATCH 02/18] Revert "Wait for world to shutdown (#624)" (#626) This reverts commit 66edf57b025196b31fc89906f3cc616f827ecb0f. --- dMasterServer/MasterServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 94e0d5b6..ac49b1a1 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -303,6 +303,7 @@ int main(int argc, char** argv) { if (affirmTimeout == 1000) { instance->Shutdown(); + instance->SetShutdownComplete(true); Game::im->RedirectPendingRequests(instance); } From 06217ad5e30981a3e8b94093dca2c0bbc4d28b80 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 10 Jul 2022 17:59:07 -0700 Subject: [PATCH 03/18] Address friends list IDs and removal of friends (#628) * Add friends list migration * Change friends to use charID Update friends table to use charID and not LWOOBJID variant. * Fix remove friend Fix remove friend and make the query more readable at a glance. * Add and remove friends in the container Properly add and remove friends in the player container --- dChatServer/ChatPacketHandler.cpp | 145 +++++++++++--------- migrations/dlu/4_friends_list_objectids.sql | 1 + 2 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 migrations/dlu/4_friends_list_objectids.sql diff --git a/dChatServer/ChatPacketHandler.cpp b/dChatServer/ChatPacketHandler.cpp index 899fd355..82f24ffa 100644 --- a/dChatServer/ChatPacketHandler.cpp +++ b/dChatServer/ChatPacketHandler.cpp @@ -21,10 +21,17 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { auto player = playerContainer.GetPlayerData(playerID); if (!player) return; - //Get our friends list from the Db: - auto stmt = Database::CreatePreppedStmt("SELECT * FROM friends WHERE player_id = ? OR friend_id = ?"); - stmt->setUInt64(1, playerID); - stmt->setUInt64(2, playerID); + //Get our friends list from the Db. Using a derived table since the friend of a player can be in either column. + auto stmt = Database::CreatePreppedStmt( + "SELECT fr.requested_player, best_friend, ci.name FROM " + "(SELECT CASE " + "WHEN player_id = ? THEN friend_id " + "WHEN friend_id = ? THEN player_id " + "END AS requested_player, best_friend FROM friends) AS fr " + "JOIN charinfo AS ci ON ci.id = fr.requested_player " + "WHERE fr.requested_player IS NOT NULL;"); + stmt->setUInt(1, static_cast(playerID)); + stmt->setUInt(2, static_cast(playerID)); std::vector friends; @@ -32,27 +39,16 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { while (res->next()) { FriendData fd; fd.isFTP = false; // not a thing in DLU - fd.friendID = res->getInt64(1); - if (fd.friendID == playerID) fd.friendID = res->getUInt64(2); + fd.friendID = res->getUInt(1); + GeneralUtils::SetBit(fd.friendID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); + GeneralUtils::SetBit(fd.friendID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); - fd.isBestFriend = res->getInt(3) == 2; //0 = friends, 1 = requested, 2 = bffs - - //We need to find their name as well: - { - auto stmt = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE id=? limit 1"); - stmt->setInt(1, fd.friendID); - - auto res = stmt->executeQuery(); - while (res->next()) { - fd.friendName = res->getString(1); - } - - delete res; - delete stmt; - } + fd.isBestFriend = res->getInt(2) == 2; //0 = friends, 1 = requested, 2 = bffs + fd.friendName = res->getString(3); //Now check if they're online: auto fr = playerContainer.GetPlayerData(fd.friendID); + Game::logger->Log("ChatPacketHandler", "friend is %llu\n", fd.friendID); if (fr) { fd.isOnline = true; fd.zoneID = fr->zoneID; @@ -69,7 +65,9 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { } delete res; + res = nullptr; delete stmt; + stmt = nullptr; //Now, we need to send the friendlist to the server they came from: CBITSTREAM; @@ -100,8 +98,6 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) { std::string playerName = PacketUtils::ReadString(0x14, packet, true); //There's another bool here to determine if it's a best friend request, but we're not handling it right now. - //PacketUtils::SavePacket("FriendRequest.bin", (char*)inStream.GetData(), inStream.GetNumberOfBytesUsed()); - //We need to check to see if the player is actually online or not: auto targetData = playerContainer.GetPlayerData(playerName); if (targetData) { @@ -118,23 +114,46 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) { uint8_t responseCode = packet->data[0x14]; std::string friendName = PacketUtils::ReadString(0x15, packet, true); - Game::logger->Log("ChatPacketHandler", "Friend response code: %i\n", responseCode); - - if (responseCode != 0) return; //If we're not accepting the request, end here, do not insert to friends table. - - PacketUtils::SavePacket("HandleFriendResponse.bin", (char*)inStream.GetData(), inStream.GetNumberOfBytesUsed()); - //Now to try and find both of these: auto goonA = playerContainer.GetPlayerData(playerID); auto goonB = playerContainer.GetPlayerData(friendName); if (!goonA || !goonB) return; + if (responseCode != 0) return; //If we're not accepting the request, end here, do not insert to friends table. + + for (auto friendData : goonA->friends) { + if (friendData.friendID == goonB->playerID) return; + } + + for (auto friendData : goonB->friends) { + if (friendData.friendID == goonA->playerID) return; + } + + // Add the goons to their friends list + FriendData goonAData; + goonAData.zoneID = goonA->zoneID; + goonAData.friendID = goonA->playerID; + goonAData.friendName = goonA->playerName; + goonAData.isBestFriend = false; + goonAData.isFTP = false; + goonAData.isOnline = true; + goonB->friends.push_back(goonAData); + + FriendData goonBData; + goonBData.zoneID = goonB->zoneID; + goonBData.friendID = goonB->playerID; + goonBData.friendName = goonB->playerName; + goonBData.isBestFriend = false; + goonBData.isFTP = false; + goonBData.isOnline = true; + goonA->friends.push_back(goonBData); + SendFriendResponse(goonB, goonA, responseCode); SendFriendResponse(goonA, goonB, responseCode); //Do we need to send it to both? I think so so both get the updated friendlist but... idk. - auto stmt = Database::CreatePreppedStmt("INSERT INTO `friends`(`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?)"); - stmt->setUInt64(1, goonA->playerID); - stmt->setUInt64(2, goonB->playerID); + auto stmt = Database::CreatePreppedStmt("INSERT IGNORE INTO `friends` (`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?)"); + stmt->setUInt(1, static_cast(goonA->playerID)); + stmt->setUInt(2, static_cast(goonB->playerID)); stmt->setInt(3, 0); stmt->execute(); delete stmt; @@ -145,50 +164,61 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) { LWOOBJID playerID; inStream.Read(playerID); inStream.Read(playerID); - std::string friendName = PacketUtils::ReadString(16, packet, true); + std::string friendName = PacketUtils::ReadString(0x14, packet, true); //we'll have to query the db here to find the user, since you can delete them while they're offline. //First, we need to find their ID: - auto stmt = Database::CreatePreppedStmt("select id from charinfo where name=? limit 1;"); + auto stmt = Database::CreatePreppedStmt("SELECT id FROM charinfo WHERE name=? LIMIT 1;"); stmt->setString(1, friendName.c_str()); LWOOBJID friendID = 0; auto res = stmt->executeQuery(); while (res->next()) { - friendID = res->getUInt64(1); + friendID = res->getUInt(1); } + // Convert friendID to LWOOBJID + GeneralUtils::SetBit(friendID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); + GeneralUtils::SetBit(friendID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); + delete res; + res = nullptr; delete stmt; + stmt = nullptr; - //Set our bits to convert to the BIG BOY objectID. - friendID = GeneralUtils::ClearBit(friendID, OBJECT_BIT_CHARACTER); - friendID = GeneralUtils::ClearBit(friendID, OBJECT_BIT_PERSISTENT); - - //YEET: - auto deletestmt = Database::CreatePreppedStmt("DELETE FROM `friends` WHERE player_id=? AND friend_id=? LIMIT 1"); - deletestmt->setUInt64(1, playerID); - deletestmt->setUInt64(2, friendID); + auto deletestmt = Database::CreatePreppedStmt("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"); + deletestmt->setUInt(1, static_cast(playerID)); + deletestmt->setUInt(2, static_cast(friendID)); + deletestmt->setUInt(3, static_cast(friendID)); + deletestmt->setUInt(4, static_cast(playerID)); deletestmt->execute(); - delete deletestmt; - //because I'm lazy and they can be reversed: - { - auto deletestmt = Database::CreatePreppedStmt("DELETE FROM `friends` WHERE player_id=? AND friend_id=? LIMIT 1"); - deletestmt->setUInt64(1, friendID); - deletestmt->setUInt64(2, playerID); - deletestmt->execute(); - delete deletestmt; - } + delete deletestmt; + deletestmt = nullptr; //Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended: auto goonA = playerContainer.GetPlayerData(playerID); if (goonA) { + // Remove the friend from our list of friends + for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) { + if ((*friendData).friendID == friendID) { + goonA->friends.erase(friendData); + break; + } + } SendRemoveFriend(goonA, friendName, true); } - + auto goonB = playerContainer.GetPlayerData(friendID); if (!goonB) return; + // Do it again for other person + for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) { + if ((*friendData).friendID == playerID) { + goonB->friends.erase(friendData); + break; + } + } + std::string goonAName = GeneralUtils::UTF16ToWTF8(playerContainer.GetName(playerID)); SendRemoveFriend(goonB, goonAName, true); } @@ -217,8 +247,6 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s\n", senderName.c_str(), channel, message.c_str()); - //PacketUtils::SavePacket("chat.bin", reinterpret_cast(packet->data), packet->length); - if (channel != 8) return; auto* team = playerContainer.GetTeam(playerID); @@ -454,8 +482,6 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) playerContainer.RemoveMember(team, kickedId, false, true, false); } - - //PacketUtils::SavePacket("kick.bin", reinterpret_cast(packet->data), packet->length); } void ChatPacketHandler::HandleTeamPromote(Packet* packet) @@ -481,8 +507,6 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) playerContainer.PromoteMember(team, promoted->playerID); } - - //PacketUtils::SavePacket("promote.bin", reinterpret_cast(packet->data), packet->length); } void ChatPacketHandler::HandleTeamLootOption(Packet* packet) @@ -509,8 +533,6 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet) playerContainer.UpdateTeamsOnWorld(team, false); } - - //PacketUtils::SavePacket("option.bin", reinterpret_cast(packet->data), packet->length); } void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) @@ -560,7 +582,6 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) const auto memberName = playerContainer.GetName(memberId); - //ChatPacketHandler::SendTeamAddPlayer(otherMember, false, false, false, data->playerID, leaderName, data->zoneID); if (otherMember != nullptr) { ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID); diff --git a/migrations/dlu/4_friends_list_objectids.sql b/migrations/dlu/4_friends_list_objectids.sql new file mode 100644 index 00000000..efb3a7ae --- /dev/null +++ b/migrations/dlu/4_friends_list_objectids.sql @@ -0,0 +1 @@ +UPDATE friends SET player_id = player_id % 0x100000000, friend_id = friend_id % 0x100000000; \ No newline at end of file From d642de9462127a10bd83885610adebd34f9c69ec Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Sun, 10 Jul 2022 20:40:26 +0100 Subject: [PATCH 04/18] Implement a migration runner --- CMakeLists.txt | 17 ++++- README.md | 2 +- dCommon/GeneralUtils.cpp | 50 +++++++++++++++ dCommon/GeneralUtils.h | 2 + dDatabase/Database.cpp | 45 +++++++------ dDatabase/Database.h | 11 +++- dDatabase/MigrationRunner.cpp | 78 +++++++++++++++++++++++ dDatabase/MigrationRunner.h | 19 ++++++ dMasterServer/MasterServer.cpp | 8 +++ migrations/cdserver/3_plunger_gun_fix.sql | 1 - migrations/dlu/2_reporter_id.sql | 2 +- 11 files changed, 208 insertions(+), 27 deletions(-) create mode 100644 dDatabase/MigrationRunner.cpp create mode 100644 dDatabase/MigrationRunner.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cf311d2..5373dfe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.14) project(Darkflame) include(CTest) +set (CMAKE_CXX_STANDARD 17) + # Read variables from file FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables) @@ -88,8 +90,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}") # Echo the version message(STATUS "Version: ${PROJECT_VERSION}") -set(CMAKE_CXX_STANDARD 17) - if(WIN32) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif(WIN32) @@ -138,6 +138,19 @@ configure_file("${CMAKE_SOURCE_DIR}/vanity/INFO.md" "${CMAKE_BINARY_DIR}/vanity/ configure_file("${CMAKE_SOURCE_DIR}/vanity/TESTAMENT.md" "${CMAKE_BINARY_DIR}/vanity/TESTAMENT.md" COPYONLY) configure_file("${CMAKE_SOURCE_DIR}/vanity/NPC.xml" "${CMAKE_BINARY_DIR}/vanity/NPC.xml" COPYONLY) +# Move our migrations for MasterServer to run +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/) +file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql) +foreach (file ${SQL_FILES}) + get_filename_component(file ${file} NAME) + if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/${file}) + configure_file( + ${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/${file} + COPYONLY + ) + endif() +endforeach() + # 3rdparty includes include_directories(${PROJECT_SOURCE_DIR}/thirdparty/raknet/Source/) if(APPLE) diff --git a/README.md b/README.md index 6b82e1b0..d029ed93 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ Darkflame Universe utilizes a MySQL/MariaDB database for account and character i Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running. * Create a database for Darkflame Universe to use -* Run each SQL file in the order at which they appear [here](migrations/dlu/) on the database +* Run the migrations by running `./MasterServer -m` to automatically run them ### Resources diff --git a/dCommon/GeneralUtils.cpp b/dCommon/GeneralUtils.cpp index b3461e8a..01306226 100644 --- a/dCommon/GeneralUtils.cpp +++ b/dCommon/GeneralUtils.cpp @@ -188,3 +188,53 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) { return string; } + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +std::vector GeneralUtils::GetFileNamesFromFolder(const std::string& folder) +{ + std::vector names; + std::string search_path = folder + "/*.*"; + WIN32_FIND_DATA fd; + HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + do { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + names.push_back(fd.cFileName); + } + } while (::FindNextFile(hFind, &fd)); + ::FindClose(hFind); + } + return names; +} +#else +#include +#include +#include +#include +#include +#include + +std::vector GeneralUtils::GetFileNamesFromFolder(const std::string& folder) { + std::vector names; + struct dirent* entry; + DIR* dir = opendir(folder.c_str()); + if (dir == NULL) { + return names; + } + + while ((entry = readdir(dir)) != NULL) { + std::string value(entry->d_name, strlen(entry->d_name)); + if (value == "." || value == "..") { + continue; + } + names.push_back(value); + } + + closedir(dir); + + return names; +} +#endif \ No newline at end of file diff --git a/dCommon/GeneralUtils.h b/dCommon/GeneralUtils.h index 58b9e962..4973201e 100644 --- a/dCommon/GeneralUtils.h +++ b/dCommon/GeneralUtils.h @@ -128,6 +128,8 @@ namespace GeneralUtils { std::vector SplitString(const std::string& str, char delimiter); + std::vector GetFileNamesFromFolder(const std::string& folder); + template T Parse(const char* value); diff --git a/dDatabase/Database.cpp b/dDatabase/Database.cpp index ef4faa52..26a45359 100644 --- a/dDatabase/Database.cpp +++ b/dDatabase/Database.cpp @@ -8,6 +8,8 @@ using namespace std; sql::Driver * Database::driver; sql::Connection * Database::con; +sql::Properties Database::props; +std::string Database::database; void Database::Connect(const string& host, const string& database, const string& username, const string& password) { @@ -25,14 +27,26 @@ void Database::Connect(const string& host, const string& database, const string& properties["user"] = szUsername; properties["password"] = szPassword; properties["autoReconnect"] = "true"; - con = driver->connect(properties); - con->setSchema(szDatabase); -} //Connect -void Database::Destroy(std::string source) { + Database::props = properties; + Database::database = database; + + Database::Connect(); +} + +void Database::Connect() { + con = driver->connect(Database::props); + con->setSchema(Database::database); +} + +void Database::Destroy(std::string source, bool log) { if (!con) return; - if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str()); - else Game::logger->Log("Database", "Destroying MySQL connection!\n"); + + if (log) { + if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str()); + else Game::logger->Log("Database", "Destroying MySQL connection!\n"); + } + con->close(); delete con; } //Destroy @@ -48,13 +62,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) { sql::SQLString str(test, size); if (!con) { - //Connect to the MySQL Database - std::string mysql_host = Game::config->GetValue("mysql_host"); - std::string mysql_database = Game::config->GetValue("mysql_database"); - std::string mysql_username = Game::config->GetValue("mysql_username"); - std::string mysql_password = Game::config->GetValue("mysql_password"); - - Connect(mysql_host, mysql_database, mysql_username, mysql_password); + Connect(); Game::logger->Log("Database", "Trying to reconnect to MySQL\n"); } @@ -64,13 +72,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) { con = nullptr; - //Connect to the MySQL Database - std::string mysql_host = Game::config->GetValue("mysql_host"); - std::string mysql_database = Game::config->GetValue("mysql_database"); - std::string mysql_username = Game::config->GetValue("mysql_username"); - std::string mysql_password = Game::config->GetValue("mysql_password"); - - Connect(mysql_host, mysql_database, mysql_username, mysql_password); + Connect(); Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection\n"); } @@ -79,3 +81,6 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) { return stmt; } //CreatePreppedStmt +void Database::Commit() { + Database::con->commit(); +} \ No newline at end of file diff --git a/dDatabase/Database.h b/dDatabase/Database.h index e972b0ca..ece62a95 100644 --- a/dDatabase/Database.h +++ b/dDatabase/Database.h @@ -13,10 +13,17 @@ class Database { private: static sql::Driver *driver; static sql::Connection *con; - + static sql::Properties props; + static std::string database; public: static void Connect(const std::string& host, const std::string& database, const std::string& username, const std::string& password); - static void Destroy(std::string source=""); + static void Connect(); + static void Destroy(std::string source = "", bool log = true); + static sql::Statement* CreateStmt(); static sql::PreparedStatement* CreatePreppedStmt(const std::string& query); + static void Commit(); + + static std::string GetDatabase() { return database; } + static sql::Properties GetProperties() { return props; } }; diff --git a/dDatabase/MigrationRunner.cpp b/dDatabase/MigrationRunner.cpp new file mode 100644 index 00000000..a058b85e --- /dev/null +++ b/dDatabase/MigrationRunner.cpp @@ -0,0 +1,78 @@ +#include "MigrationRunner.h" + +#include "GeneralUtils.h" + +#include +#include +#include + +void MigrationRunner::RunMigrations() { + auto stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());"); + stmt->executeQuery(); + delete stmt; + + sql::SQLString finalSQL = ""; + Migration checkMigration{}; + + for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) { + auto migration = LoadMigration(entry); + + if (migration.data.empty()) { + continue; + } + + checkMigration = migration; + + stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;"); + stmt->setString(1, migration.name); + auto res = stmt->executeQuery(); + bool doExit = res->next(); + delete res; + delete stmt; + if (doExit) continue; + + Game::logger->Log("MigrationRunner", "Running migration: " + migration.name + "\n"); + + finalSQL.append(migration.data); + finalSQL.append('\n'); + + stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);"); + stmt->setString(1, entry); + stmt->execute(); + delete stmt; + } + + if (!finalSQL.empty()) { + try { + auto simpleStatement = Database::CreateStmt(); + simpleStatement->execute(finalSQL); + delete simpleStatement; + } + catch (sql::SQLException e) { + Game::logger->Log("MigrationRunner", std::string("Encountered error running migration: ") + e.what() + "\n"); + } + } +} + +Migration MigrationRunner::LoadMigration(std::string path) { + Migration migration{}; + std::ifstream file("./migrations/" + path); + + if (file.is_open()) { + std::hash hash; + + std::string line; + std::string total = ""; + + while (std::getline(file, line)) { + total += line; + } + + file.close(); + + migration.name = path; + migration.data = total; + } + + return migration; +} diff --git a/dDatabase/MigrationRunner.h b/dDatabase/MigrationRunner.h new file mode 100644 index 00000000..343b252d --- /dev/null +++ b/dDatabase/MigrationRunner.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Database.h" + +#include "dCommonVars.h" +#include "Game.h" +#include "dCommonVars.h" +#include "dLogger.h" + +struct Migration { + std::string data; + std::string name; +}; + +class MigrationRunner { +public: + static void RunMigrations(); + static Migration LoadMigration(std::string path); +}; \ No newline at end of file diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index ac49b1a1..1cfd7d4a 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -19,6 +19,7 @@ #include "CDClientDatabase.h" #include "CDClientManager.h" #include "Database.h" +#include "MigrationRunner.h" #include "Diagnostics.h" #include "dCommonVars.h" #include "dConfig.h" @@ -127,6 +128,13 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } + if (argc > 1 && (strcmp(argv[1], "-m") == 0 || strcmp(argv[1], "--migrations") == 0)) { + MigrationRunner::RunMigrations(); + Game::logger->Log("MigrationRunner", "Finished running migrations\n"); + + return EXIT_SUCCESS; + } + //If the first command line argument is -a or --account then make the user //input a username and password, with the password being hidden. if (argc > 1 && diff --git a/migrations/cdserver/3_plunger_gun_fix.sql b/migrations/cdserver/3_plunger_gun_fix.sql index 35654e8b..3d33592e 100644 --- a/migrations/cdserver/3_plunger_gun_fix.sql +++ b/migrations/cdserver/3_plunger_gun_fix.sql @@ -1,2 +1 @@ --- File added April 9th, 2022 UPDATE ItemComponent SET itemType = 5 where id = 7082; diff --git a/migrations/dlu/2_reporter_id.sql b/migrations/dlu/2_reporter_id.sql index 26103342..dc2a9a7e 100644 --- a/migrations/dlu/2_reporter_id.sql +++ b/migrations/dlu/2_reporter_id.sql @@ -1 +1 @@ -ALTER TABLE bug_reports ADD reporter_id INT NOT NULL DEFAULT 0; +ALTER TABLE bug_reports ADD (reporter_id) INT NOT NULL DEFAULT 0; From bfa1f57158f7b16f73f3cdf3702610fe5b7eff93 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Tue, 12 Jul 2022 03:06:54 +0100 Subject: [PATCH 05/18] Improve cpplinq checks On certain Windows header versions defining NOMINMAX doesn't work for some odd reason. --- thirdparty/cpplinq/cpplinq.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thirdparty/cpplinq/cpplinq.hpp b/thirdparty/cpplinq/cpplinq.hpp index d25cde85..ae9169d9 100644 --- a/thirdparty/cpplinq/cpplinq.hpp +++ b/thirdparty/cpplinq/cpplinq.hpp @@ -14,6 +14,8 @@ #ifndef CPPLINQ__HEADER_GUARD # define CPPLINQ__HEADER_GUARD +#undef min +#undef max #define NOMINMAX // ---------------------------------------------------------------------------- From b7497a47e4c0aa6b3605f6b09706a7e06f62d428 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 11 Jul 2022 20:43:09 -0700 Subject: [PATCH 06/18] Lower memory usage of Behavior Parameter Table by 10MB (#627) * Added caching for table Added caching for table Add more caching Update MasterServer.cpp grds Update CDBehaviorParameterTable.cpp Update CDBehaviorParameterTable.h Update CDBehaviorTemplateTable.cpp Update Behavior.cpp Update Behavior.cpp change to map Remove redundant query * Remove include * change to enum * Update Behavior.cpp * Use already cached table * Update Behavior.cpp * Reduce memory usage Reduces the memory usage for the BehaviorParameter table by 10MB in memory. * Update CDBehaviorTemplateTable.cpp --- dDatabase/Tables/CDBehaviorParameterTable.cpp | 16 +++++++++++----- dDatabase/Tables/CDBehaviorParameterTable.h | 6 +++--- dDatabase/Tables/CDBehaviorTemplateTable.cpp | 11 +++++++++-- dDatabase/Tables/CDBehaviorTemplateTable.h | 10 ++++++---- dGame/dBehaviors/Behavior.cpp | 2 +- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/dDatabase/Tables/CDBehaviorParameterTable.cpp b/dDatabase/Tables/CDBehaviorParameterTable.cpp index bbbdb2b6..05f39016 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.cpp +++ b/dDatabase/Tables/CDBehaviorParameterTable.cpp @@ -9,14 +9,20 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) { hash = 0; CDBehaviorParameter entry; entry.behaviorID = tableData.getIntField(0, -1); - entry.parameterID = tableData.getStringField(1, ""); + auto candidateStringToAdd = std::string(tableData.getStringField(1, "")); + auto parameter = m_ParametersList.find(candidateStringToAdd); + if (parameter != m_ParametersList.end()) { + entry.parameterID = parameter; + } else { + entry.parameterID = m_ParametersList.insert(candidateStringToAdd).first; + } entry.value = tableData.getFloatField(2, -1.0f); GeneralUtils::hash_combine(hash, entry.behaviorID); - GeneralUtils::hash_combine(hash, entry.parameterID); + GeneralUtils::hash_combine(hash, *entry.parameterID); auto it = m_Entries.find(entry.behaviorID); - m_ParametersList.insert(entry.parameterID); + m_ParametersList.insert(*entry.parameterID); m_Entries.insert(std::make_pair(hash, entry)); tableData.nextRow(); @@ -36,7 +42,7 @@ CDBehaviorParameter CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID { CDBehaviorParameter returnValue; returnValue.behaviorID = 0; - returnValue.parameterID = ""; + returnValue.parameterID = m_ParametersList.end(); returnValue.value = defaultValue; size_t hash = 0; @@ -57,7 +63,7 @@ std::map CDBehaviorParameterTable::GetParametersByBehaviorID GeneralUtils::hash_combine(hash, parameterCandidate); auto infoCandidate = m_Entries.find(hash); if (infoCandidate != m_Entries.end()) { - returnInfo.insert(std::make_pair(infoCandidate->second.parameterID, infoCandidate->second.value)); + returnInfo.insert(std::make_pair(*(infoCandidate->second.parameterID), infoCandidate->second.value)); } } return returnInfo; diff --git a/dDatabase/Tables/CDBehaviorParameterTable.h b/dDatabase/Tables/CDBehaviorParameterTable.h index 17605636..c45d287b 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.h +++ b/dDatabase/Tables/CDBehaviorParameterTable.h @@ -12,9 +12,9 @@ //! BehaviorParameter Entry Struct struct CDBehaviorParameter { - unsigned int behaviorID; //!< The Behavior ID - std::string parameterID; //!< The Parameter ID - float value; //!< The value of the behavior template + unsigned int behaviorID; //!< The Behavior ID + std::unordered_set::iterator parameterID; //!< The Parameter ID + float value; //!< The value of the behavior template }; //! BehaviorParameter table diff --git a/dDatabase/Tables/CDBehaviorTemplateTable.cpp b/dDatabase/Tables/CDBehaviorTemplateTable.cpp index c79f4177..b832400d 100644 --- a/dDatabase/Tables/CDBehaviorTemplateTable.cpp +++ b/dDatabase/Tables/CDBehaviorTemplateTable.cpp @@ -24,7 +24,13 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) { entry.behaviorID = tableData.getIntField(0, -1); entry.templateID = tableData.getIntField(1, -1); entry.effectID = tableData.getIntField(2, -1); - entry.effectHandle = tableData.getStringField(3, ""); + auto candidateToAdd = tableData.getStringField(3, ""); + auto parameter = m_EffectHandles.find(candidateToAdd); + if (parameter != m_EffectHandles.end()) { + entry.effectHandle = parameter; + } else { + entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first; + } this->entries.push_back(entry); this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry)); @@ -62,7 +68,8 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav if (entry == this->entriesMappedByBehaviorID.end()) { CDBehaviorTemplate entryToReturn; entryToReturn.behaviorID = 0; - entryToReturn.effectHandle = ""; + entryToReturn.effectHandle = m_EffectHandles.end(); + entryToReturn.effectID = 0; return entryToReturn; } else { return entry->second; diff --git a/dDatabase/Tables/CDBehaviorTemplateTable.h b/dDatabase/Tables/CDBehaviorTemplateTable.h index 36424c12..170da854 100644 --- a/dDatabase/Tables/CDBehaviorTemplateTable.h +++ b/dDatabase/Tables/CDBehaviorTemplateTable.h @@ -3,6 +3,7 @@ // Custom Classes #include "CDTable.h" #include +#include /*! \file CDBehaviorTemplateTable.hpp @@ -11,10 +12,10 @@ //! BehaviorTemplate Entry Struct struct CDBehaviorTemplate { - unsigned int behaviorID; //!< The Behavior ID - unsigned int templateID; //!< The Template ID (LOT) - unsigned int effectID; //!< The Effect ID attached - std::string effectHandle; //!< The effect handle + unsigned int behaviorID; //!< The Behavior ID + unsigned int templateID; //!< The Template ID (LOT) + unsigned int effectID; //!< The Effect ID attached + std::unordered_set::iterator effectHandle; //!< The effect handle }; @@ -23,6 +24,7 @@ class CDBehaviorTemplateTable : public CDTable { private: std::vector entries; std::unordered_map entriesMappedByBehaviorID; + std::unordered_set m_EffectHandles; public: //! Constructor diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index ac1ab7de..a2329f96 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -445,7 +445,7 @@ Behavior::Behavior(const uint32_t behaviorId) this->m_effectId = templateInDatabase.effectID; - this->m_effectHandle = templateInDatabase.effectHandle != "" ? new std::string(templateInDatabase.effectHandle) : nullptr; + this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr; } From 24dbd3944da07590ac6b7508c403fdc5251609af Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 12 Jul 2022 20:36:06 -0700 Subject: [PATCH 07/18] Friends List Overhaul (#630) v103 * Add friends list migration * Change friends to use charID Update friends table to use charID and not LWOOBJID variant. * Fix remove friend Fix remove friend and make the query more readable at a glance. * Add and remove friends in the container Properly add and remove friends in the player container * add enums * Add best friends and basic GM support V1 * Add more features * not online / doesnt exist implementation Implements the not online and invalid character response codes * Address players not being removed Fix an issue where players would not be marked as offline in the friends list due to the message not being sent in all circumstances. Tested changes on 3 clients, switching characters, logging out from character select, switching characters, world transfer and my friends list looked as it was supposed to. * Implement proper friends system Remove debug logs Track count of best friends Add best friends list cap of 5 Add config option and best friend update Add a config option and implement the last missing best friend serialization Added comments and fixed remove best friend bug Added some comments and addressed an issue where removing best friends would not remove them from your internal count of friends. properties and logs fixes whoops, had an issue send reply if already BFFs Send the correct objectID I really need to rename these Fix white space goon * Replace queries with unique ptrs * remove user from player container on deletion Remove the user from the player container when they delete their character. --- CMakeVariables.txt | 2 +- dChatServer/ChatPacketHandler.cpp | 315 +++++++++++++----- dChatServer/ChatPacketHandler.h | 8 +- dChatServer/PlayerContainer.cpp | 2 +- dChatServer/PlayerContainer.h | 1 + dCommon/AddFriendResponseCode.h | 15 + dCommon/AddFriendResponseType.h | 24 ++ dGame/EntityManager.cpp | 2 +- dGame/UserManager.cpp | 14 +- .../dComponents/PropertyEntranceComponent.cpp | 24 +- dGame/dComponents/PropertyEntranceComponent.h | 2 +- dWorldServer/WorldServer.cpp | 17 +- resources/worldconfig.ini | 4 + 13 files changed, 321 insertions(+), 109 deletions(-) create mode 100644 dCommon/AddFriendResponseCode.h create mode 100644 dCommon/AddFriendResponseType.h diff --git a/CMakeVariables.txt b/CMakeVariables.txt index ed0cfce8..db89fef7 100644 --- a/CMakeVariables.txt +++ b/CMakeVariables.txt @@ -1,6 +1,6 @@ PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MINOR=0 -PROJECT_VERSION_PATCH=2 +PROJECT_VERSION_PATCH=3 # LICENSE LICENSE=AGPL-3.0 # The network version. diff --git a/dChatServer/ChatPacketHandler.cpp b/dChatServer/ChatPacketHandler.cpp index 82f24ffa..b84c3eef 100644 --- a/dChatServer/ChatPacketHandler.cpp +++ b/dChatServer/ChatPacketHandler.cpp @@ -8,6 +8,10 @@ #include "dServer.h" #include "GeneralUtils.h" #include "dLogger.h" +#include "AddFriendResponseCode.h" +#include "AddFriendResponseType.h" +#include "RakString.h" +#include "dConfig.h" extern PlayerContainer playerContainer; @@ -22,20 +26,20 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { if (!player) return; //Get our friends list from the Db. Using a derived table since the friend of a player can be in either column. - auto stmt = Database::CreatePreppedStmt( + std::unique_ptr stmt(Database::CreatePreppedStmt( "SELECT fr.requested_player, best_friend, ci.name FROM " "(SELECT CASE " "WHEN player_id = ? THEN friend_id " "WHEN friend_id = ? THEN player_id " "END AS requested_player, best_friend FROM friends) AS fr " "JOIN charinfo AS ci ON ci.id = fr.requested_player " - "WHERE fr.requested_player IS NOT NULL;"); + "WHERE fr.requested_player IS NOT NULL;")); stmt->setUInt(1, static_cast(playerID)); stmt->setUInt(2, static_cast(playerID)); std::vector friends; - auto res = stmt->executeQuery(); + std::unique_ptr res(stmt->executeQuery()); while (res->next()) { FriendData fd; fd.isFTP = false; // not a thing in DLU @@ -43,18 +47,19 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { GeneralUtils::SetBit(fd.friendID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); GeneralUtils::SetBit(fd.friendID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); - fd.isBestFriend = res->getInt(2) == 2; //0 = friends, 1 = requested, 2 = bffs + fd.isBestFriend = res->getInt(2) == 3; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs + if (fd.isBestFriend) player->countOfBestFriends+=1; fd.friendName = res->getString(3); //Now check if they're online: auto fr = playerContainer.GetPlayerData(fd.friendID); - Game::logger->Log("ChatPacketHandler", "friend is %llu\n", fd.friendID); + if (fr) { fd.isOnline = true; fd.zoneID = fr->zoneID; //Since this friend is online, we need to update them on the fact that we've just logged in: - SendFriendUpdate(fr, player, 1); + SendFriendUpdate(fr, player, 1, fd.isBestFriend); } else { fd.isOnline = false; @@ -64,11 +69,6 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { friends.push_back(fd); } - delete res; - res = nullptr; - delete stmt; - stmt = nullptr; - //Now, we need to send the friendlist to the server they came from: CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); @@ -91,18 +91,150 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { } void ChatPacketHandler::HandleFriendRequest(Packet* packet) { + auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends"); + // If this config option doesn't exist, default to 5 which is what live used. + auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U; CINSTREAM; - LWOOBJID playerID; - inStream.Read(playerID); - inStream.Read(playerID); - std::string playerName = PacketUtils::ReadString(0x14, packet, true); - //There's another bool here to determine if it's a best friend request, but we're not handling it right now. + LWOOBJID requestorPlayerID; + inStream.Read(requestorPlayerID); + inStream.Read(requestorPlayerID); + uint32_t spacing{}; + inStream.Read(spacing); + std::string playerName = ""; + uint16_t character; + bool noMoreLettersInName = false; - //We need to check to see if the player is actually online or not: - auto targetData = playerContainer.GetPlayerData(playerName); - if (targetData) { - SendFriendRequest(targetData, playerContainer.GetPlayerData(playerID)); + for (uint32_t j = 0; j < 33; j++) { + inStream.Read(character); + if (character == '\0') noMoreLettersInName = true; + if (!noMoreLettersInName) playerName.push_back(static_cast(character)); } + + char isBestFriendRequest{}; + inStream.Read(isBestFriendRequest); + + auto requestor = playerContainer.GetPlayerData(requestorPlayerID); + std::unique_ptr requestee(playerContainer.GetPlayerData(playerName)); + + // Check if player is online first + if (isBestFriendRequest && !requestee) { + for (auto friendDataCandidate : requestor->friends) { + if (friendDataCandidate.friendName == playerName) { + requestee.reset(new PlayerData()); + // Setup the needed info since you can add a best friend offline. + requestee->playerID = friendDataCandidate.friendID; + requestee->playerName = RakNet::RakString(friendDataCandidate.friendName.c_str()); + requestee->zoneID = LWOZONEID(); + + FriendData requesteeFriendData{}; + requesteeFriendData.friendID = requestor->playerID; + requesteeFriendData.friendName = requestor->playerName; + requesteeFriendData.isFTP = false; + requesteeFriendData.isOnline = false; + requesteeFriendData.zoneID = requestor->zoneID; + requestee->friends.push_back(requesteeFriendData); + requestee->sysAddr = UNASSIGNED_SYSTEM_ADDRESS; + break; + } + } + } + + // If at this point we dont have a target, then they arent online and we cant send the request. + // Send the response code that corresponds to what the error is. + if (!requestee) { + std::unique_ptr nameQuery(Database::CreatePreppedStmt("SELECT name from charinfo where name = ?;")); + nameQuery->setString(1, playerName); + std::unique_ptr result(nameQuery->executeQuery()); + + requestee.reset(new PlayerData()); + requestee->playerName = RakNet::RakString(playerName.c_str()); + + SendFriendResponse(requestor, requestee.get(), result->next() ? AddFriendResponseType::NOTONLINE : AddFriendResponseType::INVALIDCHARACTER); + return; + } + + if (isBestFriendRequest) { + std::unique_ptr friendUpdate(Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;")); + friendUpdate->setUInt(1, static_cast(requestorPlayerID)); + friendUpdate->setUInt(2, static_cast(requestee->playerID)); + friendUpdate->setUInt(3, static_cast(requestee->playerID)); + friendUpdate->setUInt(4, static_cast(requestorPlayerID)); + std::unique_ptr result(friendUpdate->executeQuery()); + + LWOOBJID queryPlayerID = LWOOBJID_EMPTY; + LWOOBJID queryFriendID = LWOOBJID_EMPTY; + uint8_t oldBestFriendStatus{}; + uint8_t bestFriendStatus{}; + + if (result->next()) { + // Get the IDs + queryPlayerID = result->getInt(1); + queryFriendID = result->getInt(2); + oldBestFriendStatus = result->getInt(3); + bestFriendStatus = oldBestFriendStatus; + + // Set the bits + GeneralUtils::SetBit(queryPlayerID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); + GeneralUtils::SetBit(queryPlayerID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); + GeneralUtils::SetBit(queryFriendID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); + GeneralUtils::SetBit(queryFriendID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); + + // Since this player can either be the friend of someone else or be friends with someone else + // their column in the database determines what bit gets set. When the value hits 3, they + // are now best friends with the other player. + if (queryPlayerID == requestorPlayerID) { + bestFriendStatus |= 1ULL << 0; + } else { + bestFriendStatus |= 1ULL << 1; + } + } + + // Only do updates if there was a change in the bff status. + if (oldBestFriendStatus != bestFriendStatus) { + if (requestee->countOfBestFriends >= maxNumberOfBestFriends || requestor->countOfBestFriends >= maxNumberOfBestFriends) { + if (requestee->countOfBestFriends >= maxNumberOfBestFriends) { + SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::THEIRFRIENDLISTFULL, false); + } + if (requestor->countOfBestFriends >= maxNumberOfBestFriends) { + SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::YOURFRIENDSLISTFULL, false); + } + } else { + // Then update the database with this new info. + std::unique_ptr updateQuery(Database::CreatePreppedStmt("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;")); + updateQuery->setUInt(1, bestFriendStatus); + updateQuery->setUInt(2, static_cast(requestorPlayerID)); + updateQuery->setUInt(3, static_cast(requestee->playerID)); + updateQuery->setUInt(4, static_cast(requestee->playerID)); + updateQuery->setUInt(5, static_cast(requestorPlayerID)); + updateQuery->executeUpdate(); + // Sent the best friend update here if the value is 3 + if (bestFriendStatus == 3U) { + requestee->countOfBestFriends+=1; + requestor->countOfBestFriends+=1; + if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee.get(), requestor, AddFriendResponseType::ACCEPTED, false, true); + if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::ACCEPTED, false, true); + for (auto& friendData : requestor->friends) { + if (friendData.friendID == requestee->playerID) { + friendData.isBestFriend = true; + } + } + for (auto& friendData : requestee->friends) { + if (friendData.friendID == requestor->playerID) { + friendData.isBestFriend = true; + } + } + } + } + } else { + if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::WAITINGAPPROVAL, true, true); + } + } else { + // Do not send this if we are requesting to be a best friend. + SendFriendRequest(requestee.get(), requestor); + } + + // If the player is actually a player and not a ghost one defined above, release it from being deleted. + if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) requestee.release(); } void ChatPacketHandler::HandleFriendResponse(Packet* packet) { @@ -110,53 +242,75 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) { LWOOBJID playerID; inStream.Read(playerID); inStream.Read(playerID); - - uint8_t responseCode = packet->data[0x14]; + + AddFriendResponseCode clientResponseCode = static_cast(packet->data[0x14]); std::string friendName = PacketUtils::ReadString(0x15, packet, true); //Now to try and find both of these: - auto goonA = playerContainer.GetPlayerData(playerID); - auto goonB = playerContainer.GetPlayerData(friendName); - if (!goonA || !goonB) return; + auto requestor = playerContainer.GetPlayerData(playerID); + auto requestee = playerContainer.GetPlayerData(friendName); + if (!requestor || !requestee) return; - if (responseCode != 0) return; //If we're not accepting the request, end here, do not insert to friends table. - - for (auto friendData : goonA->friends) { - if (friendData.friendID == goonB->playerID) return; + AddFriendResponseType serverResponseCode{}; + uint8_t isAlreadyBestFriends = 0U; + // We need to convert this response code to one we can actually send back to the client. + switch (clientResponseCode) { + case AddFriendResponseCode::ACCEPTED: + serverResponseCode = AddFriendResponseType::ACCEPTED; + break; + case AddFriendResponseCode::BUSY: + serverResponseCode = AddFriendResponseType::BUSY; + break; + case AddFriendResponseCode::CANCELLED: + serverResponseCode = AddFriendResponseType::CANCELLED; + break; + case AddFriendResponseCode::REJECTED: + serverResponseCode = AddFriendResponseType::DECLINED; + break; } - for (auto friendData : goonB->friends) { - if (friendData.friendID == goonA->playerID) return; + // Now that we have handled the base cases, we need to check the other cases. + if (serverResponseCode == AddFriendResponseType::ACCEPTED) { + for (auto friendData : requestor->friends) { + if (friendData.friendID == requestee->playerID) { + serverResponseCode = AddFriendResponseType::ALREADYFRIEND; + if (friendData.isBestFriend) { + isAlreadyBestFriends = 1U; + } + } + } } - // Add the goons to their friends list - FriendData goonAData; - goonAData.zoneID = goonA->zoneID; - goonAData.friendID = goonA->playerID; - goonAData.friendName = goonA->playerName; - goonAData.isBestFriend = false; - goonAData.isFTP = false; - goonAData.isOnline = true; - goonB->friends.push_back(goonAData); + // This message is NOT sent for best friends and is handled differently for those requests. + if (serverResponseCode == AddFriendResponseType::ACCEPTED) { + // Add the each player to the others friend list. + FriendData requestorData; + requestorData.zoneID = requestor->zoneID; + requestorData.friendID = requestor->playerID; + requestorData.friendName = requestor->playerName; + requestorData.isBestFriend = false; + requestorData.isFTP = false; + requestorData.isOnline = true; + requestee->friends.push_back(requestorData); - FriendData goonBData; - goonBData.zoneID = goonB->zoneID; - goonBData.friendID = goonB->playerID; - goonBData.friendName = goonB->playerName; - goonBData.isBestFriend = false; - goonBData.isFTP = false; - goonBData.isOnline = true; - goonA->friends.push_back(goonBData); + FriendData requesteeData; + requesteeData.zoneID = requestee->zoneID; + requesteeData.friendID = requestee->playerID; + requesteeData.friendName = requestee->playerName; + requesteeData.isBestFriend = false; + requesteeData.isFTP = false; + requesteeData.isOnline = true; + requestor->friends.push_back(requesteeData); + + std::unique_ptr statement(Database::CreatePreppedStmt("INSERT IGNORE INTO `friends` (`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?);")); + statement->setUInt(1, static_cast(requestor->playerID)); + statement->setUInt(2, static_cast(requestee->playerID)); + statement->setInt(3, 0); + statement->execute(); + } - SendFriendResponse(goonB, goonA, responseCode); - SendFriendResponse(goonA, goonB, responseCode); //Do we need to send it to both? I think so so both get the updated friendlist but... idk. - - auto stmt = Database::CreatePreppedStmt("INSERT IGNORE INTO `friends` (`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?)"); - stmt->setUInt(1, static_cast(goonA->playerID)); - stmt->setUInt(2, static_cast(goonB->playerID)); - stmt->setInt(3, 0); - stmt->execute(); - delete stmt; + if (serverResponseCode != AddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends); + if (serverResponseCode != AddFriendResponseType::ALREADYFRIEND) SendFriendResponse(requestee, requestor, serverResponseCode, isAlreadyBestFriends); } void ChatPacketHandler::HandleRemoveFriend(Packet* packet) { @@ -168,11 +322,11 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) { //we'll have to query the db here to find the user, since you can delete them while they're offline. //First, we need to find their ID: - auto stmt = Database::CreatePreppedStmt("SELECT id FROM charinfo WHERE name=? LIMIT 1;"); + std::unique_ptr stmt(Database::CreatePreppedStmt("SELECT id FROM charinfo WHERE name=? LIMIT 1;")); stmt->setString(1, friendName.c_str()); LWOOBJID friendID = 0; - auto res = stmt->executeQuery(); + std::unique_ptr res(stmt->executeQuery()); while (res->next()) { friendID = res->getUInt(1); } @@ -181,27 +335,20 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) { GeneralUtils::SetBit(friendID, static_cast(eObjectBits::OBJECT_BIT_PERSISTENT)); GeneralUtils::SetBit(friendID, static_cast(eObjectBits::OBJECT_BIT_CHARACTER)); - delete res; - res = nullptr; - delete stmt; - stmt = nullptr; - - auto deletestmt = Database::CreatePreppedStmt("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"); + std::unique_ptr deletestmt(Database::CreatePreppedStmt("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;")); deletestmt->setUInt(1, static_cast(playerID)); deletestmt->setUInt(2, static_cast(friendID)); deletestmt->setUInt(3, static_cast(friendID)); deletestmt->setUInt(4, static_cast(playerID)); deletestmt->execute(); - delete deletestmt; - deletestmt = nullptr; - //Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended: auto goonA = playerContainer.GetPlayerData(playerID); if (goonA) { // Remove the friend from our list of friends for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) { if ((*friendData).friendID == friendID) { + if ((*friendData).isBestFriend) --goonA->countOfBestFriends; goonA->friends.erase(friendData); break; } @@ -214,6 +361,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) { // Do it again for other person for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) { if ((*friendData).friendID == playerID) { + if ((*friendData).isBestFriend) --goonB->countOfBestFriends; goonB->friends.erase(friendData); break; } @@ -766,7 +914,7 @@ void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i SEND_PACKET; } -void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType) { +void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend) { /*chat notification is displayed if log in / out and friend is updated in friends list [u8] - update type Update types @@ -804,19 +952,20 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla bitStream.Write(playerData->zoneID.GetCloneID()); } - bitStream.Write(0); //isBFF + bitStream.Write(isBestFriend); //isBFF bitStream.Write(0); //isFTP SystemAddress sysAddr = friendData->sysAddr; SEND_PACKET; } -void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* sender, bool isBFFReq) { +void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* sender) { if (!receiver || !sender) return; //Make sure people aren't requesting people that they're already friends with: for (auto fr : receiver->friends) { if (fr.friendID == sender->playerID) { + SendFriendResponse(sender, receiver, AddFriendResponseType::ALREADYFRIEND, fr.isBestFriend); return; //we have this player as a friend, yeet this function so it doesn't send another request. } } @@ -828,29 +977,33 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send //portion that will get routed: PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_REQUEST); PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream); - bitStream.Write(0); + bitStream.Write(0); // This is a BFF flag however this is unused in live and does not have an implementation client side. SystemAddress sysAddr = receiver->sysAddr; SEND_PACKET; } -void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sender, uint8_t responseCode) { +void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sender, AddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) { if (!receiver || !sender) return; CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); - //portion that will get routed: + // Portion that will get routed: PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_RESPONSE); - bitStream.Write(responseCode); - bitStream.Write(1); //isOnline + bitStream.Write(responseCode); + // For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver. + bitStream.Write(responseCode != AddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS); + // Then write the player name PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream); - bitStream.Write(sender->playerID); - bitStream.Write(sender->zoneID); - bitStream.Write(0); //isBFF - bitStream.Write(0); //isFTP - + // Then if this is an acceptance code, write the following extra info. + if (responseCode == AddFriendResponseType::ACCEPTED) { + bitStream.Write(sender->playerID); + bitStream.Write(sender->zoneID); + bitStream.Write(isBestFriendRequest); //isBFF + bitStream.Write(0); //isFTP + } SystemAddress sysAddr = receiver->sysAddr; SEND_PACKET; } diff --git a/dChatServer/ChatPacketHandler.h b/dChatServer/ChatPacketHandler.h index e38a65c1..fffd1ca4 100644 --- a/dChatServer/ChatPacketHandler.h +++ b/dChatServer/ChatPacketHandler.h @@ -4,6 +4,7 @@ #include "BitStream.h" struct PlayerData; +enum class AddFriendResponseType : uint8_t; namespace ChatPacketHandler { void HandleFriendlistRequest(Packet* packet); @@ -31,10 +32,9 @@ namespace ChatPacketHandler { void SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID); //FriendData is the player we're SENDING this stuff to. Player is the friend that changed state. - void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType); + void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend); - void SendFriendRequest(PlayerData* receiver, PlayerData* sender, bool isBFFReq = false); - void SendFriendResponse(PlayerData* receiver, PlayerData* sender, uint8_t responseCode = 3); + void SendFriendRequest(PlayerData* receiver, PlayerData* sender); + void SendFriendResponse(PlayerData* receiver, PlayerData* sender, AddFriendResponseType responseCode, uint8_t isBestFriendsAlready = 0U, uint8_t isBestFriendRequest = 0U); void SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful); }; - diff --git a/dChatServer/PlayerContainer.cpp b/dChatServer/PlayerContainer.cpp index d261b32f..b40e8386 100644 --- a/dChatServer/PlayerContainer.cpp +++ b/dChatServer/PlayerContainer.cpp @@ -59,7 +59,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) { //if (!fr.isOnline) continue; auto fd = this->GetPlayerData(fr.friendID); - if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0); + if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0, fr.isBestFriend); } auto* team = GetTeam(playerID); diff --git a/dChatServer/PlayerContainer.h b/dChatServer/PlayerContainer.h index dc78d3b0..b1e1defd 100644 --- a/dChatServer/PlayerContainer.h +++ b/dChatServer/PlayerContainer.h @@ -14,6 +14,7 @@ struct PlayerData { LWOZONEID zoneID; std::vector friends; time_t muteExpire; + uint8_t countOfBestFriends = 0; }; struct TeamData { diff --git a/dCommon/AddFriendResponseCode.h b/dCommon/AddFriendResponseCode.h new file mode 100644 index 00000000..bb2faff7 --- /dev/null +++ b/dCommon/AddFriendResponseCode.h @@ -0,0 +1,15 @@ +#pragma once + +#ifndef __ADDFRIENDRESPONSECODE__H__ +#define __ADDFRIENDRESPONSECODE__H__ + +#include + +enum class AddFriendResponseCode : uint8_t { + ACCEPTED = 0, + REJECTED, + BUSY, + CANCELLED +}; + +#endif //!__ADDFRIENDRESPONSECODE__H__ diff --git a/dCommon/AddFriendResponseType.h b/dCommon/AddFriendResponseType.h new file mode 100644 index 00000000..305796e8 --- /dev/null +++ b/dCommon/AddFriendResponseType.h @@ -0,0 +1,24 @@ +#pragma once + +#ifndef __ADDFRIENDRESPONSETYPE__H__ +#define __ADDFRIENDRESPONSETYPE__H__ + +#include + +enum class AddFriendResponseType : uint8_t { + ACCEPTED = 0, + ALREADYFRIEND, + INVALIDCHARACTER, + GENERALERROR, + YOURFRIENDSLISTFULL, + THEIRFRIENDLISTFULL, + DECLINED, + BUSY, + NOTONLINE, + WAITINGAPPROVAL, + MYTHRAN, + CANCELLED, + FRIENDISFREETRIAL +}; + +#endif //!__ADDFRIENDRESPONSETYPE__H__ diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index db60a1d1..da0cf685 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -401,7 +401,7 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr Game::server->Send(&stream, sysAddr, false); } - PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed()); + // PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed()); if (entity->IsPlayer()) { diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 1d14cb0a..3956942a 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -369,10 +369,8 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) } LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet); - objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_CHARACTER); - objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_PERSISTENT); - - uint32_t charID = static_cast(objectID); + uint32_t charID = static_cast(objectID); + Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)\n", objectID, charID); //Check if this user has this character: @@ -402,10 +400,14 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) } { sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM friends WHERE player_id=? OR friend_id=?;"); - stmt->setUInt64(1, charID); - stmt->setUInt64(2, charID); + stmt->setUInt(1, charID); + stmt->setUInt(2, charID); stmt->execute(); delete stmt; + CBITSTREAM; + PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION); + bitStream.Write(objectID); + Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } { sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM leaderboard WHERE character_id=?;"); diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 1d631e88..87e0c7ed 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -102,7 +102,7 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert return property; } -std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) { +std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery, bool wantLimits) { std::string base; if (customQuery == "") { base = baseQueryForProperties; @@ -115,15 +115,13 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); - friendsListQuery->setInt64(1, entity->GetObjectID()); - friendsListQuery->setInt64(2, entity->GetObjectID()); + friendsListQuery->setUInt(1, character->GetID()); + friendsListQuery->setUInt(2, character->GetID()); auto friendsListQueryResult = friendsListQuery->executeQuery(); while (friendsListQueryResult->next()) { - auto playerIDToConvert = friendsListQueryResult->getInt64(1); - playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_CHARACTER); - playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_PERSISTENT); + auto playerIDToConvert = friendsListQueryResult->getInt(1); friendsList = friendsList + std::to_string(playerIDToConvert) + ","; } // Replace trailing comma with the closing parenthesis. @@ -193,7 +191,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl entries.push_back(playerEntry); - const auto query = BuildQuery(entity, sortMethod); + const auto query = BuildQuery(entity, sortMethod, character); auto propertyLookup = Database::CreatePreppedStmt(query); @@ -262,17 +260,17 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // Query to get friend and best friend fields auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); - friendCheck->setInt64(1, entity->GetObjectID()); - friendCheck->setInt64(2, ownerObjId); - friendCheck->setInt64(3, ownerObjId); - friendCheck->setInt64(4, entity->GetObjectID()); + friendCheck->setUInt(1, character->GetID()); + friendCheck->setUInt(2, ownerObjId); + friendCheck->setUInt(3, ownerObjId); + friendCheck->setUInt(4, character->GetID()); auto friendResult = friendCheck->executeQuery(); // If we got a result than the two players are friends. if (friendResult->next()) { isFriend = true; - if (friendResult->getInt(1) == 2) { + if (friendResult->getInt(1) == 3) { isBestFriend = true; } } @@ -326,7 +324,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // Query here is to figure out whether or not to display the button to go to the next page or not. int32_t numberOfProperties = 0; - auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false); + auto buttonQuery = BuildQuery(entity, sortMethod, character, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false); auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery); propertiesLeft->setUInt(1, this->m_MapID); diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index a3be38a6..fe583e92 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -60,7 +60,7 @@ class PropertyEntranceComponent : public Component { PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f); - std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true); + std::string BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery = "", bool wantLimits = true); private: /** diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 4f1ec400..330263ed 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -669,10 +669,12 @@ void HandlePacket(Packet* packet) { Game::logger->Log("WorldServer", "Deleting player %llu\n", entity->GetObjectID()); EntityManager::Instance()->DestroyEntity(entity); + } + { CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION); - bitStream.Write(c->GetObjectID()); + bitStream.Write(user->GetLoggedInChar()); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } @@ -930,6 +932,19 @@ void HandlePacket(Packet* packet) { playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_CHARACTER); playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_PERSISTENT); + auto user = UserManager::Instance()->GetUser(packet->systemAddress); + + if (user) { + auto lastCharacter = user->GetLoggedInChar(); + // This means we swapped characters and we need to remove the previous player from the container. + if (static_cast(lastCharacter) != playerID) { + CBITSTREAM; + PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION); + bitStream.Write(lastCharacter); + Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); + } + } + UserManager::Instance()->LoginCharacter(packet->systemAddress, static_cast(playerID)); break; } diff --git a/resources/worldconfig.ini b/resources/worldconfig.ini index a665f059..931da28c 100644 --- a/resources/worldconfig.ini +++ b/resources/worldconfig.ini @@ -60,3 +60,7 @@ classic_survival_scoring=0 # If this value is 1, pets will consume imagination as they did in live. if 0 they will not consume imagination at all. pets_take_imagination=1 + +# If you would like to increase the maximum number of best friends a player can have on the server +# Change the value below to what you would like this to be (5 is live accurate) +max_number_of_best_friends=5 \ No newline at end of file From ccb9f7c499a4ea3b054e5b172b5bfc39c0bb7b60 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 12 Jul 2022 20:45:25 -0700 Subject: [PATCH 08/18] Move instruction for database Move the instruction for running the MasterServer migration down to where the command will actually work as well as use a more syntactically correct statement --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d029ed93..5781c7b8 100644 --- a/README.md +++ b/README.md @@ -152,13 +152,6 @@ now follow the build section for your system ## Setting up the environment -### Database -Darkflame Universe utilizes a MySQL/MariaDB database for account and character information. - -Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running. -* Create a database for Darkflame Universe to use -* Run the migrations by running `./MasterServer -m` to automatically run them - ### Resources **LEGO® Universe 1.10.64** @@ -202,6 +195,13 @@ certutil -hashfile SHA256 * Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite` * Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database +### Database +Darkflame Universe utilizes a MySQL/MariaDB database for account and character information. + +Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running. +* Create a database for Darkflame Universe to use +* Use the command `./MasterServer -m` to automatically run them. + **Configuration** After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary. From 9ba297dd2e2a6814646fa755ebaac780d60f6a0e Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 13 Jul 2022 09:10:02 -0700 Subject: [PATCH 09/18] Add code to complete hidden property mission (#641) --- dScripts/BasePropertyServer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dScripts/BasePropertyServer.cpp b/dScripts/BasePropertyServer.cpp index e7a95844..ce36caa9 100644 --- a/dScripts/BasePropertyServer.cpp +++ b/dScripts/BasePropertyServer.cpp @@ -169,11 +169,10 @@ void BasePropertyServer::BaseZonePropertyRented(Entity* self, Entity* player) co EntityManager::Instance()->DestructEntity(plaque); } - if (self->GetVar(brickLinkMissionIDFlag) != 0) { - auto plaques = EntityManager::Instance()->GetEntitiesInGroup(self->GetVar(PropertyPlaqueGroup)); - for (auto* plaque : plaques) { - EntityManager::Instance()->DestructEntity(plaque); - } + auto brickLinkMissionID = self->GetVar(brickLinkMissionIDFlag); + if (brickLinkMissionID != 0) { + auto missionComponent = player->GetComponent(); + if (missionComponent) missionComponent->CompleteMission(brickLinkMissionID, true); } ActivateSpawner(self->GetVar(PropObjsSpawner)); From 3d46d703b2c10cd8673f518a44054753db7723dc Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 13 Jul 2022 09:11:24 -0700 Subject: [PATCH 10/18] Remove memory leak in player container and warning in Behavior (#640) * Add friends list migration * Change friends to use charID Update friends table to use charID and not LWOOBJID variant. * Fix remove friend Fix remove friend and make the query more readable at a glance. * Add and remove friends in the container Properly add and remove friends in the player container * add enums * Add best friends and basic GM support V1 * Add more features * not online / doesnt exist implementation Implements the not online and invalid character response codes * Address players not being removed Fix an issue where players would not be marked as offline in the friends list due to the message not being sent in all circumstances. Tested changes on 3 clients, switching characters, logging out from character select, switching characters, world transfer and my friends list looked as it was supposed to. * Implement proper friends system Remove debug logs Track count of best friends Add best friends list cap of 5 Add config option and best friend update Add a config option and implement the last missing best friend serialization Added comments and fixed remove best friend bug Added some comments and addressed an issue where removing best friends would not remove them from your internal count of friends. properties and logs fixes whoops, had an issue send reply if already BFFs Send the correct objectID I really need to rename these Fix white space goon * Replace queries with unique ptrs * remove user from player container on deletion Remove the user from the player container when they delete their character. * Bump patch version * Improvements to PlayerContainer Resolved a memory leak in the player container, removed commented out code and resolved a warning in Behavior.cpp * Make it a unique ptr * Improvements to PlayerContainer Resolved a memory leak in the player container, removed commented out code and resolved a warning in Behavior.cpp Make it a unique ptr * Update PlayerContainer.cpp --- dChatServer/PlayerContainer.cpp | 19 ++----------------- dGame/dBehaviors/Behavior.cpp | 2 +- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/dChatServer/PlayerContainer.cpp b/dChatServer/PlayerContainer.cpp index b40e8386..c5da3a7f 100644 --- a/dChatServer/PlayerContainer.cpp +++ b/dChatServer/PlayerContainer.cpp @@ -49,25 +49,21 @@ void PlayerContainer::RemovePlayer(Packet* packet) { inStream.Read(playerID); //Before they get kicked, we need to also send a message to their friends saying that they disconnected. - auto player = this->GetPlayerData(playerID); + std::unique_ptr player(this->GetPlayerData(playerID)); if (player == nullptr) { return; } for (auto& fr : player->friends) { - //if (!fr.isOnline) continue; - auto fd = this->GetPlayerData(fr.friendID); - if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0, fr.isBestFriend); + if (fd) ChatPacketHandler::SendFriendUpdate(fd, player.get(), 0, fr.isBestFriend); } auto* team = GetTeam(playerID); if (team != nullptr) { - //TeamStatusUpdate(team); - const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.C_String())); for (const auto memberId : team->memberIDs) @@ -77,7 +73,6 @@ void PlayerContainer::RemovePlayer(Packet* packet) { if (otherMember == nullptr) continue; ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, {0, 0, 0}); - //ChatPacketHandler::SendTeamRemovePlayer(otherMember, false, false, true, false, team->leaderID, player->playerID, memberName); } } @@ -241,12 +236,6 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.C_String())); ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName); - - /* - ChatPacketHandler::SendTeamAddPlayer(member, false, false, false, leader->playerID, leaderName, leader->zoneID); - - Game::logger->Log("PlayerContainer", "Team invite successfully accepted, leader: %s, member: %s\n", leader->playerName.C_String(), member->playerName.C_String()); - */ if (!team->local) { @@ -383,10 +372,6 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) { ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName); } - else - { - //ChatPacketHandler::SendTeamStatus(otherMember, LWOOBJID_EMPTY, LWOZONEID(0, 0, 0), 1, 0, u""); - } } UpdateTeamsOnWorld(team, false); diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index a2329f96..489bd1a7 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -409,7 +409,7 @@ Behavior::Behavior(const uint32_t behaviorId) { auto behaviorTemplateTable = CDClientManager::Instance()->GetTable("BehaviorTemplate"); - CDBehaviorTemplate templateInDatabase; + CDBehaviorTemplate templateInDatabase{}; if (behaviorTemplateTable) { auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); From 9c0819de4fded129dc17713b5630b382e74093f8 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Sat, 16 Jul 2022 22:55:54 +0100 Subject: [PATCH 11/18] Add MacOS building to the Github Actions (#643) * Add MacOS to CMakePresets.json * Update workflow to run MacOS builds * Update test and build presets * Add libssl install to integration * Update workflow to install libssl and openssl * Prevent brew running as super user --- .github/workflows/build-and-test.yml | 7 +++++-- CMakePresets.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 0e7785d9..5a36df4b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -12,18 +12,21 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ windows-2022, ubuntu-20.04 ] + os: [ windows-2022, ubuntu-20.04, macos-11 ] steps: - uses: actions/checkout@v2 with: submodules: true - - name: Add msbuild to PATH (windows only) + - name: Add msbuild to PATH (Windows only) if: ${{ matrix.os == 'windows-2022' }} uses: microsoft/setup-msbuild@v1.1 with: vs-version: '[17,18)' msbuild-architecture: x64 + - name: Install libssl (Mac Only) + if: ${{ matrix.os == 'macos-11' }} + run: brew install openssl@3 - name: cmake uses: lukka/run-cmake@v10 with: diff --git a/CMakePresets.json b/CMakePresets.json index 241220e0..133d6a3c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -19,6 +19,15 @@ "description": "Same as default, Used in GitHub actions workflow", "inherits": "default" }, + { + "name": "ci-macos-11", + "displayName": "CI configure step for MacOS", + "description": "Same as default, Used in GitHub actions workflow", + "inherits": "default", + "cacheVariables": { + "OPENSSL_ROOT_DIR": "/usr/local/Cellar/openssl@3/3.0.5/" + } + }, { "name": "ci-windows-2022", "displayName": "CI configure step for Windows", @@ -66,6 +75,13 @@ "displayName": "Linux CI Build", "description": "This preset is used by the CI build on linux", "jobs": 2 + }, + { + "name": "ci-macos-11", + "configurePreset": "ci-macos-11", + "displayName": "MacOS CI Build", + "description": "This preset is used by the CI build on MacOS", + "jobs": 2 } ], "testPresets": [ @@ -81,6 +97,18 @@ "outputOnFailure": true } }, + { + "name": "ci-macos-11", + "configurePreset": "ci-macos-11", + "displayName": "CI Tests on MacOS", + "description": "Runs all tests on a Mac configuration", + "execution": { + "jobs": 2 + }, + "output": { + "outputOnFailure": true + } + }, { "name": "ci-windows-2022", "configurePreset": "ci-windows-2022", From df0f11c95b76c6f5869776272189b6fb81b22e74 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Sun, 17 Jul 2022 00:24:16 +0100 Subject: [PATCH 12/18] Update CMake configuration for easier maintenance (#642) * Update CMake configuration for easier maintenance * Incorrect casing fix * Move package requirement * Update CTest linking * Add logs to the CMake * Add linking for common libraries Added linking for common libraries in tests subdirectory. * Move test subdirectory higher up for some reason * Whitespace a log removal Missed new line * Add dCommon to dChatFilter * Update library output dir * Correct libBcrypt * Further refactor CMake behaviour * Repair bad comments and update library defines * Revert to old include directory method * Implement platform defines * Add missing include Mac needs a specific include for defining platform. Does not compile without this. Co-authored-by: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> --- CMakeLists.txt | 546 +++++++++-------------------- dAuthServer/CMakeLists.txt | 4 + dChatFilter/CMakeLists.txt | 4 + dChatServer/CMakeLists.txt | 6 + dCommon/CMakeLists.txt | 26 ++ dCommon/ZCompression.cpp | 6 +- dCommon/ZCompression.h | 6 + dCommon/dPlatforms.h | 29 ++ dDatabase/CMakeLists.txt | 13 + dDatabase/Tables/CMakeLists.txt | 38 ++ dGame/CMakeLists.txt | 59 ++++ dGame/dBehaviors/CMakeLists.txt | 51 +++ dGame/dComponents/CMakeLists.txt | 40 +++ dGame/dEntity/CMakeLists.txt | 2 + dGame/dGameMessages/CMakeLists.txt | 4 + dGame/dInventory/CMakeLists.txt | 5 + dGame/dMission/CMakeLists.txt | 3 + dGame/dUtilities/CMakeLists.txt | 9 + dMasterServer/CMakeLists.txt | 10 + dNet/CMakeLists.txt | 11 + dPhysics/CMakeLists.txt | 9 + dScripts/CMakeLists.txt | 253 +++++++++++++ dWorldServer/CMakeLists.txt | 6 + dZoneManager/CMakeLists.txt | 6 + tests/CMakeLists.txt | 20 +- thirdparty/CMakeLists.txt | 102 ++++-- 26 files changed, 839 insertions(+), 429 deletions(-) create mode 100644 dAuthServer/CMakeLists.txt create mode 100644 dChatFilter/CMakeLists.txt create mode 100644 dChatServer/CMakeLists.txt create mode 100644 dCommon/CMakeLists.txt create mode 100644 dCommon/dPlatforms.h create mode 100644 dDatabase/CMakeLists.txt create mode 100644 dDatabase/Tables/CMakeLists.txt create mode 100644 dGame/CMakeLists.txt create mode 100644 dGame/dBehaviors/CMakeLists.txt create mode 100644 dGame/dComponents/CMakeLists.txt create mode 100644 dGame/dEntity/CMakeLists.txt create mode 100644 dGame/dGameMessages/CMakeLists.txt create mode 100644 dGame/dInventory/CMakeLists.txt create mode 100644 dGame/dMission/CMakeLists.txt create mode 100644 dGame/dUtilities/CMakeLists.txt create mode 100644 dMasterServer/CMakeLists.txt create mode 100644 dNet/CMakeLists.txt create mode 100644 dPhysics/CMakeLists.txt create mode 100644 dScripts/CMakeLists.txt create mode 100644 dWorldServer/CMakeLists.txt create mode 100644 dZoneManager/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 5373dfe4..0817412b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,90 +12,67 @@ string(REPLACE "\n" ";" variables ${variables}) # Set the cmake variables, formatted as "VARIABLE #" in variables foreach(variable ${variables}) - # If the string contains a #, skip it - if(NOT "${variable}" MATCHES "#") - - # Split the variable into name and value - string(REPLACE "=" ";" variable ${variable}) + # If the string contains a #, skip it + if(NOT "${variable}" MATCHES "#") + + # Split the variable into name and value + string(REPLACE "=" ";" variable ${variable}) - # Check that the length of the variable is 2 (name and value) - list(LENGTH variable length) - if(${length} EQUAL 2) + # Check that the length of the variable is 2 (name and value) + list(LENGTH variable length) + if(${length} EQUAL 2) - list(GET variable 0 variable_name) - list(GET variable 1 variable_value) + list(GET variable 0 variable_name) + list(GET variable 1 variable_value) - # Set the variable - set(${variable_name} ${variable_value}) + # Set the variable + set(${variable_name} ${variable_value}) - # Add compiler definition - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${variable_name}=${variable_value}") + # Add compiler definition + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${variable_name}=${variable_value}") - message(STATUS "Variable: ${variable_name} = ${variable_value}") + message(STATUS "Variable: ${variable_name} = ${variable_value}") endif() endif() endforeach() -# On windows it's better to build this from source, as there's no way FindZLIB is gonna find it -if(NOT WIN32) -find_package(ZLIB REQUIRED) -endif() - -# Fetch External (Non-Submodule) Libraries -if(WIN32) -include(FetchContent) - -FetchContent_Declare( - zlib - URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip - URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1 -) - -FetchContent_MakeAvailable(zlib) - -set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR}) -set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") # Why? -add_library(ZLIB::ZLIB ALIAS zlib) # You're welcome - -endif(WIN32) - -if(UNIX AND NOT APPLE) - include(FetchContent) - if (__include_backtrace__ AND __compile_backtrace__) - FetchContent_Declare( - backtrace - GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git - ) - - FetchContent_MakeAvailable(backtrace) - - if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs) - set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind") - - execute_process( - COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}" - ) - endif() - - link_directories(${backtrace_SOURCE_DIR}/.libs/) - include_directories(${backtrace_SOURCE_DIR}) - endif() -endif() - # Set the version set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}") - # Echo the version message(STATUS "Version: ${PROJECT_VERSION}") -if(WIN32) - add_compile_definitions(_CRT_SECURE_NO_WARNINGS) -endif(WIN32) +# Compiler flags: +# Disabled deprecated warnings as the MySQL includes have deprecated code in them. +# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent. +# Disabled no-register +# Disabled unknown pragmas because Linux doesn't understand Windows pragmas. +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}") +if(UNIX) + if(APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC") + endif() + if (__dynamic) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic") + endif() + if (__ggdb) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb") + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC") +elseif(MSVC) + # Skip warning for invalid conversion from size_t to uint32_t for all targets below for now + add_compile_options("/wd4267") +elseif(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +endif() # Our output dir set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # Create a /res directory make_directory(${CMAKE_BINARY_DIR}/res) @@ -107,363 +84,172 @@ make_directory(${CMAKE_BINARY_DIR}/locale) make_directory(${CMAKE_BINARY_DIR}/logs) # Copy ini files on first build -if (NOT EXISTS ${PROJECT_BINARY_DIR}/authconfig.ini) - configure_file( - ${CMAKE_SOURCE_DIR}/resources/authconfig.ini ${PROJECT_BINARY_DIR}/authconfig.ini - COPYONLY - ) -endif() -if (NOT EXISTS ${PROJECT_BINARY_DIR}/chatconfig.ini) - configure_file( - ${CMAKE_SOURCE_DIR}/resources/chatconfig.ini ${PROJECT_BINARY_DIR}/chatconfig.ini - COPYONLY - ) -endif() -if (NOT EXISTS ${PROJECT_BINARY_DIR}/worldconfig.ini) - configure_file( - ${CMAKE_SOURCE_DIR}/resources/worldconfig.ini ${PROJECT_BINARY_DIR}/worldconfig.ini - COPYONLY - ) -endif() -if (NOT EXISTS ${PROJECT_BINARY_DIR}/masterconfig.ini) - configure_file( - ${CMAKE_SOURCE_DIR}/resources/masterconfig.ini ${PROJECT_BINARY_DIR}/masterconfig.ini - COPYONLY - ) -endif() +set(INI_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini") +foreach(ini ${INI_FILES}) + if (NOT EXISTS ${PROJECT_BINARY_DIR}/${ini}) + configure_file( + ${CMAKE_SOURCE_DIR}/resources/${ini} ${PROJECT_BINARY_DIR}/${ini} + COPYONLY + ) + endif() +endforeach() -# Copy files to output -configure_file("${CMAKE_SOURCE_DIR}/vanity/CREDITS.md" "${CMAKE_BINARY_DIR}/vanity/CREDITS.md" COPYONLY) -configure_file("${CMAKE_SOURCE_DIR}/vanity/INFO.md" "${CMAKE_BINARY_DIR}/vanity/INFO.md" COPYONLY) -configure_file("${CMAKE_SOURCE_DIR}/vanity/TESTAMENT.md" "${CMAKE_BINARY_DIR}/vanity/TESTAMENT.md" COPYONLY) -configure_file("${CMAKE_SOURCE_DIR}/vanity/NPC.xml" "${CMAKE_BINARY_DIR}/vanity/NPC.xml" COPYONLY) +# Copy vanity files on first build +set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml") +foreach(file ${VANITY_FILES}) + configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY) +endforeach() # Move our migrations for MasterServer to run file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/) file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql) -foreach (file ${SQL_FILES}) - get_filename_component(file ${file} NAME) - if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/${file}) - configure_file( - ${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/${file} - COPYONLY - ) - endif() +foreach(file ${SQL_FILES}) + get_filename_component(file ${file} NAME) + if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/${file}) + configure_file( + ${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/${file} + COPYONLY + ) + endif() endforeach() -# 3rdparty includes -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/raknet/Source/) -if(APPLE) - include_directories(/usr/local/include/) -endif(APPLE) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include) +# Create our list of include directories +set(INCLUDED_DIRECTORIES + "dCommon" + "dChatFilter" + "dGame" + "dGame/dBehaviors" + "dGame/dComponents" + "dGame/dGameMessages" + "dGame/dInventory" + "dGame/dMission" + "dGame/dEntity" + "dGame/dUtilities" + "dPhysics" + "dZoneManager" + "dDatabase" + "dDatabase/Tables" + "dNet" + "dScripts" + + "thirdparty/raknet/Source" + "thirdparty/tinyxml2" + "thirdparty/recastnavigation/Recast/Include" + "thirdparty/recastnavigation/Detour/Include" + "thirdparty/SQLite" + "thirdparty/cpplinq" + ) + +# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux) +if (APPLE) + include_directories("/usr/local/include/") +endif() + +if (WIN32) + set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include") +elseif (UNIX) + set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt") + set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt") +endif() + include_directories(${ZLIB_INCLUDE_DIRS}) - -# Bcrypt -if (NOT WIN32) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt) -else () -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include) -endif () - -# Our includes +# Add binary directory as an include directory include_directories(${PROJECT_BINARY_DIR}) -include_directories(${PROJECT_SOURCE_DIR}/dChatFilter/) -include_directories(${PROJECT_SOURCE_DIR}/dCommon/) -include_directories(${PROJECT_SOURCE_DIR}/dGame/) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dBehaviors) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dComponents) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dGameMessages) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dInventory) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dMission) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dEntity) -include_directories(${PROJECT_SOURCE_DIR}/dGame/dUtilities) -include_directories(${PROJECT_SOURCE_DIR}/dPhysics/) -include_directories(${PROJECT_SOURCE_DIR}/dZoneManager/) -include_directories(${PROJECT_SOURCE_DIR}/dDatabase/) -include_directories(${PROJECT_SOURCE_DIR}/dDatabase/Tables/) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/SQLite/) -include_directories(${PROJECT_SOURCE_DIR}/thirdparty/cpplinq/) -include_directories(${PROJECT_SOURCE_DIR}/dNet/) -include_directories(${PROJECT_SOURCE_DIR}/dScripts/) -# Lib folders: +# Actually include the directories from our list +foreach (dir ${INCLUDED_DIRECTORIES}) + include_directories(${PROJECT_SOURCE_DIR}/${dir}) +endforeach() + +# Add linking directories: link_directories(${PROJECT_BINARY_DIR}) -# Third-Party libraries +# Load all of our third party directories add_subdirectory(thirdparty) -# Source Code +# Glob together all headers that need to be precompiled file( -GLOB SOURCES -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dWorldServer/*.cpp -) - -# Source Code for AuthServer -file( -GLOB SOURCES_AUTH -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dAuthServer/*.cpp -) - -# Source Code for MasterServer -file( -GLOB SOURCES_MASTER -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dMasterServer/*.cpp -) - -# Source Code for ChatServer -file( -GLOB SOURCES_CHAT -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dChatServer/*.cpp -) - -# Source Code for dCommon -file( -GLOB SOURCES_DCOMMON -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dCommon/*.cpp -) - -# Source Code for dChatFilter -file( -GLOB SOURCES_DCHATFILTER -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dChatFilter/*.cpp -) - -# Source Code for dDatabase -file( -GLOB SOURCES_DDATABASE -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dDatabase/*.cpp -${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.cpp + GLOB HEADERS_DDATABASE + LIST_DIRECTORIES false + ${PROJECT_SOURCE_DIR}/dDatabase/*.h + ${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.h + ${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h ) file( - GLOB HEADERS_DDATABASE - LIST_DIRECTORIES false - ${PROJECT_SOURCE_DIR}/dDatabase/*.h - ${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.h - ${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h + GLOB HEADERS_DZONEMANAGER + LIST_DIRECTORIES false + ${PROJECT_SOURCE_DIR}/dZoneManager/*.h ) file( - GLOB HEADERS_DZONEMANAGER - LIST_DIRECTORIES false - ${PROJECT_SOURCE_DIR}/dZoneManager/*.h + GLOB HEADERS_DCOMMON + LIST_DIRECTORIES false + ${PROJECT_SOURCE_DIR}/dCommon/*.h ) file( - GLOB HEADERS_DCOMMON - LIST_DIRECTORIES false - ${PROJECT_SOURCE_DIR}/dCommon/*.h + GLOB HEADERS_DGAME + LIST_DIRECTORIES false + ${PROJECT_SOURCE_DIR}/dGame/Entity.h + ${PROJECT_SOURCE_DIR}/dGame/dGameMessages/GameMessages.h + ${PROJECT_SOURCE_DIR}/dGame/EntityManager.h + ${PROJECT_SOURCE_DIR}/dScripts/CppScripts.h ) -file( - GLOB HEADERS_DGAME - LIST_DIRECTORIES false - ${PROJECT_SOURCE_DIR}/dGame/Entity.h - ${PROJECT_SOURCE_DIR}/dGame/dGameMessages/GameMessages.h - ${PROJECT_SOURCE_DIR}/dGame/EntityManager.h - ${PROJECT_SOURCE_DIR}/dScripts/CppScripts.h -) +# Add our library subdirectories for creation of the library object +add_subdirectory(dCommon) +add_subdirectory(dDatabase) +add_subdirectory(dChatFilter) +add_subdirectory(dNet) +add_subdirectory(dScripts) # Add for dGame to use +add_subdirectory(dGame) +add_subdirectory(dZoneManager) +add_subdirectory(dPhysics) -# Source Code for dNet -file( -GLOB SOURCES_DNET -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dNet/*.cpp -) +# Create a list of common libraries shared between all binaries +set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp") -# Source Code for dGame -file( -GLOB SOURCES_DGAME -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dGame/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dBehaviors/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dComponents/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dGameMessages/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dInventory/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dMission/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dEntity/*.cpp -${PROJECT_SOURCE_DIR}/dGame/dUtilities/*.cpp -${PROJECT_SOURCE_DIR}/dScripts/*.cpp -) +# Add platform specific common libraries +if (UNIX) + set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "dl" "pthread") -# Source Code for dZoneManager -file( -GLOB SOURCES_DZM -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dZoneManager/*.cpp -) + if (NOT APPLE AND __include_backtrace__) + set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "backtrace") + endif() +endif() -# Source Code for dPhysics -file( -GLOB SOURCES_DPHYSICS -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${PROJECT_SOURCE_DIR}/dPhysics/*.cpp -) +add_subdirectory(tests) -if(MSVC) - # Skip warning for invalid conversion from size_t to uint32_t for all targets below for now - add_compile_options("/wd4267") -endif(MSVC) +# Include all of our binary directories +add_subdirectory(dWorldServer) +add_subdirectory(dAuthServer) +add_subdirectory(dChatServer) +add_subdirectory(dMasterServer) # Add MasterServer last so it can rely on the other binaries -# Our static libraries: -add_library(dCommon ${SOURCES_DCOMMON}) -add_library(dChatFilter ${SOURCES_DCHATFILTER}) -add_library(dDatabase ${SOURCES_DDATABASE}) -add_library(dNet ${SOURCES_DNET}) -add_library(dGame ${SOURCES_DGAME}) -add_library(dZoneManager ${SOURCES_DZM}) -add_library(dPhysics ${SOURCES_DPHYSICS}) -target_link_libraries(dDatabase sqlite3) -target_link_libraries(dNet dCommon) #Needed because otherwise linker errors occur. -target_link_libraries(dCommon ZLIB::ZLIB) -target_link_libraries(dCommon libbcrypt) -target_link_libraries(dDatabase mariadbConnCpp) -target_link_libraries(dNet dDatabase) -target_link_libraries(dGame dDatabase) -target_link_libraries(dChatFilter dDatabase) - -if(WIN32) -target_link_libraries(raknet ws2_32) -endif(WIN32) - -# Our executables: -add_executable(WorldServer ${SOURCES}) -add_executable(AuthServer ${SOURCES_AUTH}) -add_executable(MasterServer ${SOURCES_MASTER}) -add_executable(ChatServer ${SOURCES_CHAT}) - -# Add out precompiled headers +# Add our precompiled headers target_precompile_headers( - dGame PRIVATE - ${HEADERS_DGAME} + dGame PRIVATE + ${HEADERS_DGAME} ) target_precompile_headers( - dZoneManager PRIVATE - ${HEADERS_DZONEMANAGER} + dZoneManager PRIVATE + ${HEADERS_DZONEMANAGER} ) # Need to specify to use the CXX compiler language here or else we get errors including . target_precompile_headers( - dDatabase PRIVATE - "$<$:${HEADERS_DDATABASE}>" + dDatabase PRIVATE + "$<$:${HEADERS_DDATABASE}>" ) target_precompile_headers( - dCommon PRIVATE - ${HEADERS_DCOMMON} + dCommon PRIVATE + ${HEADERS_DCOMMON} ) target_precompile_headers( - tinyxml2 PRIVATE - "$<$:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>" -) - -# Target libraries to link to: -target_link_libraries(WorldServer dCommon) -target_link_libraries(WorldServer dChatFilter) -target_link_libraries(WorldServer dDatabase) -target_link_libraries(WorldServer dNet) -target_link_libraries(WorldServer dGame) -target_link_libraries(WorldServer dZoneManager) -target_link_libraries(WorldServer dPhysics) -target_link_libraries(WorldServer detour) -target_link_libraries(WorldServer recast) -target_link_libraries(WorldServer raknet) -target_link_libraries(WorldServer mariadbConnCpp) -if(UNIX) -if(NOT APPLE AND __include_backtrace__) -target_link_libraries(WorldServer backtrace) -target_link_libraries(MasterServer backtrace) -target_link_libraries(AuthServer backtrace) -target_link_libraries(ChatServer backtrace) -endif() - -endif(UNIX) -target_link_libraries(WorldServer tinyxml2) - -# Target libraries for Auth: -target_link_libraries(AuthServer dCommon) -target_link_libraries(AuthServer dDatabase) -target_link_libraries(AuthServer dNet) -target_link_libraries(AuthServer raknet) -target_link_libraries(AuthServer mariadbConnCpp) -if(UNIX) -target_link_libraries(AuthServer pthread) -target_link_libraries(AuthServer dl) -endif(UNIX) - -# Target libraries for Master: -target_link_libraries(MasterServer dCommon) -target_link_libraries(MasterServer dDatabase) -target_link_libraries(MasterServer dNet) -target_link_libraries(MasterServer raknet) -target_link_libraries(MasterServer mariadbConnCpp) -if(UNIX) -target_link_libraries(MasterServer pthread) -target_link_libraries(MasterServer dl) -endif(UNIX) - -# Target libraries for Chat: -target_link_libraries(ChatServer dCommon) -target_link_libraries(ChatServer dChatFilter) -target_link_libraries(ChatServer dDatabase) -target_link_libraries(ChatServer dNet) -target_link_libraries(ChatServer raknet) -target_link_libraries(ChatServer mariadbConnCpp) -if(UNIX) -target_link_libraries(ChatServer pthread) -target_link_libraries(ChatServer dl) -endif(UNIX) - -# Compiler flags: -# Disabled deprecated warnings as the MySQL includes have deprecated code in them. -# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent. -# Disabled no-register -# Disabled unknown pragmas because Linux doesn't understand Windows pragmas. -if(UNIX) - if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC") - endif() - if (__dynamic) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic") - endif() - if (__ggdb) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb") - endif() -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC") -endif(UNIX) - -if(WIN32) -add_dependencies(MasterServer WorldServer) -add_dependencies(MasterServer AuthServer) -add_dependencies(MasterServer ChatServer) -endif() - -# Finally, add the tests -add_subdirectory(tests) - + tinyxml2 PRIVATE + "$<$:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>" +) \ No newline at end of file diff --git a/dAuthServer/CMakeLists.txt b/dAuthServer/CMakeLists.txt new file mode 100644 index 00000000..353f2a54 --- /dev/null +++ b/dAuthServer/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DAUTHSERVER_SOURCES "AuthServer.cpp") + +add_executable(AuthServer ${DAUTHSERVER_SOURCES}) +target_link_libraries(AuthServer ${COMMON_LIBRARIES}) diff --git a/dChatFilter/CMakeLists.txt b/dChatFilter/CMakeLists.txt new file mode 100644 index 00000000..24b5e428 --- /dev/null +++ b/dChatFilter/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DCHATFILTER_SOURCES "dChatFilter.cpp") + +add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES}) +target_link_libraries(dChatFilter dDatabase) diff --git a/dChatServer/CMakeLists.txt b/dChatServer/CMakeLists.txt new file mode 100644 index 00000000..948593fb --- /dev/null +++ b/dChatServer/CMakeLists.txt @@ -0,0 +1,6 @@ +set(DCHATSERVER_SOURCES "ChatPacketHandler.cpp" + "ChatServer.cpp" + "PlayerContainer.cpp") + +add_executable(ChatServer ${DCHATSERVER_SOURCES}) +target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter) diff --git a/dCommon/CMakeLists.txt b/dCommon/CMakeLists.txt new file mode 100644 index 00000000..7e047a9c --- /dev/null +++ b/dCommon/CMakeLists.txt @@ -0,0 +1,26 @@ +set(DCOMMON_SOURCES "AMFFormat.cpp" + "AMFFormat_BitStream.cpp" + "BinaryIO.cpp" + "dConfig.cpp" + "Diagnostics.cpp" + "dLogger.cpp" + "GeneralUtils.cpp" + "LDFFormat.cpp" + "MD5.cpp" + "Metrics.cpp" + "NiPoint3.cpp" + "NiQuaternion.cpp" + "SHA512.cpp" + "Type.cpp" + "ZCompression.cpp") + +include_directories(${PROJECT_SOURCE_DIR}/dCommon/) + +add_library(dCommon STATIC ${DCOMMON_SOURCES}) + +target_link_libraries(dCommon libbcrypt) + +if (UNIX) + find_package(ZLIB REQUIRED) + target_link_libraries(dCommon ZLIB::ZLIB) +endif() diff --git a/dCommon/ZCompression.cpp b/dCommon/ZCompression.cpp index 3a66323d..28588bb8 100644 --- a/dCommon/ZCompression.cpp +++ b/dCommon/ZCompression.cpp @@ -1,5 +1,7 @@ #include "ZCompression.h" +#ifndef _WIN32 + #include namespace ZCompression @@ -70,4 +72,6 @@ namespace ZCompression return(nRet); // -1 or len of output */ } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/dCommon/ZCompression.h b/dCommon/ZCompression.h index ec870fb8..6db2a600 100644 --- a/dCommon/ZCompression.h +++ b/dCommon/ZCompression.h @@ -2,6 +2,10 @@ #include +#include "dPlatforms.h" + +#ifndef DARKFLAME_PLATFORM_WIN32 + namespace ZCompression { int32_t GetMaxCompressedLength(int32_t nLenSrc); @@ -10,3 +14,5 @@ namespace ZCompression int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr); } + +#endif diff --git a/dCommon/dPlatforms.h b/dCommon/dPlatforms.h new file mode 100644 index 00000000..d19e8121 --- /dev/null +++ b/dCommon/dPlatforms.h @@ -0,0 +1,29 @@ +#pragma once + +#if defined(_WIN32) + #define DARKFLAME_PLATFORM_WIN32 +#elif defined(__APPLE__) && defined(__MACH__) + #include + #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + #define DARKFLAME_PLATFORM_IOS + #elif TARGET_OS_MAC + #define DARKFLAME_PLATFORM_MACOS + #else + #error unknown Apple operating system + #endif +#elif defined(__unix__) + #define DARKFLAME_PLATFORM_UNIX + #if defined(__ANDROID__) + #define DARKFLAME_PLATFORM_ANDROID + #elif defined(__linux__) + #define DARKFLAME_PLATFORM_LINUX + #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + #define DARKFLAME_PLATFORM_FREEBSD + #elif defined(__CYGWIN__) + #define DARKFLAME_PLATFORM_CYGWIN + #else + #error unknown unix operating system + #endif +#else + #error unknown operating system +#endif \ No newline at end of file diff --git a/dDatabase/CMakeLists.txt b/dDatabase/CMakeLists.txt new file mode 100644 index 00000000..9e55fbe2 --- /dev/null +++ b/dDatabase/CMakeLists.txt @@ -0,0 +1,13 @@ +set(DDATABASE_SOURCES "CDClientDatabase.cpp" + "CDClientManager.cpp" + "Database.cpp" + "MigrationRunner.cpp") + +add_subdirectory(Tables) + +foreach(file ${DDATABASE_TABLES_SOURCES}) + set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Tables/${file}") +endforeach() + +add_library(dDatabase STATIC ${DDATABASE_SOURCES}) +target_link_libraries(dDatabase sqlite3 mariadbConnCpp) diff --git a/dDatabase/Tables/CMakeLists.txt b/dDatabase/Tables/CMakeLists.txt new file mode 100644 index 00000000..b6a02b02 --- /dev/null +++ b/dDatabase/Tables/CMakeLists.txt @@ -0,0 +1,38 @@ +set(DDATABASE_TABLES_SOURCES "CDActivitiesTable.cpp" + "CDActivityRewardsTable.cpp" + "CDAnimationsTable.cpp" + "CDBehaviorParameterTable.cpp" + "CDBehaviorTemplateTable.cpp" + "CDBrickIDTableTable.cpp" + "CDComponentsRegistryTable.cpp" + "CDCurrencyTableTable.cpp" + "CDDestructibleComponentTable.cpp" + "CDEmoteTable.cpp" + "CDFeatureGatingTable.cpp" + "CDInventoryComponentTable.cpp" + "CDItemComponentTable.cpp" + "CDItemSetSkillsTable.cpp" + "CDItemSetsTable.cpp" + "CDLevelProgressionLookupTable.cpp" + "CDLootMatrixTable.cpp" + "CDLootTableTable.cpp" + "CDMissionEmailTable.cpp" + "CDMissionNPCComponentTable.cpp" + "CDMissionsTable.cpp" + "CDMissionTasksTable.cpp" + "CDMovementAIComponentTable.cpp" + "CDObjectSkillsTable.cpp" + "CDObjectsTable.cpp" + "CDPackageComponentTable.cpp" + "CDPhysicsComponentTable.cpp" + "CDPropertyEntranceComponentTable.cpp" + "CDPropertyTemplateTable.cpp" + "CDProximityMonitorComponentTable.cpp" + "CDRailActivatorComponent.cpp" + "CDRarityTableTable.cpp" + "CDRebuildComponentTable.cpp" + "CDRewardsTable.cpp" + "CDScriptComponentTable.cpp" + "CDSkillBehaviorTable.cpp" + "CDVendorComponentTable.cpp" + "CDZoneTableTable.cpp" PARENT_SCOPE) diff --git a/dGame/CMakeLists.txt b/dGame/CMakeLists.txt new file mode 100644 index 00000000..5acdba31 --- /dev/null +++ b/dGame/CMakeLists.txt @@ -0,0 +1,59 @@ +set(DGAME_SOURCES "Character.cpp" + "Entity.cpp" + "EntityManager.cpp" + "LeaderboardManager.cpp" + "Player.cpp" + "TeamManager.cpp" + "TradingManager.cpp" + "User.cpp" + "UserManager.cpp") + +add_subdirectory(dBehaviors) + +foreach(file ${DGAME_DBEHAVIORS_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dBehaviors/${file}") +endforeach() + +add_subdirectory(dComponents) + +foreach(file ${DGAME_DCOMPONENTS_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dComponents/${file}") +endforeach() + +add_subdirectory(dEntity) + +foreach(file ${DGAME_DENTITY_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dEntity/${file}") +endforeach() + +add_subdirectory(dGameMessages) + +foreach(file ${DGAME_DGAMEMESSAGES_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dGameMessages/${file}") +endforeach() + +add_subdirectory(dInventory) + +foreach(file ${DGAME_DINVENTORY_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dInventory/${file}") +endforeach() + +add_subdirectory(dMission) + +foreach(file ${DGAME_DMISSION_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dMission/${file}") +endforeach() + +add_subdirectory(dUtilities) + +foreach(file ${DGAME_DUTILITIES_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "dUtilities/${file}") +endforeach() + +foreach(file ${DSCRIPT_SOURCES}) + set(DGAME_SOURCES ${DGAME_SOURCES} "${PROJECT_SOURCE_DIR}/dScripts/${file}") +endforeach() + +add_library(dGame STATIC ${DGAME_SOURCES}) + +target_link_libraries(dGame dDatabase) diff --git a/dGame/dBehaviors/CMakeLists.txt b/dGame/dBehaviors/CMakeLists.txt new file mode 100644 index 00000000..fe8e89b8 --- /dev/null +++ b/dGame/dBehaviors/CMakeLists.txt @@ -0,0 +1,51 @@ +set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp" + "AndBehavior.cpp" + "ApplyBuffBehavior.cpp" + "AreaOfEffectBehavior.cpp" + "AttackDelayBehavior.cpp" + "BasicAttackBehavior.cpp" + "Behavior.cpp" + "BehaviorBranchContext.cpp" + "BehaviorContext.cpp" + "BehaviorTemplates.cpp" + "BlockBehavior.cpp" + "BuffBehavior.cpp" + "CarBoostBehavior.cpp" + "ChainBehavior.cpp" + "ChangeOrientationBehavior.cpp" + "ChargeUpBehavior.cpp" + "ClearTargetBehavior.cpp" + "DamageAbsorptionBehavior.cpp" + "DamageReductionBehavior.cpp" + "DurationBehavior.cpp" + "EmptyBehavior.cpp" + "EndBehavior.cpp" + "ForceMovementBehavior.cpp" + "HealBehavior.cpp" + "ImaginationBehavior.cpp" + "ImmunityBehavior.cpp" + "InterruptBehavior.cpp" + "JetPackBehavior.cpp" + "KnockbackBehavior.cpp" + "LootBuffBehavior.cpp" + "MovementSwitchBehavior.cpp" + "NpcCombatSkillBehavior.cpp" + "OverTimeBehavior.cpp" + "PlayEffectBehavior.cpp" + "ProjectileAttackBehavior.cpp" + "PullToPointBehavior.cpp" + "RepairBehavior.cpp" + "SkillCastFailedBehavior.cpp" + "SkillEventBehavior.cpp" + "SpawnBehavior.cpp" + "SpawnQuickbuildBehavior.cpp" + "SpeedBehavior.cpp" + "StartBehavior.cpp" + "StunBehavior.cpp" + "SwitchBehavior.cpp" + "SwitchMultipleBehavior.cpp" + "TacArcBehavior.cpp" + "TargetCasterBehavior.cpp" + "TauntBehavior.cpp" + "VentureVisionBehavior.cpp" + "VerifyBehavior.cpp" PARENT_SCOPE) diff --git a/dGame/dComponents/CMakeLists.txt b/dGame/dComponents/CMakeLists.txt new file mode 100644 index 00000000..706395ea --- /dev/null +++ b/dGame/dComponents/CMakeLists.txt @@ -0,0 +1,40 @@ +set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp" + "BouncerComponent.cpp" + "BuffComponent.cpp" + "BuildBorderComponent.cpp" + "CharacterComponent.cpp" + "Component.cpp" + "ControllablePhysicsComponent.cpp" + "DestroyableComponent.cpp" + "InventoryComponent.cpp" + "LUPExhibitComponent.cpp" + "MissionComponent.cpp" + "MissionOfferComponent.cpp" + "ModelComponent.cpp" + "ModuleAssemblyComponent.cpp" + "MovementAIComponent.cpp" + "MovingPlatformComponent.cpp" + "PetComponent.cpp" + "PhantomPhysicsComponent.cpp" + "PossessableComponent.cpp" + "PossessorComponent.cpp" + "PropertyComponent.cpp" + "PropertyEntranceComponent.cpp" + "PropertyManagementComponent.cpp" + "PropertyVendorComponent.cpp" + "ProximityMonitorComponent.cpp" + "RacingControlComponent.cpp" + "RailActivatorComponent.cpp" + "RebuildComponent.cpp" + "RenderComponent.cpp" + "RigidbodyPhantomPhysicsComponent.cpp" + "RocketLaunchLupComponent.cpp" + "RocketLaunchpadControlComponent.cpp" + "ScriptedActivityComponent.cpp" + "ShootingGalleryComponent.cpp" + "SimplePhysicsComponent.cpp" + "SkillComponent.cpp" + "SoundTriggerComponent.cpp" + "SwitchComponent.cpp" + "VehiclePhysicsComponent.cpp" + "VendorComponent.cpp" PARENT_SCOPE) diff --git a/dGame/dEntity/CMakeLists.txt b/dGame/dEntity/CMakeLists.txt new file mode 100644 index 00000000..4bb49799 --- /dev/null +++ b/dGame/dEntity/CMakeLists.txt @@ -0,0 +1,2 @@ +set(DGAME_DENTITY_SOURCES "EntityCallbackTimer.cpp" + "EntityTimer.cpp" PARENT_SCOPE) diff --git a/dGame/dGameMessages/CMakeLists.txt b/dGame/dGameMessages/CMakeLists.txt new file mode 100644 index 00000000..3c3cb53f --- /dev/null +++ b/dGame/dGameMessages/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DGAME_DGAMEMESSAGES_SOURCES "GameMessageHandler.cpp" + "GameMessages.cpp" + "PropertyDataMessage.cpp" + "PropertySelectQueryProperty.cpp" PARENT_SCOPE) diff --git a/dGame/dInventory/CMakeLists.txt b/dGame/dInventory/CMakeLists.txt new file mode 100644 index 00000000..60cfca75 --- /dev/null +++ b/dGame/dInventory/CMakeLists.txt @@ -0,0 +1,5 @@ +set(DGAME_DINVENTORY_SOURCES "EquippedItem.cpp" + "Inventory.cpp" + "Item.cpp" + "ItemSet.cpp" + "ItemSetPassiveAbility.cpp" PARENT_SCOPE) diff --git a/dGame/dMission/CMakeLists.txt b/dGame/dMission/CMakeLists.txt new file mode 100644 index 00000000..652c3cb2 --- /dev/null +++ b/dGame/dMission/CMakeLists.txt @@ -0,0 +1,3 @@ +set(DGAME_DMISSION_SOURCES "Mission.cpp" + "MissionPrerequisites.cpp" + "MissionTask.cpp" PARENT_SCOPE) diff --git a/dGame/dUtilities/CMakeLists.txt b/dGame/dUtilities/CMakeLists.txt new file mode 100644 index 00000000..0c848bf4 --- /dev/null +++ b/dGame/dUtilities/CMakeLists.txt @@ -0,0 +1,9 @@ +set(DGAME_DUTILITIES_SOURCES "BrickDatabase.cpp" + "dLocale.cpp" + "GameConfig.cpp" + "GUID.cpp" + "Loot.cpp" + "Mail.cpp" + "Preconditions.cpp" + "SlashCommandHandler.cpp" + "VanityUtilities.cpp" PARENT_SCOPE) diff --git a/dMasterServer/CMakeLists.txt b/dMasterServer/CMakeLists.txt new file mode 100644 index 00000000..08fc63db --- /dev/null +++ b/dMasterServer/CMakeLists.txt @@ -0,0 +1,10 @@ +set(DMASTERSERVER_SOURCES "InstanceManager.cpp" + "MasterServer.cpp" + "ObjectIDManager.cpp") + +add_executable(MasterServer ${DMASTERSERVER_SOURCES}) +target_link_libraries(MasterServer ${COMMON_LIBRARIES}) + +if(WIN32) + add_dependencies(MasterServer WorldServer AuthServer ChatServer) +endif() diff --git a/dNet/CMakeLists.txt b/dNet/CMakeLists.txt new file mode 100644 index 00000000..938c0449 --- /dev/null +++ b/dNet/CMakeLists.txt @@ -0,0 +1,11 @@ +set(DNET_SOURCES "AuthPackets.cpp" + "ChatPackets.cpp" + "ClientPackets.cpp" + "dServer.cpp" + "MasterPackets.cpp" + "PacketUtils.cpp" + "WorldPackets.cpp" + "ZoneInstanceManager.cpp") + +add_library(dNet STATIC ${DNET_SOURCES}) +target_link_libraries(dNet dCommon dDatabase) diff --git a/dPhysics/CMakeLists.txt b/dPhysics/CMakeLists.txt new file mode 100644 index 00000000..383393cc --- /dev/null +++ b/dPhysics/CMakeLists.txt @@ -0,0 +1,9 @@ +set(DPHYSICS_SOURCES "dpCollisionChecks.cpp" + "dpEntity.cpp" + "dpGrid.cpp" + "dpShapeBase.cpp" + "dpShapeBox.cpp" + "dpShapeSphere.cpp" + "dpWorld.cpp") + +add_library(dPhysics STATIC ${DPHYSICS_SOURCES}) diff --git a/dScripts/CMakeLists.txt b/dScripts/CMakeLists.txt new file mode 100644 index 00000000..1fa177ba --- /dev/null +++ b/dScripts/CMakeLists.txt @@ -0,0 +1,253 @@ +set(DSCRIPT_SOURCES "ActivityManager.cpp" + "ActMine.cpp" + "ActNinjaTurret.cpp" + "ActParadoxPipeFix.cpp" + "ActPlayerDeathTrigger.cpp" + "ActSharkPlayerDeathTrigger.cpp" + "ActVehicleDeathTrigger.cpp" + "AgBugsprayer.cpp" + "AgBusDoor.cpp" + "AgCagedBricksServer.cpp" + "AgDarkSpiderling.cpp" + "AgFans.cpp" + "AgImagSmashable.cpp" + "AgJetEffectServer.cpp" + "AgLaserSensorServer.cpp" + "AgMonumentBirds.cpp" + "AgMonumentLaserServer.cpp" + "AgMonumentRaceCancel.cpp" + "AgMonumentRaceGoal.cpp" + "AgPicnicBlanket.cpp" + "AgPropGuard.cpp" + "AgPropguards.cpp" + "AgQbElevator.cpp" + "AgSalutingNpcs.cpp" + "AgShipPlayerDeathTrigger.cpp" + "AgShipPlayerShockServer.cpp" + "AgSpaceStuff.cpp" + "AgStagePlatforms.cpp" + "AgStromlingProperty.cpp" + "AgSurvivalBuffStation.cpp" + "AgSurvivalMech.cpp" + "AgSurvivalSpiderling.cpp" + "AgSurvivalStromling.cpp" + "AgTurret.cpp" + "AllCrateChicken.cpp" + "AmBlueX.cpp" + "AmBridge.cpp" + "AmConsoleTeleportServer.cpp" + "AmDarklingDragon.cpp" + "AmDarklingMech.cpp" + "AmDrawBridge.cpp" + "AmDropshipComputer.cpp" + "AmScrollReaderServer.cpp" + "AmShieldGenerator.cpp" + "AmShieldGeneratorQuickbuild.cpp" + "AmSkeletonEngineer.cpp" + "AmSkullkinDrill.cpp" + "AmSkullkinDrillStand.cpp" + "AmSkullkinTower.cpp" + "AmTeapotServer.cpp" + "AmTemplateSkillVolume.cpp" + "AnvilOfArmor.cpp" + "BankInteractServer.cpp" + "BaseConsoleTeleportServer.cpp" + "BaseEnemyApe.cpp" + "BaseEnemyMech.cpp" + "BaseFootRaceManager.cpp" + "BaseInteractDropLootServer.cpp" + "BasePropertyServer.cpp" + "BaseRandomServer.cpp" + "BaseSurvivalServer.cpp" + "BaseWavesGenericEnemy.cpp" + "BaseWavesServer.cpp" + "Binoculars.cpp" + "BootyDigServer.cpp" + "BossSpiderQueenEnemyServer.cpp" + "BuccaneerValiantShip.cpp" + "BurningTile.cpp" + "CatapultBaseServer.cpp" + "CatapultBouncerServer.cpp" + "CauldronOfLife.cpp" + "CavePrisonCage.cpp" + "ChooseYourDestinationNsToNt.cpp" + "ClRing.cpp" + "CppScripts.cpp" + "CrabServer.cpp" + "DamagingPets.cpp" + "Darkitect.cpp" + "DLUVanityNPC.cpp" + "EnemyNjBuff.cpp" + "EnemyRoninSpawner.cpp" + "EnemySkeletonSpawner.cpp" + "EnemySpiderSpawner.cpp" + "ExplodingAsset.cpp" + "FallingTile.cpp" + "FireFirstSkillonStartup.cpp" + "FlameJetServer.cpp" + "ForceVolumeServer.cpp" + "FountainOfImagination.cpp" + "FvBounceOverWall.cpp" + "FvBrickPuzzleServer.cpp" + "FvCandle.cpp" + "FvConsoleLeftQuickbuild.cpp" + "FvConsoleRightQuickbuild.cpp" + "FvDragonSmashingGolemQb.cpp" + "FvFacilityBrick.cpp" + "FvFlyingCreviceDragon.cpp" + "FvFong.cpp" + "FvFreeGfNinjas.cpp" + "FvHorsemenTrigger.cpp" + "FvMaelstromCavalry.cpp" + "FvMaelstromDragon.cpp" + "FvNinjaGuard.cpp" + "FvPandaServer.cpp" + "FvPandaSpawnerServer.cpp" + "FvPassThroughWall.cpp" + "FvRaceSmashEggImagineServer.cpp" + "GfApeSmashingQB.cpp" + "GfBanana.cpp" + "GfBananaCluster.cpp" + "GfCampfire.cpp" + "GfCaptainsCannon.cpp" + "GfJailkeepMission.cpp" + "GfJailWalls.cpp" + "GfOrgan.cpp" + "GfTikiTorch.cpp" + "GrowingFlower.cpp" + "HydrantBroken.cpp" + "HydrantSmashable.cpp" + "ImaginationBackpackHealServer.cpp" + "ImaginationShrineServer.cpp" + "ImgBrickConsoleQB.cpp" + "InstanceExitTransferPlayerToLastNonInstance.cpp" + "InvalidScript.cpp" + "LegoDieRoll.cpp" + "Lieutenant.cpp" + "MaestromExtracticatorServer.cpp" + "MailBoxServer.cpp" + "MastTeleport.cpp" + "MinigameTreasureChestServer.cpp" + "MonCoreNookDoors.cpp" + "MonCoreSmashableDoors.cpp" + "NjColeNPC.cpp" + "NjDragonEmblemChestServer.cpp" + "NjEarthDragonPetServer.cpp" + "NjEarthPetServer.cpp" + "NjGarmadonCelebration.cpp" + "NjhubLavaPlayerDeathTrigger.cpp" + "NjIceRailActivator.cpp" + "NjJayMissionItems.cpp" + "NjMonastryBossInstance.cpp" + "NjNPCMissionSpinjitzuServer.cpp" + "NjNyaMissionitems.cpp" + "NjRailActivatorsServer.cpp" + "NjRailPostServer.cpp" + "NjRailSwitch.cpp" + "NjScrollChestServer.cpp" + "NjWuNPC.cpp" + "NPCAddRemoveItem.cpp" + "NpcAgCourseStarter.cpp" + "NpcCowboyServer.cpp" + "NpcEpsilonServer.cpp" + "NpcNjAssistantServer.cpp" + "NpcNpSpacemanBob.cpp" + "NpcPirateServer.cpp" + "NpcWispServer.cpp" + "NsConcertChoiceBuild.cpp" + "NsConcertChoiceBuildManager.cpp" + "NsConcertInstrument.cpp" + "NsConcertQuickBuild.cpp" + "NsGetFactionMissionServer.cpp" + "NsJohnnyMissionServer.cpp" + "NsLegoClubDoor.cpp" + "NsLupTeleport.cpp" + "NsModularBuild.cpp" + "NsQbImaginationStatue.cpp" + "NsTokenConsoleServer.cpp" + "NtAssemblyTubeServer.cpp" + "NtBeamImaginationCollectors.cpp" + "NtCombatChallengeDummy.cpp" + "NtCombatChallengeExplodingDummy.cpp" + "NtCombatChallengeServer.cpp" + "NtConsoleTeleportServer.cpp" + "NtDarkitectRevealServer.cpp" + "NtDirtCloudServer.cpp" + "NtDukeServer.cpp" + "NtFactionSpyServer.cpp" + "NtHaelServer.cpp" + "NtImagBeamBuffer.cpp" + "NtOverbuildServer.cpp" + "NtParadoxPanelServer.cpp" + "NtParadoxTeleServer.cpp" + "NtSentinelWalkwayServer.cpp" + "NtSleepingGuard.cpp" + "NtVandaServer.cpp" + "NtVentureCannonServer.cpp" + "NtVentureSpeedPadServer.cpp" + "NtXRayServer.cpp" + "PersonalFortress.cpp" + "PetDigBuild.cpp" + "PetDigServer.cpp" + "PetFromDigServer.cpp" + "PetFromObjectServer.cpp" + "PropertyBankInteract.cpp" + "PropertyDeathPlane.cpp" + "PropertyDevice.cpp" + "PropertyFXDamage.cpp" + "PropertyPlatform.cpp" + "PrSeagullFly.cpp" + "PrWhistle.cpp" + "QbEnemyStunner.cpp" + "RaceImagineCrateServer.cpp" + "RaceImaginePowerup.cpp" + "RaceMaelstromGeiser.cpp" + "RaceSmashServer.cpp" + "RainOfArrows.cpp" + "RandomSpawnerFin.cpp" + "RandomSpawnerPit.cpp" + "RandomSpawnerStr.cpp" + "RandomSpawnerZip.cpp" + "RemoveRentalGear.cpp" + "RockHydrantBroken.cpp" + "RockHydrantSmashable.cpp" + "ScriptComponent.cpp" + "ScriptedPowerupSpawner.cpp" + "SGCannon.cpp" + "SpawnGryphonServer.cpp" + "SpawnLionServer.cpp" + "SpawnPetBaseServer.cpp" + "SpawnSaberCatServer.cpp" + "SpawnShrakeServer.cpp" + "SpawnStegoServer.cpp" + "SpecialImaginePowerupSpawner.cpp" + "SpiderBossTreasureChestServer.cpp" + "SsModularBuildServer.cpp" + "StinkyFishTarget.cpp" + "StoryBoxInteractServer.cpp" + "Sunflower.cpp" + "TokenConsoleServer.cpp" + "TouchMissionUpdateServer.cpp" + "TreasureChestDragonServer.cpp" + "TriggerAmbush.cpp" + "VeBricksampleServer.cpp" + "VeEpsilonServer.cpp" + "VeMech.cpp" + "VeMissionConsole.cpp" + "WaveBossApe.cpp" + "WaveBossHammerling.cpp" + "WaveBossHorsemen.cpp" + "WaveBossSpiderling.cpp" + "WhFans.cpp" + "WildAmbients.cpp" + "WishingWellServer.cpp" + "ZoneAgMedProperty.cpp" + "ZoneAgProperty.cpp" + "ZoneAgSpiderQueen.cpp" + "ZoneAgSurvival.cpp" + "ZoneFvProperty.cpp" + "ZoneGfProperty.cpp" + "ZoneNsMedProperty.cpp" + "ZoneNsProperty.cpp" + "ZoneNsWaves.cpp" + "ZoneSGServer.cpp" PARENT_SCOPE) diff --git a/dWorldServer/CMakeLists.txt b/dWorldServer/CMakeLists.txt new file mode 100644 index 00000000..3df808a2 --- /dev/null +++ b/dWorldServer/CMakeLists.txt @@ -0,0 +1,6 @@ +set(DWORLDSERVER_SOURCES "ObjectIDManager.cpp" + "PerformanceManager.cpp" + "WorldServer.cpp") + +add_executable(WorldServer ${DWORLDSERVER_SOURCES}) +target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics detour recast tinyxml2) diff --git a/dZoneManager/CMakeLists.txt b/dZoneManager/CMakeLists.txt new file mode 100644 index 00000000..1dd3841b --- /dev/null +++ b/dZoneManager/CMakeLists.txt @@ -0,0 +1,6 @@ +set(DZONEMANAGER_SOURCES "dZoneManager.cpp" + "Level.cpp" + "Spawner.cpp" + "Zone.cpp") + +add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 85f4bda4..b0e2c28d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,17 +1,13 @@ # create the testing file and list of tests create_test_sourcelist (Tests - CommonCxxTests.cpp - TestNiPoint3.cpp - TestLDFFormat.cpp + CommonCxxTests.cpp + TestNiPoint3.cpp + TestLDFFormat.cpp ) - + # add the executable add_executable (CommonCxxTests ${Tests}) -target_link_libraries(CommonCxxTests dCommon raknet) - -if(WIN32) - target_link_libraries(CommonCxxTests ws2_32) -endif(WIN32) +target_link_libraries(CommonCxxTests ${COMMON_LIBRARIES}) # remove the test driver source file set (TestsToRun ${Tests}) @@ -19,7 +15,7 @@ remove (TestsToRun CommonCxxTests.cpp) # Add all the ADD_TEST for each test foreach (test ${TestsToRun}) - get_filename_component (TName ${test} NAME_WE) - add_test (NAME ${TName} COMMAND CommonCxxTests ${TName}) - set_property(TEST ${TName} PROPERTY ENVIRONMENT CTEST_OUTPUT_ON_FAILURE=1) + get_filename_component (TName ${test} NAME_WE) + add_test (NAME ${TName} COMMAND CommonCxxTests ${TName}) + set_property(TEST ${TName} PROPERTY ENVIRONMENT CTEST_OUTPUT_ON_FAILURE=1) endforeach () diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index ce24ecd3..119ce4fd 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,50 +1,50 @@ # Source Code for raknet file( -GLOB SOURCES_RAKNET -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/raknet/Source/*.cpp + GLOB SOURCES_RAKNET + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/raknet/Source/*.cpp ) # Source Code for recast file( -GLOB SOURCES_RECAST -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Recast/Source/*.cpp + GLOB SOURCES_RECAST + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Recast/Source/*.cpp ) # Source Code for detour file( -GLOB SOURCES_DETOUR -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Detour/Source/*.cpp + GLOB SOURCES_DETOUR + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Detour/Source/*.cpp ) # Source Code for tinyxml2 file( -GLOB SOURCES_TINYXML2 -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/tinyxml2/tinyxml2.cpp + GLOB SOURCES_TINYXML2 + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/tinyxml2/tinyxml2.cpp ) # Source Code for libbcrypt file( -GLOB SOURCES_LIBBCRYPT -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c -${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c + GLOB SOURCES_LIBBCRYPT + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c ) file( -GLOB SOURCES_SQLITE3 -LIST_DIRECTORIES false -RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" -${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.cpp -${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.c + GLOB SOURCES_SQLITE3 + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.c ) # mariadb connector cpp @@ -147,7 +147,6 @@ else() # Build from source set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/RelWithDebInfo/${MARIADB_SHARED_LIBRARY_NAME}") set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}/$") set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb/RelWithDebInfo") - message(STATUS "1 ${CMAKE_SOURCE_DIR}") else() set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}") set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}") @@ -179,16 +178,19 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists. file(REMOVE "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.txt") endif() +# Create mariadb connector library object add_library(mariadbConnCpp SHARED IMPORTED GLOBAL) set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_LOCATION ${MARIADB_SHARED_LIBRARY_LOCATION}) + if(WIN32) set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_IMPLIB ${MARIADB_IMPLIB_LOCATION}) endif() + +# Add directories to include lists target_include_directories(mariadbConnCpp INTERFACE ${MARIADB_INCLUDE_DIR}) add_dependencies(mariadbConnCpp mariadb_connector_cpp) -# 3rdparty static libraries: -#add_library(zlib ${SOURCES_ZLIB}) +# Create our third party library objects add_library(raknet ${SOURCES_RAKNET}) add_library(tinyxml2 ${SOURCES_TINYXML2}) add_library(detour ${SOURCES_DETOUR}) @@ -196,11 +198,39 @@ add_library(recast ${SOURCES_RECAST}) add_library(libbcrypt ${SOURCES_LIBBCRYPT}) add_library(sqlite3 ${SOURCES_SQLITE3}) -if(UNIX) -target_link_libraries(sqlite3 pthread dl m) +if(WIN32) + # Link Win Sockets 2 to RakNet + target_link_libraries(raknet ws2_32) +elseif(UNIX) + # Add warning disable flags and link Unix libraries to sqlite3 + target_link_libraries(sqlite3 pthread dl m) -# -Wno-unused-result -Wno-unknown-pragmas -fpermissive -target_compile_options(sqlite3 PRIVATE "-Wno-return-local-addr" "-Wno-maybe-uninitialized") -target_compile_options(raknet PRIVATE "-Wno-write-strings" "-Wformat-overflow=0" "-Wformat=0") -target_compile_options(libbcrypt PRIVATE "-Wno-implicit-function-declaration" "-Wno-int-conversion") -endif(UNIX) \ No newline at end of file + # -Wno-unused-result -Wno-unknown-pragmas -fpermissive + target_compile_options(sqlite3 PRIVATE "-Wno-return-local-addr" "-Wno-maybe-uninitialized") + target_compile_options(raknet PRIVATE "-Wno-write-strings" "-Wformat-overflow=0" "-Wformat=0") + target_compile_options(libbcrypt PRIVATE "-Wno-implicit-function-declaration" "-Wno-int-conversion") +endif() + +# Download Backtrace if configured +if(UNIX AND NOT APPLE) + include(FetchContent) + if (__include_backtrace__ AND __compile_backtrace__) + FetchContent_Declare( + backtrace + GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git + ) + + FetchContent_MakeAvailable(backtrace) + + if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs) + set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind") + + execute_process( + COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}" + ) + endif() + + link_directories(${backtrace_SOURCE_DIR}/.libs/) + include_directories(${backtrace_SOURCE_DIR}) + endif() +endif() \ No newline at end of file From f5ae5aa13e34d2ed879497f9c8cf5592a213476d Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 16 Jul 2022 18:21:35 -0700 Subject: [PATCH 13/18] Address timers being iterated through poorly (#646) * Fix timers * Update Entity.cpp * Fix timers Fix timers Remove debug logs remove _dynamic * I like to move it move it --- dGame/Entity.cpp | 26 +++++++++++++++++++------- dGame/Entity.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 68277cd8..93fa0609 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1201,17 +1201,21 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { } void Entity::Update(const float deltaTime) { - for (int i = 0; i < m_Timers.size(); i++) { - m_Timers[i]->Update(deltaTime); - if (m_Timers[i]->GetTime() <= 0) { - const auto timerName = m_Timers[i]->GetName(); + uint32_t timerPosition; + timerPosition = 0; + while (timerPosition < m_Timers.size()) { + m_Timers[timerPosition]->Update(deltaTime); + if (m_Timers[timerPosition]->GetTime() <= 0) { + const auto timerName = m_Timers[timerPosition]->GetName(); - delete m_Timers[i]; - m_Timers.erase(m_Timers.begin() + i); + delete m_Timers[timerPosition]; + m_Timers.erase(m_Timers.begin() + timerPosition); for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { script->OnTimerDone(this, timerName); } + } else { + timerPosition++; } } @@ -1223,6 +1227,14 @@ void Entity::Update(const float deltaTime) { m_CallbackTimers.erase(m_CallbackTimers.begin() + i); } } + + // Add pending timers to the list of timers so they start next tick. + if (m_PendingTimers.size() > 0) { + for (auto namedTimer : m_PendingTimers) { + m_Timers.push_back(namedTimer); + } + m_PendingTimers.clear(); + } if (IsSleeping()) { @@ -1661,7 +1673,7 @@ void Entity::RemoveChild(Entity* child) { void Entity::AddTimer(std::string name, float time) { EntityTimer* timer = new EntityTimer(name, time); - m_Timers.push_back(timer); + m_PendingTimers.push_back(timer); } void Entity::AddCallbackTimer(float time, std::function callback) { diff --git a/dGame/Entity.h b/dGame/Entity.h index c804deaa..ca12b355 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -309,6 +309,7 @@ protected: std::unordered_map m_Components; //The int is the ID of the component std::vector m_Timers; + std::vector m_PendingTimers; std::vector m_CallbackTimers; bool m_ShouldDestroyAfterUpdate = false; From 9287e5bc4bd61fb469e90ef8c476d754a760df06 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Sat, 16 Jul 2022 20:36:09 -0500 Subject: [PATCH 14/18] Split itemType enum into it's own header (#647) * Split itemType enum into it's own header add mount item type * fix whitespace --- dCommon/dCommonVars.h | 27 ------------ dCommon/eItemType.h | 36 ++++++++++++++++ dGame/dComponents/InventoryComponent.cpp | 15 +++---- dGame/dComponents/InventoryComponent.h | 4 +- dGame/dInventory/Inventory.cpp | 52 ++++++++++++------------ 5 files changed, 74 insertions(+), 60 deletions(-) create mode 100644 dCommon/eItemType.h diff --git a/dCommon/dCommonVars.h b/dCommon/dCommonVars.h index e941413b..c458b9fb 100644 --- a/dCommon/dCommonVars.h +++ b/dCommon/dCommonVars.h @@ -440,33 +440,6 @@ enum eInventoryType : uint32_t { INVALID // made up, for internal use!!! }; -enum eItemType : int32_t { - ITEM_TYPE_UNKNOWN = -1, //!< An unknown item type - ITEM_TYPE_BRICK = 1, //!< A brick - ITEM_TYPE_HAT = 2, //!< A hat / head item - ITEM_TYPE_HAIR = 3, //!< A hair item - ITEM_TYPE_NECK = 4, //!< A neck item - ITEM_TYPE_LEFT_HAND = 5, //!< A left handed item - ITEM_TYPE_RIGHT_HAND = 6, //!< A right handed item - ITEM_TYPE_LEGS = 7, //!< A pants item - ITEM_TYPE_LEFT_TRINKET = 8, //!< A left handled trinket item - ITEM_TYPE_RIGHT_TRINKET = 9, //!< A right handed trinket item - ITEM_TYPE_BEHAVIOR = 10, //!< A behavior - ITEM_TYPE_PROPERTY = 11, //!< A property - ITEM_TYPE_MODEL = 12, //!< A model - ITEM_TYPE_COLLECTIBLE = 13, //!< A collectible item - ITEM_TYPE_CONSUMABLE = 14, //!< A consumable item - ITEM_TYPE_CHEST = 15, //!< A chest item - ITEM_TYPE_EGG = 16, //!< An egg - ITEM_TYPE_PET_FOOD = 17, //!< A pet food item - ITEM_TYPE_QUEST_OBJECT = 18, //!< A quest item - ITEM_TYPE_PET_INVENTORY_ITEM = 19, //!< A pet inventory item - ITEM_TYPE_PACKAGE = 20, //!< A package - ITEM_TYPE_LOOT_MODEL = 21, //!< A loot model - ITEM_TYPE_VEHICLE = 22, //!< A vehicle - ITEM_TYPE_CURRENCY = 23 //!< Currency -}; - enum eRebuildState : uint32_t { REBUILD_OPEN, REBUILD_COMPLETED = 2, diff --git a/dCommon/eItemType.h b/dCommon/eItemType.h new file mode 100644 index 00000000..453e8737 --- /dev/null +++ b/dCommon/eItemType.h @@ -0,0 +1,36 @@ +#pragma once + +#ifndef __EITEMTYPE__H__ +#define __EITEMTYPE__H__ + +#include + +enum class eItemType : int32_t { + ITEM_TYPE_UNKNOWN = -1, //!< An unknown item type + ITEM_TYPE_BRICK = 1, //!< A brick + ITEM_TYPE_HAT = 2, //!< A hat / head item + ITEM_TYPE_HAIR = 3, //!< A hair item + ITEM_TYPE_NECK = 4, //!< A neck item + ITEM_TYPE_LEFT_HAND = 5, //!< A left handed item + ITEM_TYPE_RIGHT_HAND = 6, //!< A right handed item + ITEM_TYPE_LEGS = 7, //!< A pants item + ITEM_TYPE_LEFT_TRINKET = 8, //!< A left handled trinket item + ITEM_TYPE_RIGHT_TRINKET = 9, //!< A right handed trinket item + ITEM_TYPE_BEHAVIOR = 10, //!< A behavior + ITEM_TYPE_PROPERTY = 11, //!< A property + ITEM_TYPE_MODEL = 12, //!< A model + ITEM_TYPE_COLLECTIBLE = 13, //!< A collectible item + ITEM_TYPE_CONSUMABLE = 14, //!< A consumable item + ITEM_TYPE_CHEST = 15, //!< A chest item + ITEM_TYPE_EGG = 16, //!< An egg + ITEM_TYPE_PET_FOOD = 17, //!< A pet food item + ITEM_TYPE_QUEST_OBJECT = 18, //!< A quest item + ITEM_TYPE_PET_INVENTORY_ITEM = 19, //!< A pet inventory item + ITEM_TYPE_PACKAGE = 20, //!< A package + ITEM_TYPE_LOOT_MODEL = 21, //!< A loot model + ITEM_TYPE_VEHICLE = 22, //!< A vehicle + ITEM_TYPE_CURRENCY = 23, //!< Currency + ITEM_TYPE_MOUNT = 24 //!< A Mount +}; + +#endif //!__EITEMTYPE__H__ \ No newline at end of file diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 8ae6e93f..0772482c 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -25,6 +25,7 @@ #include "PropertyManagementComponent.h" #include "DestroyableComponent.h" #include "dConfig.h" +#include "eItemType.h" InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) { @@ -1024,13 +1025,13 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) return; } - if (type == ITEM_TYPE_LOOT_MODEL || type == ITEM_TYPE_VEHICLE) + if (type == eItemType::ITEM_TYPE_LOOT_MODEL || type == eItemType::ITEM_TYPE_VEHICLE) { return; } } - if (type != ITEM_TYPE_LOOT_MODEL && type != ITEM_TYPE_MODEL) + if (type != eItemType::ITEM_TYPE_LOOT_MODEL && type != eItemType::ITEM_TYPE_MODEL) { if (!item->GetBound() && !item->GetPreconditionExpression()->Check(m_Parent)) { @@ -1411,15 +1412,15 @@ void InventoryComponent::RemoveDatabasePet(LWOOBJID id) BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type) { switch (type) { - case ITEM_TYPE_HAT: + case eItemType::ITEM_TYPE_HAT: return BehaviorSlot::Head; - case ITEM_TYPE_NECK: + case eItemType::ITEM_TYPE_NECK: return BehaviorSlot::Neck; - case ITEM_TYPE_LEFT_HAND: + case eItemType::ITEM_TYPE_LEFT_HAND: return BehaviorSlot::Offhand; - case ITEM_TYPE_RIGHT_HAND: + case eItemType::ITEM_TYPE_RIGHT_HAND: return BehaviorSlot::Primary; - case ITEM_TYPE_CONSUMABLE: + case eItemType::ITEM_TYPE_CONSUMABLE: return BehaviorSlot::Consumable; default: return BehaviorSlot::Invalid; diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 1fda5942..a7d3f8ea 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #ifndef INVENTORYCOMPONENT_H #define INVENTORYCOMPONENT_H @@ -25,6 +25,8 @@ class ItemSet; typedef std::map EquipmentMap; +enum class eItemType : int32_t; + /** * Handles the inventory of entity, including the items they possess and have equipped. An entity can have inventories * of different types, each type representing a different group of items, see `eInventoryType` for a list of diff --git a/dGame/dInventory/Inventory.cpp b/dGame/dInventory/Inventory.cpp index 6e8be6aa..53ff37b4 100644 --- a/dGame/dInventory/Inventory.cpp +++ b/dGame/dInventory/Inventory.cpp @@ -1,7 +1,8 @@ -#include "Inventory.h" +#include "Inventory.h" #include "GameMessages.h" #include "Game.h" #include "Item.h" +#include "eItemType.h" std::vector Inventory::m_GameMasterRestrictedItems = { 1727, // GM Only - JetPack @@ -274,40 +275,41 @@ eInventoryType Inventory::FindInventoryTypeForLot(const LOT lot) const auto itemType = static_cast(itemComponent.itemType); switch (itemType) { - case ITEM_TYPE_BRICK: + case eItemType::ITEM_TYPE_BRICK: return BRICKS; - case ITEM_TYPE_BEHAVIOR: + case eItemType::ITEM_TYPE_BEHAVIOR: return BEHAVIORS; - case ITEM_TYPE_PROPERTY: + case eItemType::ITEM_TYPE_PROPERTY: return PROPERTY_DEEDS; - case ITEM_TYPE_MODEL: - case ITEM_TYPE_VEHICLE: - case ITEM_TYPE_LOOT_MODEL: + case eItemType::ITEM_TYPE_MODEL: + case eItemType::ITEM_TYPE_VEHICLE: + case eItemType::ITEM_TYPE_LOOT_MODEL: + case eItemType::ITEM_TYPE_MOUNT: return MODELS; - case ITEM_TYPE_HAT: - case ITEM_TYPE_HAIR: - case ITEM_TYPE_NECK: - case ITEM_TYPE_LEFT_HAND: - case ITEM_TYPE_RIGHT_HAND: - case ITEM_TYPE_LEGS: - case ITEM_TYPE_LEFT_TRINKET: - case ITEM_TYPE_RIGHT_TRINKET: - case ITEM_TYPE_COLLECTIBLE: - case ITEM_TYPE_CONSUMABLE: - case ITEM_TYPE_CHEST: - case ITEM_TYPE_EGG: - case ITEM_TYPE_PET_FOOD: - case ITEM_TYPE_PET_INVENTORY_ITEM: - case ITEM_TYPE_PACKAGE: - case ITEM_TYPE_CURRENCY: + case eItemType::ITEM_TYPE_HAT: + case eItemType::ITEM_TYPE_HAIR: + case eItemType::ITEM_TYPE_NECK: + case eItemType::ITEM_TYPE_LEFT_HAND: + case eItemType::ITEM_TYPE_RIGHT_HAND: + case eItemType::ITEM_TYPE_LEGS: + case eItemType::ITEM_TYPE_LEFT_TRINKET: + case eItemType::ITEM_TYPE_RIGHT_TRINKET: + case eItemType::ITEM_TYPE_COLLECTIBLE: + case eItemType::ITEM_TYPE_CONSUMABLE: + case eItemType::ITEM_TYPE_CHEST: + case eItemType::ITEM_TYPE_EGG: + case eItemType::ITEM_TYPE_PET_FOOD: + case eItemType::ITEM_TYPE_PET_INVENTORY_ITEM: + case eItemType::ITEM_TYPE_PACKAGE: + case eItemType::ITEM_TYPE_CURRENCY: return ITEMS; - case ITEM_TYPE_QUEST_OBJECT: - case ITEM_TYPE_UNKNOWN: + case eItemType::ITEM_TYPE_QUEST_OBJECT: + case eItemType::ITEM_TYPE_UNKNOWN: default: return HIDDEN; } From 77d35019cc7258229a99934ed41d2efca48ccb88 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Sun, 17 Jul 2022 04:40:46 +0100 Subject: [PATCH 15/18] Replace the usage of RakString (#648) --- dChatServer/ChatPacketHandler.cpp | 22 +++++++-------- dChatServer/PlayerContainer.cpp | 26 +++++++++++------- dChatServer/PlayerContainer.h | 4 +-- dGame/dUtilities/SlashCommandHandler.cpp | 12 ++++++--- dMasterServer/MasterServer.cpp | 34 +++++++++++++++++------- dNet/MasterPackets.cpp | 12 ++++++--- dWorldServer/WorldServer.cpp | 29 +++++++++++++------- 7 files changed, 91 insertions(+), 48 deletions(-) diff --git a/dChatServer/ChatPacketHandler.cpp b/dChatServer/ChatPacketHandler.cpp index b84c3eef..4f055121 100644 --- a/dChatServer/ChatPacketHandler.cpp +++ b/dChatServer/ChatPacketHandler.cpp @@ -123,7 +123,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) { requestee.reset(new PlayerData()); // Setup the needed info since you can add a best friend offline. requestee->playerID = friendDataCandidate.friendID; - requestee->playerName = RakNet::RakString(friendDataCandidate.friendName.c_str()); + requestee->playerName = friendDataCandidate.friendName; requestee->zoneID = LWOZONEID(); FriendData requesteeFriendData{}; @@ -147,7 +147,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) { std::unique_ptr result(nameQuery->executeQuery()); requestee.reset(new PlayerData()); - requestee->playerName = RakNet::RakString(playerName.c_str()); + requestee->playerName = playerName; SendFriendResponse(requestor, requestee.get(), result->next() ? AddFriendResponseType::NOTONLINE : AddFriendResponseType::INVALIDCHARACTER); return; @@ -384,7 +384,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) if (playerContainer.GetIsMuted(sender)) return; - const auto senderName = std::string(sender->playerName.C_String()); + const auto senderName = std::string(sender->playerName.c_str()); inStream.SetReadOffset(0x14 * 8); @@ -407,7 +407,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) if (otherMember == nullptr) return; - const auto otherName = std::string(otherMember->playerName.C_String()); + const auto otherName = std::string(otherMember->playerName.c_str()); CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER); @@ -443,8 +443,8 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { if (playerContainer.GetIsMuted(goonA)) return; - std::string goonAName = goonA->playerName.C_String(); - std::string goonBName = goonB->playerName.C_String(); + std::string goonAName = goonA->playerName.c_str(); + std::string goonBName = goonB->playerName.c_str(); //To the sender: { @@ -720,7 +720,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) playerContainer.TeamStatusUpdate(team); - const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.C_String())); + const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str())); for (const auto memberId : team->memberIDs) { @@ -750,7 +750,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) //portion that will get routed: PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_TEAM_INVITE); - PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream); + PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); bitStream.Write(sender->playerID); SystemAddress sysAddr = receiver->sysAddr; @@ -936,7 +936,7 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_UPDATE_FRIEND_NOTIFY); bitStream.Write(notifyType); - std::string playerName = playerData->playerName.C_String(); + std::string playerName = playerData->playerName.c_str(); PacketUtils::WritePacketWString(playerName, 33, &bitStream); @@ -976,7 +976,7 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send //portion that will get routed: PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_REQUEST); - PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream); + PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); bitStream.Write(0); // This is a BFF flag however this is unused in live and does not have an implementation client side. SystemAddress sysAddr = receiver->sysAddr; @@ -996,7 +996,7 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen // For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver. bitStream.Write(responseCode != AddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS); // Then write the player name - PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream); + PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); // Then if this is an acceptance code, write the following extra info. if (responseCode == AddFriendResponseType::ACCEPTED) { bitStream.Write(sender->playerID); diff --git a/dChatServer/PlayerContainer.cpp b/dChatServer/PlayerContainer.cpp index c5da3a7f..1517153d 100644 --- a/dChatServer/PlayerContainer.cpp +++ b/dChatServer/PlayerContainer.cpp @@ -20,17 +20,25 @@ PlayerContainer::~PlayerContainer() { void PlayerContainer::InsertPlayer(Packet* packet) { CINSTREAM; PlayerData* data = new PlayerData(); + inStream.SetReadOffset(inStream.GetReadOffset() + 64); inStream.Read(data->playerID); - inStream.Read(data->playerID); - inStream.Read(data->playerName); + + uint32_t len; + inStream.Read(len); + + for (int i = 0; i < len; i++) { + char character; inStream.Read(character); + data->playerName += character; + } + inStream.Read(data->zoneID); inStream.Read(data->muteExpire); data->sysAddr = packet->systemAddress; - mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.C_String())); + mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str())); mPlayers.insert(std::make_pair(data->playerID, data)); - Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.C_String(), data->playerID, data->zoneID.GetMapID()); + Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID()); auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);"); @@ -64,7 +72,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) { if (team != nullptr) { - const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.C_String())); + const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.c_str())); for (const auto memberId : team->memberIDs) { @@ -232,8 +240,8 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) if (leader == nullptr || member == nullptr) return; - const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String())); - const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.C_String())); + const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str())); + const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.c_str())); ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName); @@ -337,7 +345,7 @@ void PlayerContainer::DisbandTeam(TeamData* team) if (otherMember == nullptr) continue; - const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.C_String())); + const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.c_str())); ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName); @@ -360,7 +368,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) if (leader == nullptr) return; - const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String())); + const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str())); for (const auto memberId : team->memberIDs) { diff --git a/dChatServer/PlayerContainer.h b/dChatServer/PlayerContainer.h index b1e1defd..9216a361 100644 --- a/dChatServer/PlayerContainer.h +++ b/dChatServer/PlayerContainer.h @@ -9,7 +9,7 @@ struct PlayerData { LWOOBJID playerID; - RakNet::RakString playerName; + std::string playerName; SystemAddress sysAddr; LWOZONEID zoneID; std::vector friends; @@ -46,7 +46,7 @@ public: PlayerData* GetPlayerData(const std::string& playerName) { for (auto player : mPlayers) { if (player.second) { - std::string pn = player.second->playerName.C_String(); + std::string pn = player.second->playerName.c_str(); if (pn == playerName) return player.second; } } diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index ae8e7969..74d44ce7 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -2017,11 +2017,15 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std:: CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ANNOUNCEMENT); - RakNet::RakString rsTitle(title.c_str()); - RakNet::RakString rsMsg(message.c_str()); + bitStream.Write(title.size()); + for (auto character : title) { + bitStream.Write(character); + } - bitStream.Write(rsTitle); - bitStream.Write(rsMsg); + bitStream.Write(message.size()); + for (auto character : message) { + bitStream.Write(character); + } Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 1cfd7d4a..2e881934 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -497,7 +497,10 @@ void HandlePacket(Packet* packet) { CBITSTREAM; PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_NEW_SESSION_ALERT); bitStream.Write(sessionKey); - bitStream.Write(RakNet::RakString(username.c_str())); + bitStream.Write(username.size()); + for (auto character : username) { + bitStream.Write(character); + } SEND_PACKET_BROADCAST; break; @@ -572,14 +575,20 @@ void HandlePacket(Packet* packet) { uint32_t mapId; LWOCLONEID cloneId; - RakNet::RakString password; + std::string password; inStream.Read(mapId); inStream.Read(cloneId); - inStream.Read(password); - Game::im->CreatePrivateInstance(mapId, cloneId, - password.C_String()); + uint32_t len; + inStream.Read(len); + for (int i = 0; len > i; i++) { + char character; + inStream.Read(character); + password += character; + } + + Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str()); break; } @@ -591,15 +600,22 @@ void HandlePacket(Packet* packet) { uint64_t requestID = 0; uint8_t mythranShift = false; - RakNet::RakString password; + std::string password; inStream.Read(requestID); inStream.Read(mythranShift); - inStream.Read(password); + + uint32_t len; + inStream.Read(len); - auto* instance = Game::im->FindPrivateInstance(password.C_String()); + for (int i = 0; i < len; i++) { + char character; inStream.Read(character); + password += character; + } - Game::logger->Log( "MasterServer", "Join private zone: %llu %d %s %p\n", requestID, mythranShift, password.C_String(), instance); + auto* instance = Game::im->FindPrivateInstance(password.c_str()); + + Game::logger->Log( "MasterServer", "Join private zone: %llu %d %s %p\n", requestID, mythranShift, password.c_str(), instance); if (instance == nullptr) { return; diff --git a/dNet/MasterPackets.cpp b/dNet/MasterPackets.cpp index 96ad1b81..bf58d71c 100644 --- a/dNet/MasterPackets.cpp +++ b/dNet/MasterPackets.cpp @@ -43,8 +43,10 @@ void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint bitStream.Write(zoneID); bitStream.Write(cloneID); - RakNet::RakString passwd(password.c_str()); - bitStream.Write(passwd); + bitStream.Write(password.size()); + for (auto character : password) { + bitStream.Write(character); + } server->SendToMaster(&bitStream); } @@ -56,8 +58,10 @@ void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID, bitStream.Write(requestID); bitStream.Write(static_cast(mythranShift)); - RakNet::RakString passwd(password.c_str()); - bitStream.Write(passwd); + bitStream.Write(password.size()); + for (auto character : password) { + bitStream.Write(character); + } server->SendToMaster(&bitStream); } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 330263ed..9e5ff8c1 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -546,18 +546,31 @@ void HandlePacketChat(Packet* packet) { LWOOBJID header; inStream.Read(header); - RakNet::RakString title; - RakNet::RakString msg; + std::string title; + std::string msg; - inStream.Read(title); - inStream.Read(msg); + uint32_t len; + inStream.Read(len); + for (int i = 0; len > i; i++) { + char character; + inStream.Read(character); + title += character; + } + + len = 0; + inStream.Read(len); + for (int i = 0; len > i; i++) { + char character; + inStream.Read(character); + msg += character; + } //Send to our clients: AMFArrayValue args; auto* titleValue = new AMFStringValue(); - titleValue->SetStringValue(title.C_String()); + titleValue->SetStringValue(title.c_str()); auto* messageValue = new AMFStringValue(); - messageValue->SetStringValue(msg.C_String()); + messageValue->SetStringValue(msg.c_str()); args.InsertValue("title", titleValue); args.InsertValue("message", messageValue); @@ -1122,14 +1135,12 @@ void HandlePacket(Packet* packet) { CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_ADDED_NOTIFICATION); bitStream.Write(player->GetObjectID()); - bitStream.Write(playerName.size()); + bitStream.Write(playerName.size()); for (size_t i = 0; i < playerName.size(); i++) { bitStream.Write(playerName[i]); } - //bitStream.Write(playerName); - auto zone = dZoneManager::Instance()->GetZone()->GetZoneID(); bitStream.Write(zone.GetMapID()); bitStream.Write(zone.GetInstanceID()); From c689b3d3d1a6af247c5c72da25162dc32a23b852 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 16 Jul 2022 21:39:13 -0700 Subject: [PATCH 16/18] Parent and Child Deletion Improvements (#649) * Fix timers * Update Entity.cpp * Fix timers Fix timers Remove debug logs remove _dynamic * I like to move it move it * Child Deletion Improvements * Check bounds --- dGame/Entity.cpp | 19 +++++++++++++++---- dGame/Entity.h | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 93fa0609..a063b3c6 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -109,6 +109,11 @@ Entity::~Entity() { m_Components.erase(pair.first); } + + for (auto child : m_ChildEntities) { + if (child) child->RemoveParent(); + } + if (m_ParentEntity) { m_ParentEntity->RemoveChild(this); } @@ -1662,15 +1667,21 @@ void Entity::AddChild(Entity* child) { void Entity::RemoveChild(Entity* child) { if (!child) return; - for (auto entity = m_ChildEntities.begin(); entity != m_ChildEntities.end(); entity++) { - if (*entity && (*entity)->GetObjectID() == child->GetObjectID()) { + uint32_t entityPosition = 0; + while (entityPosition < m_ChildEntities.size()) { + if (!m_ChildEntities[entityPosition] || (m_ChildEntities[entityPosition])->GetObjectID() == child->GetObjectID()) { m_IsParentChildDirty = true; - m_ChildEntities.erase(entity); - return; + m_ChildEntities.erase(m_ChildEntities.begin() + entityPosition); + } else { + entityPosition++; } } } +void Entity::RemoveParent() { + this->m_ParentEntity = nullptr; +} + void Entity::AddTimer(std::string name, float time) { EntityTimer* timer = new EntityTimer(name, time); m_PendingTimers.push_back(timer); diff --git a/dGame/Entity.h b/dGame/Entity.h index ca12b355..85f992e8 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -144,6 +144,7 @@ public: void AddChild(Entity* child); void RemoveChild(Entity* child); + void RemoveParent(); void AddTimer(std::string name, float time); void AddCallbackTimer(float time, std::function callback); bool HasTimer(const std::string& name); From 0d4f86b20b9527028ae0ccfca2b207f4d9fe767a Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Sun, 17 Jul 2022 06:57:00 +0100 Subject: [PATCH 17/18] Resolve missing RakNet replacement (#650) Repair issue from PR earlier, crucial fix. --- dWorldServer/WorldServer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 9e5ff8c1..d7a3b41e 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -817,19 +817,27 @@ void HandlePacket(Packet* packet) { RakNet::BitStream inStream(packet->data, packet->length, false); uint64_t header = inStream.Read(header); uint32_t sessionKey = inStream.Read(sessionKey); - RakNet::RakString username; - inStream.Read(username); + + std::string username; + + uint32_t len; + inStream.Read(len); + + for (int i = 0; i < len; i++) { + char character; inStream.Read(character); + username += character; + } //Find them: - User* user = UserManager::Instance()->GetUser(username.C_String()); + User* user = UserManager::Instance()->GetUser(username.c_str()); if (!user) { - Game::logger->Log("WorldServer", "Got new session alert for user %s, but they're not logged in.\n", username.C_String()); + Game::logger->Log("WorldServer", "Got new session alert for user %s, but they're not logged in.\n", username.c_str()); return; } //Check the key: if (sessionKey != std::atoi(user->GetSessionKey().c_str())) { - Game::logger->Log("WorldServer", "Got new session alert for user %s, but the session key is invalid.\n", username.C_String()); + Game::logger->Log("WorldServer", "Got new session alert for user %s, but the session key is invalid.\n", username.c_str()); Game::server->Disconnect(user->GetSystemAddress(), SERVER_DISCON_INVALID_SESSION_KEY); return; } From ef8c2a40f384973c68c5cc483b2e602e9579fb4f Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Sun, 17 Jul 2022 02:35:11 -0500 Subject: [PATCH 18/18] Framework for GM's and helpers for mounts (#651) * Framework for GM's and helpers for mounts * docs and spacing * whitespace --- dGame/dComponents/CharacterComponent.h | 17 + dGame/dComponents/PossessableComponent.cpp | 3 + dGame/dComponents/PossessableComponent.h | 17 + dGame/dComponents/PossessorComponent.h | 18 ++ dGame/dGameMessages/GameMessages.cpp | 359 +++++++++++---------- dGame/dGameMessages/GameMessages.h | 30 +- dNet/dMessageIdentifiers.h | 2 + 7 files changed, 281 insertions(+), 165 deletions(-) diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index c7706325..009530c4 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -179,6 +179,18 @@ public: */ void SetLastRocketItemID(LWOOBJID lastRocketItemID) { m_LastRocketItemID = lastRocketItemID; } + /** + * Gets the object ID of the mount item that is being used + * @return the object ID of the mount item that is being used + */ + LWOOBJID GetMountItemID() const { return m_MountItemID; } + + /** + * Sets the object ID of the mount item that is being used + * @param m_MountItemID the object ID of the mount item that is being used + */ + void SetMountItemID(LWOOBJID mountItemID) { m_MountItemID = mountItemID; } + /** * Gives the player rewards for the last level that they leveled up from */ @@ -579,6 +591,11 @@ private: * ID of the last rocket used */ LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY; + + /** + * Mount Item ID + */ + LWOOBJID m_MountItemID = LWOOBJID_EMPTY; }; #endif // CHARACTERCOMPONENT_H diff --git a/dGame/dComponents/PossessableComponent.cpp b/dGame/dComponents/PossessableComponent.cpp index 1d721466..8190b9eb 100644 --- a/dGame/dComponents/PossessableComponent.cpp +++ b/dGame/dComponents/PossessableComponent.cpp @@ -1,10 +1,13 @@ #include "PossessableComponent.h" #include "PossessorComponent.h" #include "EntityManager.h" +#include "Inventory.h" #include "Item.h" PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent){ m_Possessor = LWOOBJID_EMPTY; + CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT()); + m_AnimationFlag = static_cast(item.animationFlag); // Get the possession Type from the CDClient auto query = CDClientDatabase::CreatePreppedStmt("SELECT possessionType, depossessOnHit FROM PossessableComponent WHERE id = ?;"); diff --git a/dGame/dComponents/PossessableComponent.h b/dGame/dComponents/PossessableComponent.h index 5eefaaf4..a37b6e34 100644 --- a/dGame/dComponents/PossessableComponent.h +++ b/dGame/dComponents/PossessableComponent.h @@ -54,6 +54,18 @@ class PossessableComponent : public Component { */ void ForceDepossess() { m_ImmediatelyDepossess = true; m_DirtyPossessable = true;}; + /** + * Set if the parent entity was spawned from an item + * @param value if the parent entity was spawned from an item + */ + void SetItemSpawned(bool value) { m_ItemSpawned = value;}; + + /** + * Returns if the parent entity was spawned from an item + * @return if the parent entity was spawned from an item + */ + LWOOBJID GetItemSpawned() const { return m_ItemSpawned; }; + /** * Handles an OnUsed event by some other entity, if said entity has a Possessor it becomes the possessor * of this entity @@ -95,4 +107,9 @@ class PossessableComponent : public Component { */ bool m_ImmediatelyDepossess = false; + /** + * @brief Whether the parent entity was spawned from an item + * + */ + bool m_ItemSpawned = false; }; diff --git a/dGame/dComponents/PossessorComponent.h b/dGame/dComponents/PossessorComponent.h index f202b907..a81868a5 100644 --- a/dGame/dComponents/PossessorComponent.h +++ b/dGame/dComponents/PossessorComponent.h @@ -36,6 +36,18 @@ class PossessorComponent : public Component { */ LWOOBJID GetPossessable() const { return m_Possessable; } + /** + * Sets if we are busy mounting or dismounting + * @param value if we are busy mounting or dismounting + */ + void SetIsBusy(bool value) { m_IsBusy = value; } + + /** + * Returns if we are busy mounting or dismounting + * @return if we are busy mounting or dismounting + */ + bool GetIsBusy() const { return m_IsBusy; } + /** * Sets the possesible type that's currently used, merely used by the shooting gallery if it's 0 * @param value the possesible type to set @@ -60,4 +72,10 @@ class PossessorComponent : public Component { * */ bool m_DirtyPossesor = false; + + /** + * @brief if the possessor is busy mounting or dismounting + * + */ + bool m_IsBusy = false; }; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 4f5cb1f4..292afc71 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -147,7 +147,7 @@ void GameMessages::SendPlayAnimation(Entity* entity, const std::u16string& anima PacketUtils::WriteWString(bitStream, animationName, animationIDLength); bitStream.Write(bExpectAnimToExist); - + bitStream.Write(bPlayImmediate); bitStream.Write(bTriggerOnCompleteMsg); @@ -427,7 +427,7 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System LWONameValue extraInfo; auto config = item->GetConfig(); - + for (auto* data : config) { extraInfo.name += GeneralUtils::ASCIIToUTF16(data->GetString()) + u","; @@ -435,7 +435,7 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System if (extraInfo.name.length() > 0) extraInfo.name.pop_back(); // remove the last comma - bitStream.Write(extraInfo.name.size()); + bitStream.Write(extraInfo.name.size()); if (extraInfo.name.size() > 0) { for (uint32_t i = 0; i < extraInfo.name.size(); ++i) { bitStream.Write(static_cast(extraInfo.name[i])); @@ -447,10 +447,10 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System bitStream.Write(subKey != LWOOBJID_EMPTY); if (subKey != LWOOBJID_EMPTY) bitStream.Write(subKey); - + auto* inventory = item->GetInventory(); const auto inventoryType = inventory->GetType(); - + bitStream.Write(inventoryType != eInventoryType::ITEMS); if (inventoryType != eInventoryType::ITEMS) bitStream.Write(inventoryType); @@ -458,7 +458,7 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System if (itemCount != 1) bitStream.Write(itemCount); const auto count = item->GetCount(); - + bitStream.Write(count != 0); //items total if (count != 0) bitStream.Write(count); @@ -1008,7 +1008,7 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, if (GameConfig::GetValue("no_drops") == 1) { return; } - + bool bUsePosition = false; NiPoint3 finalPosition; LWOOBJID lootID = LWOOBJID_EMPTY; @@ -1063,7 +1063,7 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, if (spawnPos != NiPoint3::ZERO) bitStream.Write(spawnPos); auto* team = TeamManager::Instance()->GetTeam(owner); - + // Currency and powerups should not sync if (team != nullptr && currency == 0) { @@ -1086,7 +1086,7 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, return; } } - + SystemAddress sysAddr = entity->GetSystemAddress(); SEND_PACKET; } @@ -1097,7 +1097,7 @@ void GameMessages::SendSetPlayerControlScheme(Entity* entity, eControlSceme cont bool bDelayCamSwitchIfInCinematic = true; bool bSwitchCam = true; - + bitStream.Write(entity->GetObjectID()); bitStream.Write(uint16_t(GAME_MSG_SET_PLAYER_CONTROL_SCHEME)); @@ -1265,7 +1265,7 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s bitStream.Write(entity->GetObjectID()); bitStream.Write(GAME_MSG::GAME_MSG_VENDOR_STATUS_UPDATE); - bitStream.Write(bUpdateOnly); + bitStream.Write(bUpdateOnly); bitStream.Write(static_cast(vendorItems.size())); for (std::pair item : vendorItems) { @@ -1282,7 +1282,7 @@ void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddre CMSGHEADER int iResult = 0x02; // success, seems to be the only relevant one - + bitStream.Write(entity->GetObjectID()); bitStream.Write(GAME_MSG::GAME_MSG_VENDOR_TRANSACTION_RESULT); bitStream.Write(iResult); @@ -1537,7 +1537,7 @@ void GameMessages::NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sy bitStream.Write(level); bitStream.Write(sending_rewards); - + SEND_PACKET } @@ -1549,7 +1549,7 @@ void GameMessages::SendSetShootingGalleryParams(LWOOBJID objectId, const SystemA NiPoint3 playerPosOffset, float projectileVelocity, float timeLimit, - bool bUseLeaderboards) + bool bUseLeaderboards) { CBITSTREAM CMSGHEADER @@ -1585,7 +1585,7 @@ void GameMessages::SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const float addTime, int32_t score, LWOOBJID target, - NiPoint3 targetPos) + NiPoint3 targetPos) { CBITSTREAM CMSGHEADER @@ -1602,7 +1602,7 @@ void GameMessages::SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const } -void GameMessages::HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { float angle = 0.0f; NiPoint3 facing = NiPoint3::ZERO; @@ -1833,13 +1833,13 @@ void GameMessages::SendNotifyClientObject(const LWOOBJID& objectID, std::u16stri for (auto character : name) { bitStream.Write(character); } - + bitStream.Write(param1); - + bitStream.Write(param2); bitStream.Write(paramObj); - + bitStream.Write(uint32_t(paramStr.size())); for (auto character : paramStr) { bitStream.Write(character); @@ -1988,7 +1988,7 @@ void GameMessages::SendDownloadPropertyData(const LWOOBJID objectId, const Prope data.Serialize(bitStream); Game::logger->Log("SendDownloadPropertyData", "(%llu) sending property data (%d)\n", objectId, sysAddr == UNASSIGNED_SYSTEM_ADDRESS); - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } @@ -2000,12 +2000,12 @@ void GameMessages::SendPropertyRentalResponse(const LWOOBJID objectId, const LWO bitStream.Write(objectId); bitStream.Write(GAME_MSG::GAME_MSG_PROPERTY_RENTAL_RESPONSE); - + bitStream.Write(cloneId); bitStream.Write(code); bitStream.Write(propertyId); bitStream.Write(rentDue); - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } @@ -2078,7 +2078,7 @@ void GameMessages::SendZonePropertyModelEquipped(LWOOBJID objectId, LWOOBJID pla bitStream.Write(playerId); bitStream.Write(propertyId); - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } @@ -2115,7 +2115,7 @@ void GameMessages::SendPlaceModelResponse(LWOOBJID objectId, const SystemAddress { bitStream.Write(response); } - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; @@ -2131,7 +2131,7 @@ void GameMessages::SendUGCEquipPreCreateBasedOnEditMode(LWOOBJID objectId, const bitStream.Write(modelCount); bitStream.Write(model); - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } @@ -2250,7 +2250,7 @@ void GameMessages::HandleSetBuildMode(RakNet::BitStream* inStream, Entity* entit NiPoint3 startPosition = NiPoint3::ZERO; inStream->Read(start); - + if (inStream->ReadBit()) inStream->Read(distanceType); @@ -2273,7 +2273,7 @@ void GameMessages::HandleSetBuildMode(RakNet::BitStream* inStream, Entity* entit player->GetCharacter()->SetBuildMode(start); Game::logger->Log("GameMessages", "Sending build mode confirm (%i): (%d) (%i) (%d) (%i) (%llu)\n", entity->GetLOT(), start, distanceType, modePaused, modeValue, playerId); - + SendSetBuildModeConfirmed(entity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS, start, false, modePaused, modeValue, playerId, startPosition); } @@ -2283,7 +2283,7 @@ void GameMessages::HandleStartBuildingWithItem(RakNet::BitStream* inStream, Enti { return; } - + bool firstTime{}; bool success{}; int32_t sourceBag{}; @@ -2311,11 +2311,11 @@ void GameMessages::HandleStartBuildingWithItem(RakNet::BitStream* inStream, Enti } Game::logger->Log("GameMessages", "Handling start building with item (%i): (%d) (%d) (%i) (%llu) (%i) (%i) (%llu) (%i) (%i)\n", entity->GetLOT(), firstTime, success, sourceBag, sourceId, sourceLot, sourceType, targetId, targetLot, targetType); - + auto* user = UserManager::Instance()->GetUser(sysAddr); auto* player = EntityManager::Instance()->GetEntity(user->GetLoggedInChar()); - + SendStartArrangingWithItem( player, sysAddr, @@ -2336,7 +2336,7 @@ void GameMessages::HandleStartBuildingWithItem(RakNet::BitStream* inStream, Enti void GameMessages::HandlePropertyEditorBegin(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { PropertyManagementComponent::Instance()->OnStartBuilding(); - + dZoneManager::Instance()->GetZoneControlObject()->OnZonePropertyEditBegin(); } @@ -2366,7 +2366,7 @@ void GameMessages::HandlePlacePropertyModel(RakNet::BitStream* inStream, Entity* LWOOBJID model; inStream->Read(model); - + PropertyManagementComponent::Instance()->UpdateModelPosition(model, NiPoint3::ZERO, NiQuaternion::IDENTITY); } @@ -2383,7 +2383,7 @@ void GameMessages::HandleUpdatePropertyModel(RakNet::BitStream* inStream, Entity { inStream->Read(rotation); } - + PropertyManagementComponent::Instance()->UpdateModelPosition(model, position, rotation); } @@ -2422,18 +2422,18 @@ void GameMessages::HandleBBBLoadItemRequest(RakNet::BitStream* inStream, Entity* void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { /* - ___ ___ - /\ /\___ _ __ ___ / __\ ___ / \_ __ __ _ __ _ ___ _ __ ___ + ___ ___ + /\ /\___ _ __ ___ / __\ ___ / \_ __ __ _ __ _ ___ _ __ ___ / /_/ / _ \ '__/ _ \ /__\/// _ \ / /\ / '__/ _` |/ _` |/ _ \| '_ \/ __| / __ / __/ | | __/ / \/ \ __/ / /_//| | | (_| | (_| | (_) | | | \__ \ \/ /_/ \___|_| \___| \_____/\___| /___,' |_| \__,_|\__, |\___/|_| |_|___/ - |___/ - ___ _ - / __\ _____ ____ _ _ __ ___ / \ - /__\/// _ \ \ /\ / / _` | '__/ _ \/ / - / \/ \ __/\ V V / (_| | | | __/\_/ - \_____/\___| \_/\_/ \__,_|_| \___\/ - + |___/ + ___ _ + / __\ _____ ____ _ _ __ ___ / \ + /__\/// _ \ \ /\ / / _` | '__/ _ \/ / + / \/ \ __/\ V V / (_| | | | __/\_/ + \_____/\___| \_/\_/ \__,_|_| \___\/ + <>=======() (/\___ /|\\ ()==========<>_ \_/ | \\ //|\ ______/ \) @@ -2463,7 +2463,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent uint8_t c; inStream->Read(c); } - + uint32_t lxfmlSize; inStream->Read(lxfmlSize); uint8_t* inData = static_cast(std::malloc(lxfmlSize)); @@ -2471,13 +2471,13 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent if (inData == nullptr) { return; } - + for (uint32_t i = 0; i < lxfmlSize; ++i) { uint8_t c; inStream->Read(c); inData[i] = c; } - + inStream->Read(timeTaken); /* @@ -2505,7 +2505,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent //Now, the cave of dragons: - //We runs this in async because the http library here is blocking, meaning it'll halt the thread. + //We runs this in async because the http library here is blocking, meaning it'll halt the thread. //But we don't want the server to go unresponsive, because then the client would disconnect. std::async(std::launch::async, [&]() { @@ -2595,7 +2595,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent */ ////Send off to UGC for processing, if enabled: - //if (Game::config->GetValue("ugc_remote") == "1") { + //if (Game::config->GetValue("ugc_remote") == "1") { // std::string ugcIP = Game::config->GetValue("ugc_ip"); // int ugcPort = std::stoi(Game::config->GetValue("ugc_port")); @@ -2750,7 +2750,7 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti } } -void GameMessages::HandleSetConsumableItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleSetConsumableItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LOT lot; @@ -2763,10 +2763,10 @@ void GameMessages::HandleSetConsumableItem(RakNet::BitStream* inStream, Entity* inventory->SetConsumable(lot); } -void GameMessages::SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, +void GameMessages::SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, bool allowGhostUpdates, bool bCloseMultiInteract, bool bSendServerNotify, bool bUseControlledObjectForAudioListener, int endBehavior, bool hidePlayerDuringCine, float leadIn, bool leavePlayerLockedWhenFinished, - bool lockPlayer, bool result, bool skipIfSamePath, float startTimeAdvance) + bool lockPlayer, bool result, bool skipIfSamePath, float startTimeAdvance) { CBITSTREAM; CMSGHEADER; @@ -2806,7 +2806,7 @@ void GameMessages::SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, } void GameMessages::SendEndCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, - float leadOut, bool leavePlayerLocked) + float leadOut, bool leavePlayerLocked) { CBITSTREAM; CMSGHEADER; @@ -2880,7 +2880,7 @@ void GameMessages::SendSetStunned(LWOOBJID objectId, eStunState stateChangeType, bool bCantAttackOutChangeWasApplied, bool bCantEquipOutChangeWasApplied, bool bCantInteractOutChangeWasApplied, bool bCantJumpOutChangeWasApplied, bool bCantMoveOutChangeWasApplied, bool bCantTurnOutChangeWasApplied, - bool bCantUseItemOutChangeWasApplied) + bool bCantUseItemOutChangeWasApplied) { CBITSTREAM; CMSGHEADER; @@ -2915,7 +2915,7 @@ void GameMessages::SendSetStunned(LWOOBJID objectId, eStunState stateChangeType, bitStream.Write(bCantUseItemOutChangeWasApplied); bitStream.Write(bDontTerminateInteract); - + bitStream.Write(bIgnoreImmunity); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; @@ -2923,7 +2923,7 @@ void GameMessages::SendSetStunned(LWOOBJID objectId, eStunState stateChangeType, } -void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr) +void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -2939,7 +2939,7 @@ void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, } -void GameMessages::SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, uint32_t modifier, const SystemAddress& sysAddr) +void GameMessages::SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, uint32_t modifier, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -2957,7 +2957,7 @@ void GameMessages::SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, u SEND_PACKET; } -void GameMessages::SendRemoveRunSpeedModifier(LWOOBJID objectId, uint32_t modifier, const SystemAddress& sysAddr) +void GameMessages::SendRemoveRunSpeedModifier(LWOOBJID objectId, uint32_t modifier, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3009,7 +3009,7 @@ void GameMessages::SendPropertySelectQuery(LWOOBJID objectId, int32_t navOffset, SEND_PACKET; } -void GameMessages::SendNotifyObject(LWOOBJID objectId, LWOOBJID objIDSender, std::u16string name, const SystemAddress& sysAddr, int param1, int param2) +void GameMessages::SendNotifyObject(LWOOBJID objectId, LWOOBJID objIDSender, std::u16string name, const SystemAddress& sysAddr, int param1, int param2) { CBITSTREAM; CMSGHEADER; @@ -3023,7 +3023,7 @@ void GameMessages::SendNotifyObject(LWOOBJID objectId, LWOOBJID objIDSender, std { bitStream.Write(character); } - + bitStream.Write(param1); bitStream.Write(param2); @@ -3031,7 +3031,7 @@ void GameMessages::SendNotifyObject(LWOOBJID objectId, LWOOBJID objIDSender, std SEND_PACKET; } -void GameMessages::HandleVerifyAck(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleVerifyAck(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bDifferent; std::string sBitStream; @@ -3053,7 +3053,7 @@ void GameMessages::HandleVerifyAck(RakNet::BitStream* inStream, Entity* entity, } } -void GameMessages::SendTeamPickupItem(LWOOBJID objectId, LWOOBJID lootID, LWOOBJID lootOwnerID, const SystemAddress& sysAddr) +void GameMessages::SendTeamPickupItem(LWOOBJID objectId, LWOOBJID lootID, LWOOBJID lootOwnerID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3063,7 +3063,7 @@ void GameMessages::SendTeamPickupItem(LWOOBJID objectId, LWOOBJID lootID, LWOOBJ bitStream.Write(lootID); bitStream.Write(lootOwnerID); - + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } @@ -3144,7 +3144,7 @@ void GameMessages::SendServerTradeAccept(LWOOBJID objectId, bool bFirst, const S SEND_PACKET; } -void GameMessages::SendServerTradeCancel(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendServerTradeCancel(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3156,7 +3156,7 @@ void GameMessages::SendServerTradeCancel(LWOOBJID objectId, const SystemAddress& SEND_PACKET; } -void GameMessages::SendServerTradeUpdate(LWOOBJID objectId, uint64_t coins, const std::vector& items, const SystemAddress& sysAddr) +void GameMessages::SendServerTradeUpdate(LWOOBJID objectId, uint64_t coins, const std::vector& items, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3242,7 +3242,7 @@ void GameMessages::HandleClientTradeRequest(RakNet::BitStream* inStream, Entity* { TradingManager::Instance()->NewTrade(entity->GetObjectID(), i64Invitee); } - + SendServerTradeInvite( i64Invitee, bNeedInvitePopUp, @@ -3256,7 +3256,7 @@ void GameMessages::HandleClientTradeRequest(RakNet::BitStream* inStream, Entity* void GameMessages::HandleClientTradeCancel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { auto* trade = TradingManager::Instance()->GetPlayerTrade(entity->GetObjectID()); - + if (trade == nullptr) return; Game::logger->Log("GameMessages", "Trade canceled from (%llu)\n", entity->GetObjectID()); @@ -3269,9 +3269,9 @@ void GameMessages::HandleClientTradeAccept(RakNet::BitStream* inStream, Entity* bool bFirst = inStream->ReadBit(); Game::logger->Log("GameMessages", "Trade accepted from (%llu) -> (%d)\n", entity->GetObjectID(), bFirst); - + auto* trade = TradingManager::Instance()->GetPlayerTrade(entity->GetObjectID()); - + if (trade == nullptr) return; trade->SetAccepted(entity->GetObjectID(), bFirst); @@ -3343,9 +3343,9 @@ void GameMessages::HandleClientTradeUpdate(RakNet::BitStream* inStream, Entity* Game::logger->Log("GameMessages", "Trade item from (%llu) -> (%llu)/(%llu), (%i), (%llu), (%i), (%i)\n", entity->GetObjectID(), itemId, itemId2, lot, unknown1, unknown2, unknown3); } - + auto* trade = TradingManager::Instance()->GetPlayerTrade(entity->GetObjectID()); - + if (trade == nullptr) return; trade->SetCoins(entity->GetObjectID(), currency); @@ -3355,7 +3355,7 @@ void GameMessages::HandleClientTradeUpdate(RakNet::BitStream* inStream, Entity* //Pets: -void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId, LWOOBJID playerTamingId, bool bForceTeleport, uint32_t notifyType, NiPoint3 petsDestPos, NiPoint3 telePos, NiQuaternion teleRot, const SystemAddress& sysAddr) +void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId, LWOOBJID playerTamingId, bool bForceTeleport, uint32_t notifyType, NiPoint3 petsDestPos, NiPoint3 telePos, NiQuaternion teleRot, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3378,7 +3378,7 @@ void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId SEND_PACKET; } -void GameMessages::SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3390,7 +3390,7 @@ void GameMessages::SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SEND_PACKET; } -void GameMessages::SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, std::vector& bricks, const SystemAddress& sysAddr) +void GameMessages::SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, std::vector& bricks, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3409,7 +3409,7 @@ void GameMessages::SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, std::vec SEND_PACKET; } -void GameMessages::SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, int32_t iNumCorrect, const SystemAddress& sysAddr) +void GameMessages::SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, int32_t iNumCorrect, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3425,7 +3425,7 @@ void GameMessages::SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, SEND_PACKET; } -void GameMessages::SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t iPetCommandType, int32_t iResponse, int32_t iTypeID, const SystemAddress& sysAddr) +void GameMessages::SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t iPetCommandType, int32_t iResponse, int32_t iTypeID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3442,7 +3442,7 @@ void GameMessages::SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t SEND_PACKET; } -void GameMessages::SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, std::u16string name, LWOOBJID petDBID, LOT petLOT, const SystemAddress& sysAddr) +void GameMessages::SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, std::u16string name, LWOOBJID petDBID, LOT petLOT, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3456,7 +3456,7 @@ void GameMessages::SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, { bitStream.Write(character); } - + bitStream.Write(petDBID); bitStream.Write(petLOT); @@ -3464,7 +3464,7 @@ void GameMessages::SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, SEND_PACKET; } -void GameMessages::SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const SystemAddress& sysAddr) +void GameMessages::SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3478,7 +3478,7 @@ void GameMessages::SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const Sy SEND_PACKET; } -void GameMessages::SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, const SystemAddress& sysAddr) +void GameMessages::SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3492,7 +3492,7 @@ void GameMessages::SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, cons SEND_PACKET; } -void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive, int32_t iType, LWOOBJID itemID, const SystemAddress& sysAddr) +void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive, int32_t iType, LWOOBJID itemID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3501,7 +3501,7 @@ void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive bitStream.Write(GAME_MSG::GAME_MSG_MARK_INVENTORY_ITEM_AS_ACTIVE); bitStream.Write(bActive); - + bitStream.Write(iType != 0); if (iType != 0) bitStream.Write(iType); @@ -3512,7 +3512,7 @@ void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive SEND_PACKET; } -void GameMessages::SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr) +void GameMessages::SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3526,7 +3526,7 @@ void GameMessages::SendClientExitTamingMinigame(LWOOBJID objectId, bool bVolunta SEND_PACKET; } -void GameMessages::SendShowPetActionButton(LWOOBJID objectId, int32_t buttonLabel, bool bShow, const SystemAddress& sysAddr) +void GameMessages::SendShowPetActionButton(LWOOBJID objectId, int32_t buttonLabel, bool bShow, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3557,7 +3557,7 @@ void GameMessages::SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID ta } -void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) +void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3572,7 +3572,7 @@ void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, cons } -void GameMessages::SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJID petDBID, const SystemAddress& sysAddr) +void GameMessages::SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJID petDBID, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3585,7 +3585,7 @@ void GameMessages::SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJ { bitStream.Write(character); } - + bitStream.Write(petDBID != LWOOBJID_EMPTY); if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID); @@ -3594,14 +3594,14 @@ void GameMessages::SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJ } -void GameMessages::SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, int32_t nModerationStatus, const SystemAddress& sysAddr) +void GameMessages::SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, int32_t nModerationStatus, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(GAME_MSG::GAME_MSG_SET_PET_NAME_MODERATED); - + bitStream.Write(petDBID != LWOOBJID_EMPTY); if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID); @@ -3612,7 +3612,7 @@ void GameMessages::SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, } -void GameMessages::SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatus, std::u16string name, std::u16string ownerName, const SystemAddress& sysAddr) +void GameMessages::SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatus, std::u16string name, std::u16string ownerName, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3627,7 +3627,7 @@ void GameMessages::SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatu { bitStream.Write(character); } - + bitStream.Write(static_cast(ownerName.size())); for (const auto character : ownerName) { @@ -3639,7 +3639,7 @@ void GameMessages::SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatu } -void GameMessages::HandleClientExitTamingMinigame(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleClientExitTamingMinigame(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bVoluntaryExit = inStream->ReadBit(); @@ -3653,7 +3653,7 @@ void GameMessages::HandleClientExitTamingMinigame(RakNet::BitStream* inStream, E petComponent->ClientExitTamingMinigame(bVoluntaryExit); } -void GameMessages::HandleStartServerPetMinigameTimer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleStartServerPetMinigameTimer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID()); @@ -3665,7 +3665,7 @@ void GameMessages::HandleStartServerPetMinigameTimer(RakNet::BitStream* inStream petComponent->StartTimer(); } -void GameMessages::HandlePetTamingTryBuild(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandlePetTamingTryBuild(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { uint32_t brickCount; std::vector bricks; @@ -3696,7 +3696,7 @@ void GameMessages::HandlePetTamingTryBuild(RakNet::BitStream* inStream, Entity* petComponent->TryBuild(bricks.size(), clientFailed); } -void GameMessages::HandleNotifyTamingBuildSuccess(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleNotifyTamingBuildSuccess(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { NiPoint3 position; @@ -3712,7 +3712,7 @@ void GameMessages::HandleNotifyTamingBuildSuccess(RakNet::BitStream* inStream, E petComponent->NotifyTamingBuildSuccess(position); } -void GameMessages::HandleRequestSetPetName(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleRequestSetPetName(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { uint32_t nameLength; std::u16string name; @@ -3725,7 +3725,7 @@ void GameMessages::HandleRequestSetPetName(RakNet::BitStream* inStream, Entity* inStream->Read(character); name.push_back(character); } - + auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID()); if (petComponent == nullptr) @@ -3741,14 +3741,14 @@ void GameMessages::HandleRequestSetPetName(RakNet::BitStream* inStream, Entity* petComponent->RequestSetPetName(name); } -void GameMessages::HandleCommandPet(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleCommandPet(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { NiPoint3 genericPosInfo; LWOOBJID objIdSource; int32_t iPetCommandType; int32_t iTypeID; bool overrideObey; - + inStream->Read(genericPosInfo); inStream->Read(objIdSource); inStream->Read(iPetCommandType); @@ -3765,7 +3765,7 @@ void GameMessages::HandleCommandPet(RakNet::BitStream* inStream, Entity* entity, petComponent->Command(genericPosInfo, objIdSource, iPetCommandType, iTypeID, overrideObey); } -void GameMessages::HandleDespawnPet(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleDespawnPet(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bDeletePet; @@ -3788,7 +3788,7 @@ void GameMessages::HandleDespawnPet(RakNet::BitStream* inStream, Entity* entity, } } -void GameMessages::HandleMessageBoxResponse(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleMessageBoxResponse(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { int32_t iButton; uint32_t identifierLength; @@ -3813,7 +3813,7 @@ void GameMessages::HandleMessageBoxResponse(RakNet::BitStream* inStream, Entity* inStream->Read(character); userData.push_back(character); } - + Game::logger->Log("HandleMessageBoxResponse", "Button: " + std::to_string(iButton) + "; LOT: " + std::to_string(entity->GetLOT()) + " identifier: " + GeneralUtils::UTF16ToWTF8(identifier) + "; userData: " + GeneralUtils::UTF16ToWTF8(userData) + "\n"); auto* user = UserManager::Instance()->GetUser(sysAddr); @@ -3852,7 +3852,7 @@ void GameMessages::HandleMessageBoxResponse(RakNet::BitStream* inStream, Entity* } } -void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { int32_t iButton; uint32_t buttonIdentifierLength; @@ -3877,7 +3877,7 @@ void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream* inStream, Entity* e inStream->Read(character); identifier.push_back(character); } - + Game::logger->Log("HandleChoiceBoxRespond", "Button: " + std::to_string(iButton) + "; LOT: " + std::to_string(entity->GetLOT()) + " buttonIdentifier: " + GeneralUtils::UTF16ToWTF8(buttonIdentifier) + "; userData: " + GeneralUtils::UTF16ToWTF8(identifier) + "\n"); auto* user = UserManager::Instance()->GetUser(sysAddr); @@ -3897,7 +3897,7 @@ void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream* inStream, Entity* e entity->OnChoiceBoxResponse(userEntity, iButton, buttonIdentifier, identifier); } -void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap, bool isZoneStart, LWOOBJID sender) +void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap, bool isZoneStart, LWOOBJID sender) { CBITSTREAM; CMSGHEADER; @@ -3916,7 +3916,7 @@ void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress //UI -void GameMessages::SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeSlotsNeeded, eInventoryType inventoryType, const SystemAddress& sysAddr) +void GameMessages::SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeSlotsNeeded, eInventoryType inventoryType, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3932,7 +3932,7 @@ void GameMessages::SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeS SEND_PACKET; } -void GameMessages::SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) +void GameMessages::SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -3950,7 +3950,7 @@ void GameMessages::SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID } bitStream.Write(imageID); - + bitStream.Write(static_cast(text.size())); for (const auto character : text) { @@ -3986,6 +3986,47 @@ void GameMessages::SendDisplayChatBubble(LWOOBJID objectId, const std::u16string SEND_PACKET; } +// Mounts + +void GameMessages::SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr){ + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(GAME_MSG::GAME_MSG_SET_MOUNT_INVENTORY_ID); + bitStream.Write(objectID); + + SEND_PACKET_BROADCAST; +} + + +void GameMessages::HandleDismountComplete(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr){ + LWOOBJID objectId{}; + inStream->Read(objectId); + auto* mount = EntityManager::Instance()->GetEntity(objectId); + + if (objectId != LWOOBJID_EMPTY) { + PossessorComponent* possessor; + if (entity->TryGetComponent(COMPONENT_TYPE_POSSESSOR, possessor)) { + if (mount) { + possessor->SetIsBusy(false); + possessor->SetPossessable(LWOOBJID_EMPTY); + possessor->SetPossessableType(ePossessionType::NO_POSSESSION); + + GameMessages::SendSetStunned(entity->GetObjectID(), eStunState::POP, UNASSIGNED_SYSTEM_ADDRESS, LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); + + EntityManager::Instance()->SerializeEntity(entity); + } + } + } +} + + +void GameMessages::HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { + Game::logger->Log("HandleAcknowledgePossession", "Got AcknowledgePossession from %i\n", entity->GetLOT()); + EntityManager::Instance()->SerializeEntity(entity); +} + //Racing void GameMessages::HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) @@ -3998,12 +4039,12 @@ void GameMessages::HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, En { Game::logger->Log("HandleModuleAssemblyQueryData", "Returning assembly %s\n", GeneralUtils::UTF16ToWTF8(moduleAssemblyComponent->GetAssemblyPartsLOTs()).c_str()); - SendModuleAssemblyDBDataForClient(entity->GetObjectID(), moduleAssemblyComponent->GetSubKey(), moduleAssemblyComponent->GetAssemblyPartsLOTs(), UNASSIGNED_SYSTEM_ADDRESS); + SendModuleAssemblyDBDataForClient(entity->GetObjectID(), moduleAssemblyComponent->GetSubKey(), moduleAssemblyComponent->GetAssemblyPartsLOTs(), UNASSIGNED_SYSTEM_ADDRESS); } } -void GameMessages::HandleModularAssemblyNIFCompleted(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleModularAssemblyNIFCompleted(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LWOOBJID objectID; @@ -4011,14 +4052,14 @@ void GameMessages::HandleModularAssemblyNIFCompleted(RakNet::BitStream* inStream } -void GameMessages::HandleVehicleSetWheelLockState(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleVehicleSetWheelLockState(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bExtraFriction = inStream->ReadBit(); bool bLocked = inStream->ReadBit(); } -void GameMessages::HandleRacingClientReady(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleRacingClientReady(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LWOOBJID playerID; @@ -4042,15 +4083,7 @@ void GameMessages::HandleRacingClientReady(RakNet::BitStream* inStream, Entity* } -void GameMessages::HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) -{ - Game::logger->Log("HandleAcknowledgePossession", "Got AcknowledgePossession from %i\n", entity->GetLOT()); - - EntityManager::Instance()->SerializeEntity(entity); -} - - -void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bClientDeath; bool bSpawnLoot; @@ -4064,7 +4097,7 @@ void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, bClientDeath = inStream->ReadBit(); bSpawnLoot = inStream->ReadBit(); - + uint32_t deathTypeLength = 0; inStream->Read(deathTypeLength); @@ -4123,13 +4156,13 @@ void GameMessages::HandleVehicleNotifyServerAddPassiveBoostAction(RakNet::BitStr } -void GameMessages::HandleVehicleNotifyServerRemovePassiveBoostAction(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleVehicleNotifyServerRemovePassiveBoostAction(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { //SendVehicleRemovePassiveBoostAction(entity->GetObjectID(), sysAddr); } -void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LWOOBJID playerID; @@ -4190,7 +4223,7 @@ void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStre updatePerformanceCostQuery = nullptr; } -void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LWOOBJID pickupObjID = LWOOBJID_EMPTY; LWOOBJID pickupSpawnerID = LWOOBJID_EMPTY; @@ -4350,7 +4383,7 @@ void GameMessages::SendRacingResetPlayerToLastReset(LWOOBJID objectId, LWOOBJID } -void GameMessages::SendNotifyRacingClient(LWOOBJID objectId, int32_t eventType, int32_t param1, LWOOBJID paramObj, std::u16string paramStr, LWOOBJID singleClient, const SystemAddress& sysAddr) +void GameMessages::SendNotifyRacingClient(LWOOBJID objectId, int32_t eventType, int32_t param1, LWOOBJID paramObj, std::u16string paramStr, LWOOBJID singleClient, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4378,7 +4411,7 @@ void GameMessages::SendNotifyRacingClient(LWOOBJID objectId, int32_t eventType, } -void GameMessages::SendActivityEnter(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendActivityEnter(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4391,7 +4424,7 @@ void GameMessages::SendActivityEnter(LWOOBJID objectId, const SystemAddress& sys } -void GameMessages::SendActivityStart(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendActivityStart(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4404,7 +4437,7 @@ void GameMessages::SendActivityStart(LWOOBJID objectId, const SystemAddress& sys } -void GameMessages::SendActivityExit(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendActivityExit(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4417,7 +4450,7 @@ void GameMessages::SendActivityExit(LWOOBJID objectId, const SystemAddress& sysA } -void GameMessages::SendActivityStop(LWOOBJID objectId, bool bExit, bool bUserCancel, const SystemAddress& sysAddr) +void GameMessages::SendActivityStop(LWOOBJID objectId, bool bExit, bool bUserCancel, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4459,7 +4492,7 @@ void GameMessages::SendVehicleRemovePassiveBoostAction(LWOOBJID objectId, const } -void GameMessages::SendVehicleNotifyFinishedRace(LWOOBJID objectId, const SystemAddress& sysAddr) +void GameMessages::SendVehicleNotifyFinishedRace(LWOOBJID objectId, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4561,7 +4594,7 @@ void GameMessages::HandleRequestMoveItemBetweenInventoryTypes(RakNet::BitStream* } -void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditionalSound, bool bPlayCountdownSound, std::u16string sndName, int32_t stateToPlaySoundOn, const SystemAddress& sysAddr) +void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditionalSound, bool bPlayCountdownSound, std::u16string sndName, int32_t stateToPlaySoundOn, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4590,7 +4623,7 @@ void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditi //------------------------------------------------------------------- Handlers ------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------------------------------- -void GameMessages::HandleToggleGhostReferenceOverride(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleToggleGhostReferenceOverride(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { bool bOverride = false; @@ -4601,13 +4634,13 @@ void GameMessages::HandleToggleGhostReferenceOverride(RakNet::BitStream* inStrea if (player != nullptr) { player->SetGhostOverride(bOverride); - + EntityManager::Instance()->UpdateGhosting(player); } } -void GameMessages::HandleSetGhostReferencePosition(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) +void GameMessages::HandleSetGhostReferencePosition(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { NiPoint3 position; @@ -4650,7 +4683,7 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti } const auto isCommendationVendor = entity->GetLOT() == 13806; - + VendorComponent* vend = static_cast(entity->GetComponent(COMPONENT_TYPE_VENDOR)); if (!vend && !isCommendationVendor) return; @@ -4923,7 +4956,7 @@ void GameMessages::HandleFireEventServerSide(RakNet::BitStream* inStream, Entity LWOCLONEID cloneId = 0; LWOMAPID mapId = 0; - + auto* rocketPad = entity->GetComponent(); if (rocketPad == nullptr) return; @@ -4948,7 +4981,7 @@ void GameMessages::HandleFireEventServerSide(RakNet::BitStream* inStream, Entity } Game::logger->Log("FireEventServerSide", "Player %llu has requested zone transfer to (%i, %i).\n", sender->GetObjectID(), (int) mapId, (int) cloneId); - + auto* character = player->GetCharacter(); if (mapId <= 0) { @@ -4957,7 +4990,7 @@ void GameMessages::HandleFireEventServerSide(RakNet::BitStream* inStream, Entity ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, mapId, cloneId, false, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { Game::logger->Log("UserManager", "Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i\n", character->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort); - + if (character) { character->SetZoneID(zoneID); character->SetZoneInstance(zoneInstance); @@ -5011,12 +5044,12 @@ void GameMessages::HandleRequestUse(RakNet::BitStream* inStream, Entity* entity, return; } - + if (interactedObject->GetLOT() == 9524) { entity->GetCharacter()->SetBuildMode(true); } - + if (bIsMultiInteractUse) { if (multiInteractType == 0) @@ -5039,7 +5072,7 @@ void GameMessages::HandleRequestUse(RakNet::BitStream* inStream, Entity* entity, //Perform use task if possible: auto missionComponent = static_cast(entity->GetComponent(COMPONENT_TYPE_MISSION)); - + if (missionComponent == nullptr) return; missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MISSION_INTERACTION, interactedObject->GetLOT(), interactedObject->GetObjectID()); @@ -5054,7 +5087,7 @@ void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity) inStream->Read(targetID); Game::logger->Log("GameMessages", "Emote (%i) (%llu)\n", emoteID, targetID); - + //TODO: If targetID != 0, and we have one of the "perform emote" missions, complete them. if (emoteID == 0) return; @@ -5064,13 +5097,13 @@ void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity) if (mission) { mission->Progress(MissionTaskType::MISSION_TASK_TYPE_EMOTE, emoteID, targetID); } - + if (targetID != LWOOBJID_EMPTY) { auto* targetEntity = EntityManager::Instance()->GetEntity(targetID); Game::logger->Log("GameMessages", "Emote target found (%d)\n", targetEntity != nullptr); - + if (targetEntity != nullptr) { targetEntity->OnEmoteReceived(emoteID, entity); @@ -5222,7 +5255,7 @@ void GameMessages::HandleRequestLinkedMission(RakNet::BitStream* inStream, Entit auto* player = EntityManager::Instance()->GetEntity(playerId); auto* missionOfferComponent = static_cast(entity->GetComponent(COMPONENT_TYPE_MISSION_OFFER)); - + if (missionOfferComponent != nullptr) { missionOfferComponent->OfferMissions(player, 0); @@ -5245,7 +5278,7 @@ void GameMessages::HandleHasBeenCollected(RakNet::BitStream* inStream, Entity* e void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream* inStream, Entity* entity) { auto* character = static_cast(entity->GetComponent(COMPONENT_TYPE_CHARACTER)); if (!character) return; - + //Update our character's level in memory: character->SetLevel(character->GetLevel() + 1); @@ -5281,7 +5314,7 @@ void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream* void GameMessages::HandlePickupCurrency(RakNet::BitStream* inStream, Entity* entity) { unsigned int currency; inStream->Read(currency); - + if (currency == 0) return; auto* ch = entity->GetCharacter(); @@ -5306,7 +5339,7 @@ void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity) inStream->Read(bClientDeath); inStream->Read(bDieAccepted); inStream->Read(bSpawnLoot); - + bool coinSpawnTimeIsDefault{}; inStream->Read(coinSpawnTimeIsDefault); if (coinSpawnTimeIsDefault != 0) inStream->Read(coinSpawnTime); @@ -5343,7 +5376,7 @@ void GameMessages::HandleEquipItem(RakNet::BitStream* inStream, Entity* entity) if (!item) return; item->Equip(); - + EntityManager::Instance()->SerializeEntity(entity); } @@ -5361,9 +5394,9 @@ void GameMessages::HandleUnequipItem(RakNet::BitStream* inStream, Entity* entity auto* item = inv->FindItemById(objectID); if (!item) return; - + item->UnEquip(); - + EntityManager::Instance()->SerializeEntity(entity); } @@ -5439,9 +5472,9 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En { return; } - + iStackCount = std::min(item->GetCount(), iStackCount); - + if (bConfirmed) { for (auto i = 0; i < iStackCount; ++i) { if (eInvType == eInventoryType::MODELS) @@ -5454,7 +5487,7 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En EntityManager::Instance()->SerializeEntity(entity); auto* missionComponent = entity->GetComponent(); - + if (missionComponent != nullptr) { missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -iStackCount); @@ -5525,7 +5558,7 @@ void GameMessages::HandleMoveItemBetweenInventoryTypes(RakNet::BitStream* inStre } } } - + if (entity->GetCharacter()) { if (entity->GetCharacter()->GetBuildMode()) { showFlyingLoot = false; @@ -5543,7 +5576,7 @@ void GameMessages::HandleBuildModeSet(RakNet::BitStream* inStream, Entity* entit // there's more here but we don't need it (for now?) Game::logger->Log("GameMessages", "Set build mode to (%d) for (%llu)\n", bStart, entity->GetObjectID()); - + if (entity->GetCharacter()) { entity->GetCharacter()->SetBuildMode(bStart); } @@ -5607,7 +5640,7 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity* } auto* missionComponent = character->GetComponent(); - + if (entity->GetLOT() != 9980 || Game::server->GetZoneID() != 1200) { if (missionComponent != nullptr) @@ -5686,7 +5719,7 @@ void GameMessages::HandleDoneArrangingWithItem(RakNet::BitStream* inStream, Enti inStream->Read(oldItemTYPE); /* - Game::logger->Log("GameMessages", + Game::logger->Log("GameMessages", "\nnewSourceBAG: %d\nnewSourceID: %llu\nnewSourceLOT: %d\nnewSourceTYPE: %d\nnewTargetID: %llu\nnewTargetLOT: %d\nnewTargetTYPE: %d\nnewTargetPOS: %f, %f, %f\noldItemBAG: %d\noldItemID: %llu\noldItemLOT: %d\noldItemTYPE: %d\n", newSourceBAG, newSourceID, newSourceLOT, newSourceTYPE, newTargetID, newTargetLOT, newTargetTYPE, newTargetPOS.x, newTargetPOS.y, newTargetPOS.z, oldItemBAG, oldItemID, oldItemLOT, oldItemTYPE ); @@ -5694,7 +5727,7 @@ void GameMessages::HandleDoneArrangingWithItem(RakNet::BitStream* inStream, Enti if (PropertyManagementComponent::Instance() != nullptr) { const auto& buildAreas = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_BUILD_BORDER); - + const auto& entities = EntityManager::Instance()->GetEntitiesInGroup("PropertyPlaque"); Entity* buildArea; @@ -5704,7 +5737,7 @@ void GameMessages::HandleDoneArrangingWithItem(RakNet::BitStream* inStream, Enti } else if (!entities.empty()) { buildArea = entities[0]; - + Game::logger->Log("BuildBorderComponent", "Using PropertyPlaque\n"); } else { @@ -5839,7 +5872,7 @@ void GameMessages::HandleClientItemConsumed(RakNet::BitStream* inStream, Entity* inStream->Read(itemConsumed); auto* inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - + if (inventory == nullptr) { return; @@ -5866,13 +5899,13 @@ void GameMessages::HandleUseNonEquipmentItem(RakNet::BitStream* inStream, Entity LWOOBJID itemConsumed; inStream->Read(itemConsumed); - + auto* inv = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - + if (!inv) return; auto* item = inv->FindItemById(itemConsumed); - + if (item == nullptr) { return; diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 1d42eebc..18e1467e 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -328,6 +328,34 @@ namespace GameMessages { void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr); + // Mounts + /** + * @brief Set the Inventory LWOOBJID of the mount + * + * @param entity The entity that is mounting + * @param sysAddr the system address to send game message responses to + * @param objectID LWOOBJID of the item in inventory that is being used + */ + void SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr); + + /** + * @brief Handle client dismounting mount + * + * @param inStream Raknet BitStream of incoming data + * @param entity The Entity that is dismounting + * @param sysAddr the system address to send game message responses to + */ + void HandleDismountComplete(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + + /** + * @brief Handle acknowledging that the client possessed something + * + * @param inStream Raknet BitStream of incoming data + * @param entity The Entity that is possessing + * @param sysAddr the system address to send game message responses to + */ + void HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + //Racing: void HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); @@ -337,8 +365,6 @@ namespace GameMessages { void HandleRacingClientReady(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); - void HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); - void HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); void HandleVehicleNotifyServerAddPassiveBoostAction(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index 5b2ff639..5ad3921c 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -535,8 +535,10 @@ enum GAME_MSG : unsigned short { GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, GAME_MSG_PLAYER_SET_CAMERA_CYCLING_MODE = 1676, + GAME_MSG_SET_MOUNT_INVENTORY_ID = 1726, GAME_MSG_NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734, GAME_MSG_NOTIFY_LEVEL_REWARDS = 1735, + GAME_MSG_DISMOUNT_COMPLETE = 1756, GAME_MSG_MARK_INVENTORY_ITEM_AS_ACTIVE = 1767, END }; \ No newline at end of file