diff --git a/.env.example b/.env.example index 153859060..462fb17f1 100644 --- a/.env.example +++ b/.env.example @@ -14,4 +14,4 @@ EXTERNAL_IP=localhost MARIADB_USER=darkflame MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME -MARIADB_DATABASE=darkflame \ No newline at end of file +MARIADB_DATABASE=darkflame diff --git a/CMakeVariables.txt b/CMakeVariables.txt index 5140ddff4..abfe9e159 100644 --- a/CMakeVariables.txt +++ b/CMakeVariables.txt @@ -1,12 +1,8 @@ PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MINOR=1 -PROJECT_VERSION_PATCH=0 +PROJECT_VERSION_PATCH=1 # LICENSE LICENSE=AGPL-3.0 -# The network version. -# 171023 - Darkflame Universe client -# 171022 - Unmodded client -NET_VERSION=171022 # Debugging # Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs. __dynamic=1 diff --git a/README.md b/README.md index b7e2a1012..b51fa4b0c 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j` where number i ### Notes Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building: * If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory. -* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023. +* If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023. ## Configuring your server This server has a few steps that need to be taken to configure the server for your use case. diff --git a/dChatServer/ChatPacketHandler.cpp b/dChatServer/ChatPacketHandler.cpp index 878cc71cc..3d6fca318 100644 --- a/dChatServer/ChatPacketHandler.cpp +++ b/dChatServer/ChatPacketHandler.cpp @@ -3,6 +3,7 @@ #include "Database.h" #include #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "Game.h" #include "dServer.h" #include "GeneralUtils.h" @@ -75,11 +76,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { //Now, we need to send the friendlist to the server they came from: CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(playerID); //portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE); bitStream.Write(0); bitStream.Write(1); //Length of packet -- just writing one as it doesn't matter, client skips it. bitStream.Write((uint16_t)friends.size()); @@ -412,21 +413,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) { const auto otherName = std::string(otherMember->playerName.c_str()); CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(otherMember->playerID); - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); bitStream.Write(otherMember->playerID); bitStream.Write(8); bitStream.Write(69); - PacketUtils::WritePacketWString(senderName, 33, &bitStream); + bitStream.Write(LUWString(senderName)); bitStream.Write(sender->playerID); bitStream.Write(0); bitStream.Write(0); //not mythran nametag - PacketUtils::WritePacketWString(otherName, 33, &bitStream); + bitStream.Write(LUWString(otherName)); bitStream.Write(0); //not mythran for receiver bitStream.Write(0); //teams? - PacketUtils::WritePacketWString(message, 512, &bitStream); + bitStream.Write(LUWString(message, 512)); SystemAddress sysAddr = otherMember->sysAddr; SEND_PACKET; @@ -434,7 +435,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) { } void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { - LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet); + LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet); std::string receiverName = PacketUtils::ReadString(0x66, packet, true); std::string message = PacketUtils::ReadString(0xAA, packet, true, 512); @@ -451,21 +452,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { //To the sender: { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(goonA->playerID); - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); bitStream.Write(goonA->playerID); bitStream.Write(7); bitStream.Write(69); - PacketUtils::WritePacketWString(goonAName, 33, &bitStream); + bitStream.Write(LUWString(goonAName)); bitStream.Write(goonA->playerID); bitStream.Write(0); bitStream.Write(0); //not mythran nametag - PacketUtils::WritePacketWString(goonBName, 33, &bitStream); + bitStream.Write(LUWString(goonBName)); bitStream.Write(0); //not mythran for receiver bitStream.Write(0); //success - PacketUtils::WritePacketWString(message, 512, &bitStream); + bitStream.Write(LUWString(message, 512)); SystemAddress sysAddr = goonA->sysAddr; SEND_PACKET; @@ -474,21 +475,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { //To the receiver: { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(goonB->playerID); - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); bitStream.Write(goonA->playerID); bitStream.Write(7); bitStream.Write(69); - PacketUtils::WritePacketWString(goonAName, 33, &bitStream); + bitStream.Write(LUWString(goonAName)); bitStream.Write(goonA->playerID); bitStream.Write(0); bitStream.Write(0); //not mythran nametag - PacketUtils::WritePacketWString(goonBName, 33, &bitStream); + bitStream.Write(LUWString(goonBName)); bitStream.Write(0); //not mythran for receiver bitStream.Write(3); //new whisper - PacketUtils::WritePacketWString(message, 512, &bitStream); + bitStream.Write(LUWString(message, 512)); SystemAddress sysAddr = goonB->sysAddr; SEND_PACKET; @@ -709,13 +710,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) { void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE); - PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); + bitStream.Write(LUWString(sender->playerName.c_str())); bitStream.Write(sender->playerID); SystemAddress sysAddr = receiver->sysAddr; @@ -724,7 +725,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -751,7 +752,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -776,7 +777,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -793,7 +794,7 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -822,7 +823,7 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -848,7 +849,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: @@ -882,16 +883,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla [bool] - is FTP*/ CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(friendData->playerID); //portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY); bitStream.Write(notifyType); std::string playerName = playerData->playerName.c_str(); - PacketUtils::WritePacketWString(playerName, 33, &bitStream); + bitStream.Write(LUWString(playerName)); bitStream.Write(playerData->zoneID.GetMapID()); bitStream.Write(playerData->zoneID.GetInstanceID()); @@ -921,12 +922,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send } CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST); - PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST); + bitStream.Write(LUWString(sender->playerName.c_str())); 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; @@ -937,16 +938,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen if (!receiver || !sender) return; CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); // Portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE); 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 != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS); // Then write the player name - PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream); + bitStream.Write(LUWString(sender->playerName.c_str())); // Then if this is an acceptance code, write the following extra info. if (responseCode == eAddFriendResponseType::ACCEPTED) { bitStream.Write(sender->playerID); @@ -962,13 +963,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers if (!receiver) return; CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); bitStream.Write(receiver->playerID); //portion that will get routed: - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE); bitStream.Write(isSuccessful); //isOnline - PacketUtils::WritePacketWString(personToRemove, 33, &bitStream); + bitStream.Write(LUWString(personToRemove)); SystemAddress sysAddr = receiver->sysAddr; SEND_PACKET; diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index b9fb8556a..185bccbf1 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -33,6 +33,7 @@ namespace Game { dChatFilter* chatFilter = nullptr; AssetManager* assetManager = nullptr; bool shouldShutdown = false; + std::mt19937 randomEngine; } @@ -114,6 +115,8 @@ int main(int argc, char** argv) { Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); + + Game::randomEngine = std::mt19937(time(0)); //Run it until server gets a kill message from Master: auto t = std::chrono::high_resolution_clock::now(); diff --git a/dChatServer/PlayerContainer.cpp b/dChatServer/PlayerContainer.cpp index 689ffd776..e49630ed8 100644 --- a/dChatServer/PlayerContainer.cpp +++ b/dChatServer/PlayerContainer.cpp @@ -6,10 +6,11 @@ #include "dLogger.h" #include "ChatPacketHandler.h" #include "GeneralUtils.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "Database.h" #include "eConnectionType.h" #include "eChatInternalMessageType.h" +#include "ChatPackets.h" PlayerContainer::PlayerContainer() { } @@ -146,7 +147,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) { void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); bitStream.Write(player); bitStream.Write(time); @@ -207,6 +208,14 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) { } void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) { + if (team->memberIDs.size() >= 4){ + Game::logger->Log("PlayerContainer", "Tried to add player to team that already had 4 players"); + auto* player = GetPlayerData(playerID); + if (!player) return; + ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!"); + return; + } + const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID); if (index != team->memberIDs.end()) return; @@ -345,7 +354,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) { void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE); bitStream.Write(team->teamID); bitStream.Write(deleteTeam); diff --git a/dCommon/NiPoint3.cpp b/dCommon/NiPoint3.cpp index b2ffa0d1d..5ad06f302 100644 --- a/dCommon/NiPoint3.cpp +++ b/dCommon/NiPoint3.cpp @@ -129,10 +129,19 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const { } //! Operator for addition of vectors -NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const { - return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z); +NiPoint3& NiPoint3::operator+=(const NiPoint3& point) { + this->x += point.x; + this->y += point.y; + this->z += point.z; + return *this; } +NiPoint3& NiPoint3::operator*=(const float scalar) { + this->x *= scalar; + this->y *= scalar; + this->z *= scalar; + return *this; +} //! Operator for subtraction of vectors NiPoint3 NiPoint3::operator-(const NiPoint3& point) const { diff --git a/dCommon/NiPoint3.h b/dCommon/NiPoint3.h index f76b9269d..44c3c3830 100644 --- a/dCommon/NiPoint3.h +++ b/dCommon/NiPoint3.h @@ -136,7 +136,9 @@ class NiPoint3 { NiPoint3 operator+(const NiPoint3& point) const; //! Operator for addition of vectors - NiPoint3 operator+=(const NiPoint3& point) const; + NiPoint3& operator+=(const NiPoint3& point); + + NiPoint3& operator*=(const float scalar); //! Operator for subtraction of vectors NiPoint3 operator-(const NiPoint3& point) const; diff --git a/dCommon/dClient/AssetManager.h b/dCommon/dClient/AssetManager.h index bc7e5ff76..d25434892 100644 --- a/dCommon/dClient/AssetManager.h +++ b/dCommon/dClient/AssetManager.h @@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf { } void close() { - delete m_Base; + free(m_Base); } }; diff --git a/dCommon/dEnums/dCommonVars.h b/dCommon/dEnums/dCommonVars.h index f67145da3..dc7a1d545 100644 --- a/dCommon/dEnums/dCommonVars.h +++ b/dCommon/dEnums/dCommonVars.h @@ -9,6 +9,7 @@ #include "BitStream.h" #include "eConnectionType.h" #include "eClientMessageType.h" +#include "BitStreamUtils.h" #pragma warning (disable:4251) //Disables SQL warnings @@ -32,7 +33,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate); #define CBITSTREAM RakNet::BitStream bitStream; #define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false); #define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits()); -#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); +#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); #define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false); #define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); diff --git a/dCommon/dEnums/eGameMessageType.h b/dCommon/dEnums/eGameMessageType.h index 051a5ae81..df822c52b 100644 --- a/dCommon/dEnums/eGameMessageType.h +++ b/dCommon/dEnums/eGameMessageType.h @@ -4,300 +4,1602 @@ #include enum class eGameMessageType : uint16_t { - TELEPORT = 19, - SET_PLAYER_CONTROL_SCHEME = 26, - DROP_CLIENT_LOOT = 30, - DIE = 37, - REQUEST_DIE = 38, - PLAY_EMOTE = 41, - PLAY_ANIMATION = 43, - CONTROL_BEHAVIOR = 48, - SET_NAME = 72, - ECHO_START_SKILL = 118, - START_SKILL = 119, - VERIFY_ACK = 121, - ADD_SKILL = 127, - REMOVE_SKILL = 128, - SET_CURRENCY = 133, - PICKUP_CURRENCY = 137, - PICKUP_ITEM = 139, - TEAM_PICKUP_ITEM = 140, - PLAY_FX_EFFECT = 154, - STOP_FX_EFFECT = 155, - REQUEST_RESURRECT = 159, - RESURRECT = 160, - PUSH_EQUIPPED_ITEMS_STATE = 191, - POP_EQUIPPED_ITEMS_STATE = 192, - SET_GM_LEVEL = 193, - SET_STUNNED = 198, - SET_STUN_IMMUNITY = 200, - KNOCKBACK = 202, - REBUILD_CANCEL = 209, - ENABLE_REBUILD = 213, - MOVE_ITEM_IN_INVENTORY = 224, - ADD_ITEM_TO_INVENTORY_CLIENT_SYNC = 227, - REMOVE_ITEM_FROM_INVENTORY = 230, - EQUIP_ITEM = 231, - UN_EQUIP_ITEM = 233, - OFFER_MISSION = 248, - RESPOND_TO_MISSION = 249, - NOTIFY_MISSION = 254, - NOTIFY_MISSION_TASK = 255, - REBUILD_NOTIFY_STATE = 336, - TERMINATE_INTERACTION = 357, - SERVER_TERMINATE_INTERACTION = 358, - REQUEST_USE = 364, - VENDOR_OPEN_WINDOW = 369, - BUY_FROM_VENDOR = 373, - SELL_TO_VENDOR = 374, - TEAM_SET_OFF_WORLD_FLAG = 383, - SET_INVENTORY_SIZE = 389, - ACKNOWLEDGE_POSSESSION = 391, - SET_SHOOTING_GALLERY_PARAMS = 400, - REQUEST_ACTIVITY_START_STOP = 402, - REQUEST_ACTIVITY_ENTER = 403, - REQUEST_ACTIVITY_EXIT = 404, - ACTIVITY_ENTER = 405, - ACTIVITY_EXIT = 406, - ACTIVITY_START = 407, - ACTIVITY_STOP = 408, - SHOOTING_GALLERY_CLIENT_AIM_UPDATE = 409, - SHOOTING_GALLERY_FIRE = 411, - REQUEST_VENDOR_STATUS_UPDATE = 416, - VENDOR_STATUS_UPDATE = 417, - NOTIFY_CLIENT_SHOOTING_GALLERY_SCORE = 425, - CONSUME_CLIENT_ITEM = 427, - CLIENT_ITEM_CONSUMED = 428, - UPDATE_SHOOTING_GALLERY_ROTATION = 448, - SET_FLAG = 471, - NOTIFY_CLIENT_FLAG_CHANGE = 472, - VENDOR_TRANSACTION_RESULT = 476, - HAS_BEEN_COLLECTED = 486, - DISPLAY_CHAT_BUBBLE = 495, - SPAWN_PET = 498, - DESPAWN_PET = 499, - PLAYER_LOADED = 505, - PLAYER_READY = 509, - REQUEST_LINKED_MISSION = 515, - INVALID_ZONE_TRANSFER_LIST = 519, - MISSION_DIALOGUE_OK = 520, - DISPLAY_MESSAGE_BOX = 529, - MESSAGE_BOX_RESPOND = 530, - CHOICE_BOX_RESPOND = 531, - SMASH = 537, - UNSMASH = 538, - PLACE_MODEL_RESPONSE = 547, - SET_SHOOTING_GALLERY_RETICULE_EFFECT = 548, - SET_JET_PACK_MODE = 561, - REGISTER_PET_ID = 565, - REGISTER_PET_DBID = 566, - SHOW_ACTIVITY_COUNTDOWN = 568, - START_ACTIVITY_TIME = 576, - ACTIVITY_PAUSE = 602, - USE_NON_EQUIPMENT_ITEM = 603, - USE_ITEM_RESULT = 607, - COMMAND_PET = 640, - PET_RESPONSE = 641, - REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA = 648, - SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA = 649, - NOTIFY_OBJECT = 656, - CLIENT_NOTIFY_PET = 659, - NOTIFY_PET = 660, - NOTIFY_PET_TAMING_MINIGAME = 661, - START_SERVER_PET_MINIGAME_TIMER = 662, - CLIENT_EXIT_TAMING_MINIGAME = 663, - PET_NAME_CHANGED = 686, - PET_TAMING_MINIGAME_RESULT = 667, - PET_TAMING_TRY_BUILD_RESULT = 668, - NOTIFY_TAMING_BUILD_SUCCESS = 673, - NOTIFY_TAMING_MODEL_LOADED_ON_SERVER = 674, - ACTIVATE_BUBBLE_BUFF = 678, - DEACTIVATE_BUBBLE_BUFF = 679, - ADD_PET_TO_PLAYER = 681, - REQUEST_SET_PET_NAME = 683, - SET_PET_NAME = 684, - NOTIFY_PET_TAMING_PUZZLE_SELECTED = 675, - SHOW_PET_ACTION_BUTTON = 692, - SET_EMOTE_LOCK_STATE = 693, - USE_ITEM_REQUIREMENTS_RESPONSE = 703, - PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT = 713, - DOWNLOAD_PROPERTY_DATA = 716, - QUERY_PROPERTY_DATA = 717, - PROPERTY_EDITOR_BEGIN = 724, - PROPERTY_EDITOR_END = 725, - IS_MINIFIG_IN_A_BUBBLE = 729, - START_PATHING = 733, - ACTIVATE_BUBBLE_BUFF_FROM_SERVER = 734, - DEACTIVATE_BUBBLE_BUFF_FROM_SERVER = 735, - NOTIFY_CLIENT_ZONE_OBJECT = 737, - UPDATE_REPUTATION = 746, - PROPERTY_RENTAL_RESPONSE = 750, - REQUEST_PLATFORM_RESYNC = 760, - PLATFORM_RESYNC = 761, - PLAY_CINEMATIC = 762, - END_CINEMATIC = 763, - CINEMATIC_UPDATE = 764, - TOGGLE_GHOST_REFERENCE_OVERRIDE = 767, - SET_GHOST_REFERENCE_POSITION = 768, - FIRE_EVENT_SERVER_SIDE = 770, - SET_NETWORK_SCRIPT_VAR = 781, - UPDATE_MODEL_FROM_CLIENT = 793, - DELETE_MODEL_FROM_CLIENT = 794, - PLAY_ND_AUDIO_EMITTER = 821, - PLAY2_DAMBIENT_SOUND = 831, - ENTER_PROPERTY1 = 840, - ENTER_PROPERTY2 = 841, - PROPERTY_ENTRANCE_SYNC = 842, - PROPERTY_SELECT_QUERY = 845, - PARSE_CHAT_MESSAGE = 850, - BROADCAST_TEXT_TO_CHATBOX = 858, - OPEN_PROPERTY_MANAGEMENT = 860, - OPEN_PROPERTY_VENDOR = 861, - UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK = 863, - CLIENT_TRADE_REQUEST = 868, + GET_POSITION = 0, + GET_ROTATION = 1, + GET_LINEAR_VELOCITY = 2, + GET_ANGULAR_VELOCITY = 3, + GET_FORWARD_VELOCITY = 4, + GET_PLAYER_FORWARD = 5, + GET_FORWARD_VECTOR = 6, + SET_POSITION = 7, + SET_LOCAL_POSITION = 8, + SET_ROTATION = 9, + SET_LINEAR_VELOCITY = 10, + MODIFY_LINEAR_VELOCITY = 11, + SET_ANGULAR_VELOCITY = 12, + MODIFY_ANGULAR_VELOCITY = 13, + DEFLECT = 14, + SEND_POSITION_UPDATE = 15, + SET_OBJECT_SCALE = 16, + GET_OBJECT_SCALE = 17, + TIMED_SCALE_FINISHED = 18, + TELEPORT = 19, + TOGGLE_PLAYER_FWD_TO_CAMERA = 20, + LOCK_PLAYER_ROT_TO_CAMERA = 21, + UNLOCK_PLAYER_ROT_FROM_CAMERA = 22, + TOGGLE_PLAYER_ROT_LOCK_TO_MOUSE = 23, + LOCK_PLAYER_ROT_TO_MOUSE = 24, + UNLOCK_PLAYER_ROT_FROM_MOUSE = 25, + SET_PLAYER_CONTROL_SCHEME = 26, + GET_PLAYER_CONTROL_SCHEME = 27, + RESET_PLAYER_CONTROL_SCHEME = 28, + PLAYER_TO_PREVIOUS_CONTROL_SCHEME = 29, + DROP_CLIENT_LOOT = 30, + GET_SPEED = 34, + GET_ROT_SPEED = 35, + IS_DEAD = 36, + DIE = 37, + REQUEST_DIE = 38, + ADD_OBJECT = 39, + PLAY_EMOTE = 41, + PRELOAD_ANIMATION = 42, + PLAY_ANIMATION = 43, + ANIMATION_COMPLETE = 44, + ENABLE_HIGHLIGHT = 45, + DISABLE_HIGHLIGHT = 46, + GET_ANIMATION_NAMES = 47, + CONTROL_BEHAVIORS = 48, + BLEND_PRIMARY_ANIMATION = 52, + SET_OFFSCREEN_ANIMATION = 53, + GET_MOVEMENT_INPUT_VALUES = 54, + SWAP_TEXTURE = 55, + SWAP_COLOR = 56, + ATTACH_HAIR = 57, + GET_ENTITY_STRUCT = 58, + SET_ENTITY_STRUCT = 59, + SET_ATTR = 60, + GET_ATTR = 61, + ON_HIT = 62, + HIT_OR_HEAL_RESULT = 63, + SHOW_ATTACK = 64, + GO_TO = 65, + GET_CONFIG_DATA = 66, + SET_CONFIG_DATA = 68, + GET_INVENTORY_EXTRA_INFO = 69, + GET_DISPLAY_NAME = 70, + GET_NAME = 71, + SET_NAME = 72, + IS_NAME_LOCALIZED = 73, + GET_HAIR_COLOR = 74, + SET_HAIR_COLOR = 75, + GET_HAIR_STYLE = 76, + SET_HAIR_STYLE = 77, + GET_HEAD = 78, + SET_HEAD = 79, + GET_TORSO = 80, + SET_TORSO = 81, + GET_LEGS = 82, + SET_LEGS = 83, + SET_PROXIMITY_RADIUS = 84, + PROXIMITY_UPDATE = 85, + GET_PROXIMITY_OBJECTS = 86, + UNSET_PROXIMITY_RADIUS = 87, + CLEAR_PROXIMITY_RADIUS = 88, + GET_PROXIMITY_DATA = 89, + SET_PROXIMITY_RADIUS_ICON = 90, + TOGGLE_TAC_ARC = 93, + CAST_SKILL = 95, + CAST_LOCAL_SKILL = 96, + ECHO_LOCAL_SKILL = 97, + QUEUE_AI_SKILL = 98, + ADD_THREAT_RATING = 99, + GET_THREAT_RATING = 100, + CLEAR_THREAT_LIST = 103, + GET_TIME_FOR_NPC_SKILL = 111, + ENEMY_HEAL_NOTIFICATION = 112, + RESET_SCRIPTED_AI_STATE = 113, + ENABLE_COMBAT_AI_COMPONENT = 114, + COMBAT_AI_FORCE_TETHER = 115, + SUSPEND_MOVEMENT_AI = 116, + NOTIFY_SCRIPT_VARS_INITIALIZED = 117, + ECHO_START_SKILL = 118, + START_SKILL = 119, + CASTER_DEAD = 120, + VERIFY_ACK = 121, + ADD_PENDING_VERIFY = 122, + MAP_SKILL = 123, + SELECT_SKILL = 124, + CAST_ACTIVE_SKILL = 125, + MODIFY_SKILL_COOLDOWN = 126, + ADD_SKILL = 127, + REMOVE_SKILL = 128, + LOG = 129, + LOG_CHAT = 130, + SET_MAX_CURRENCY = 131, + GET_MAX_CURRENCY = 132, + SET_CURRENCY = 133, + GET_CURRENCY = 134, + ADD_PENDING_CURRENCY = 136, + PICKUP_CURRENCY = 137, + SERVER_DELETE_LOOT_ITEM = 138, + PICKUP_ITEM = 139, + TEAM_PICKUP_ITEM = 140, + CLIENT_DELETE_LOOT_ITEM = 141, + CLIENT_SET_LOOT_ITEM_FFA = 143, + COLLISION_PHANTOM = 144, + OFF_COLLISION_PHANTOM = 145, + COLLISION_PROXIMITY = 146, + OFF_COLLISION_PROXIMITY = 147, + COLLISION = 148, + OFF_COLLISION = 149, + GET_SKILLS = 150, + CLEAR_FX_SINGLE_EFFECT = 152, + GET_FX_EXIST_EFFECT = 153, + PLAY_FX_EFFECT = 154, + STOP_FX_EFFECT = 155, + CLEAR_FX_ALL_CREATE_EFFECTS = 156, + UPDATE_FX_ALL_CREATE_EFFECTS = 157, + REQUEST_RESURRECT = 159, + RESURRECT = 160, + UPDATE_FROM_GHOST = 162, + FETCH_GHOST = 163, + KFM_LOADED = 164, + NIF_LOADED = 165, + HKX_LOADED = 166, + MOVE_TO_DELETE_QUEUE = 167, + RESTORE_FROM_DELETE_QUEUE = 168, + IS_ENEMY = 169, + GET_FACTION = 170, + SET_IMAGINATION = 171, + GET_IMAGINATION = 172, + SET_MAX_IMAGINATION = 173, + GET_MAX_IMAGINATION = 174, + MODIFY_IMAGINATION = 175, + MODIFY_MAX_IMAGINATION = 176, + SET_HEALTH = 177, + GET_HEALTH = 178, + SET_MAX_HEALTH = 179, + GET_MAX_HEALTH = 180, + MODIFY_HEALTH = 181, + MODIFY_MAX_HEALTH = 182, + SET_ARMOR = 183, + GET_ARMOR = 184, + SET_MAX_ARMOR = 185, + GET_MAX_ARMOR = 186, + MODIFY_ARMOR = 187, + MODIFY_MAX_ARMOR = 188, + POP_HEALTH_STATE = 190, + PUSH_EQUIPPED_ITEMS_STATE = 191, + POP_EQUIPPED_ITEMS_STATE = 192, + SET_GM_LEVEL = 193, + GET_GM_LEVEL = 194, + ADD_STATUS_EFFECT = 196, + REMOVE_STATUS_EFFECT = 197, + SET_STUNNED = 198, + GET_STUNNED = 199, + SET_STUN_IMMUNITY = 200, + GET_STUN_IMMUNITY = 201, + KNOCKBACK = 202, + SET_VISIBLE = 203, + GET_VISIBLE = 204, + REPORT_ITEM_INFO = 205, + GET_REBUILD_STATE = 207, + REBUILD_CANCEL = 209, + REBUILD_START = 211, + ENABLE_REBUILD = 213, + SKILL_FAILURE = 214, + IS_ATTACK_STANCE = 216, + SET_OBJECT_RENDER = 217, + REQUEST_MAPPED_SKILLS = 218, + UI_SELECT_MAPPED_SKILL = 219, + GET_INVENTORY_ITEM_IN_SLOT = 220, + GET_FIRST_INVENTORY_ITEM_BY_LOT = 221, + GET_SMALLEST_INVENTORY_STACK_BY_LOT = 222, + MOVE_ITEM_IN_INVENTORY = 224, + ADD_ITEM_TO_INVENTORY_CLIENT_SYNC = 227, + GET_EQUIPPED_ITEMS = 229, + REMOVE_ITEM_FROM_INVENTORY = 230, + EQUIP_INVENTORY = 231, + UN_EQUIP_INVENTORY = 233, + EQUIP_ITEM = 234, + UN_EQUIP_ITEM = 235, + IS_ITEM_RESPOND = 236, + IS_ITEM_EQUIPPED = 237, + ATTACH_ITEM = 238, + DETACH_ITEM = 239, + GET_NODE = 240, + GET_LOT = 241, + IS_ITEM_EQUIPPABLE = 242, + GET_CURRENT_ANIMATION = 243, + GET_INV_ITEM_COUNT = 244, + POST_LOAD_EQUIP = 245, + SET_PHYSICS_ACTIVE_STATE = 246, + GET_CURRENT_SKILL_TAC_ARC = 247, + OFFER_MISSION = 248, + RESPOND_TO_MISSION = 249, + GET_MISSION_STATE = 250, + GET_MISSION_COMPLETE_TIMESTAMP = 251, + NOTIFY_MISSION = 254, + NOTIFY_MISSION_TASK = 255, + ARE_GFX_LOADED = 257, + ADDED_TO_WORLD = 258, + REMOVE_EXTRA_GFX_FROM_PIPE = 259, + HIDE_EQUIPED_WEAPON = 260, + UN_HIDE_EQUIPED_WEAPON = 261, + GET_ITEM_SLOT = 262, + IS_CHARACTER = 263, + SET_IMMUNITY = 264, + TOGGLE_TOOLTIPS = 266, + GET_TOOLTIPS_DISABLED = 267, + GET_BOUNDING_INFO = 268, + OVERRIDE_BOUNDING_RADIUS = 269, + GET_OFFSCREEN = 270, + USE_STATE_MACHINE = 271, + ADD_STATE = 272, + ADD_SUB_STATE = 273, + SET_STATE = 274, + SET_SUB_STATE = 275, + ADD_MESSAGE = 276, + RELOAD_SCRIPT = 277, + RELOAD_ALL_SCRIPTS = 278, + FRIEND_INVITE_MSG = 279, + ADD_FRIEND_REPOSNSE_MSG = 280, + REMOVE_FRIEND_RESPONSE_MSG = 281, + ADD_FRIEND_FROM_UI_MSG = 282, + GET_CACHED_FRIENDS_LIST_MSG = 283, + REQUEST_NEW_FRIENDS_LIST_MSG = 284, + REPOPULATE_FRIENDS_LIST_MSG = 285, + ADD_IGNORE_REPONSE_MSG = 286, + REMOVE_IGNORE_RESPONSE_MSG = 287, + ADD_IGNORE_FROM_UI_MSG = 288, + GET_CACHED_IGNORE_LIST_MSG = 289, + REQUEST_NEW_IGNORE_LIST_MSG = 290, + REMOVE_FRIEND_BY_NAME = 291, + REMOVE_IGNORE_BY_NAME = 292, + IS_PLAYER_IN_IGNORE_LIST_MSG = 293, + REPOPULATE_IGNORE_LIST_MSG = 294, + GET_INVENTORY_LIST = 295, + UPDATE_FRIEND_MSG = 296, + UPDATE_FRIEND_NAME_MSG = 297, + UPDATE_IGNORE_NAME_MSG = 298, + DEPARTED = 299, + ARRIVED = 300, + TEMPLATE_CHANGE_WAYPOINTS = 301, + CANCELLED = 302, + FLUSH_CACHED_GRAPHICS = 303, + FOLLOW_TARGET = 304, + TIMER_DONE = 305, + TIMER_CANCELLED = 306, + SET_TETHER_POINT = 307, + GET_TETHER_POINT = 308, + LEFT_TETHER_RADIUS = 309, + GET_SCRIPT_VARS_PTR = 310, + FACE_TARGET = 311, + ROTATE_BY_DEGREES = 312, + STRING_RENDERED = 313, + RESET_PRIMARY_ANIMATION = 314, + FACE_PLAY_STREAM = 315, + TORSO_PLAY_STREAM = 316, + CAN_PICKUP = 317, + GET_INVENTORY_SIZE = 318, + GET_INVENTORY_COUNT = 319, + GET_OBJECTS_IN_GROUP = 320, + HIDE_ITEM = 321, + IS_OBJECT_IN_FOV = 322, + GET_TYPE = 323, + TEAM_INVITE_MSG = 324, + TEAM_GET_SIZE = 325, + TEAM_REQUEST_SET_LOOT = 326, + TEAM_REMOVE_PLAYER_MSG = 327, + TEAM_UPDATE_PLAYER_NAME_MSG = 328, + SET_UPDATABLE = 329, + REQUEST_TEAM_UI_UPDATE = 330, + SET_COLLISION_GROUP = 331, + GET_COLLISION_GROUP = 332, + GET_ORIGINAL_COLLISION_GROUP = 333, + SET_COLLISION_GROUP_TO_ORIGINAL = 334, + GET_OBJECT_RADIUS = 335, + REBUILD_NOTIFY_STATE = 336, + GET_PLAYER_INTERACTION = 337, + SET_PLAYER_INTERACTION = 338, + FORCE_PLAYER_TO_INTERACT = 339, + GET_SELECTED_POTENTIAL_INTERACTION = 340, + SET_SELECTED_POTENTIAL_INTERACTION = 341, + GET_INTERACTION_DISTANCE = 342, + SET_INTERACTION_DISTANCE = 343, + CALCULATE_INTERACTION_DISTANCE = 344, + INTERACTION_ATTEMPT_FROM_OUT_OF_RANGE = 345, + SET_PICKING_TARGET = 346, + CLIENT_UNUSE = 347, + BEGIN_PET_INTERACTION = 348, + WANTS_INTERACTION_ICON = 349, + PROPERTY_EDIT_ICON_INTERACTION = 350, + PROPERTY_MODEL_INTERACTION = 351, + GET_INTERACTION_DETAILS = 352, + GET_DISABLED_INTERACTION_TYPES = 353, + GET_INTERACTION_INFO = 354, + INTERACTION_GAME_STATE_CHANGE = 355, + TOGGLE_INTERACTION_UPDATES = 356, + TERMINATE_INTERACTION = 357, + SERVER_TERMINATE_INTERACTION = 358, + GET_PLAYERS_TARGET_FOR_SELECTION = 359, + PROCESS_INTERACTION_UNDER_CURSOR = 360, + HANDLE_INTERACT_ACTION = 361, + ATTEMPT_INTERACTION = 362, + HANDLE_INTERACTION_CAMERA = 363, + REQUEST_USE = 364, + CLIENT_USE = 366, + GET_PLAYER_MULTI_INTERACTION = 367, + GET_MULTI_INTERACTION_STATE = 368, + VENDOR_OPEN_WINDOW = 369, + VENDOR_CLOSE_WINDOW = 370, + EMOTE_PLAYED = 371, + EMOTE_RECEIVED = 372, + BUY_FROM_VENDOR = 373, + SELL_TO_VENDOR = 374, + ADD_DONATION_ITEM = 375, + REMOVE_DONATION_ITEM = 376, + CONFIRM_DONATION_ON_PLAYER = 378, + CANCEL_DONATION_ON_PLAYER = 379, + TEAM_GET_LEADER = 380, + TEAM_GET_ON_WORLD_MEMBERS = 381, + TEAM_GET_ALL_MEMBERS = 382, + TEAM_SET_OFF_WORLD_FLAG = 383, + SET_TRANSPARENCY = 385, + GET_PREFERS_FADE = 386, + PROJECTILE_IMPACT = 387, + SET_PROJECTILE_PARAMS = 388, + SET_INVENTORY_SIZE = 389, + ACKNOWLEDGE_POSSESSION = 391, + SET_POSSESSED_OBJECT = 392, + CHANGE_POSSESSOR = 393, + GET_POSSESSION_TYPE = 395, + GET_POSSESSED_OBJECT = 396, + GET_POSSESSOR = 397, + IS_POSSESSED = 398, + ENABLE_ACTIVITY = 399, + SET_SHOOTING_GALLERY_PARAMS = 400, + OPEN_ACTIVITY_START_DIALOG = 401, + REQUEST_ACTIVITY_START_STOP = 402, + REQUEST_ACTIVITY_ENTER = 403, + REQUEST_ACTIVITY_EXIT = 404, + ACTIVITY_ENTER = 405, + ACTIVITY_EXIT = 406, + ACTIVITY_START = 407, + ACTIVITY_STOP = 408, + SHOOTING_GALLERY_CLIENT_AIM_UPDATE = 409, + ROTATE_TO_POINT = 410, + SHOOTING_GALLERY_FIRE = 411, + CALCULATE_FIRING_PARAMETERS = 412, + GET_MUZZLE_OFFSET = 413, + GET_ACTIVITY_POINTS = 414, + TEAM_IS_ON_WORLD_MEMBER = 415, + REQUEST_VENDOR_STATUS_UPDATE = 416, + VENDOR_STATUS_UPDATE = 417, + CANCEL_MISSION = 418, + RESET_MISSIONS = 419, + RENDER_COMPONENT_READY = 420, + SEND_MINIFIG_DECALS = 421, + PHYSICS_COMPONENT_READY = 422, + ENTER_STANDBY_MODE = 423, + LEAVE_STANDBY_MODE = 424, + NOTIFY_CLIENT_SHOOTING_GALLERY_SCORE = 425, + REQUEST_CONSUME_ITEM = 426, + CONSUME_CLIENT_ITEM = 427, + CLIENT_ITEM_CONSUMED = 428, + QUERY_STANDBY_MODE = 429, + GET_NI_BOUND = 430, + MISSION_FAILURE = 431, + GET_ANIMATION_TIME = 432, + GET_CURRENT_ACTIVITY = 434, + SET_EYEBROWS = 435, + GET_EYEBROWS = 436, + SET_EYES = 437, + GET_EYES = 438, + SET_MOUTH = 439, + GET_MOUTH = 440, + IS_OBJECT_SMASHABLE = 441, + SMASHABLE_STATE_CHANGED = 443, + USE_STATE_LOGGER = 444, + ROTATE_SUB_NODE = 445, + GET_SUB_NODE_POSITION = 446, + GET_SUB_NODE = 447, + UPDATE_SHOOTING_GALLERY_ROTATION = 448, + RENDER_FLOATING_TEXT = 449, + REQUEST2_D_TEXT_ELEMENT = 450, + UPDATE2_D_TEXT_ELEMENT = 451, + REMOVE2_D_TEXT_ELEMENT = 452, + SET_COLOR = 453, + GET_COLOR = 454, + HKX_CHARACTER_LOADED = 455, + ACTIVATE_PHYSICS = 457, + SET_ICON_ABOVE_HEAD = 458, + ADD_ICON_COMPOSITE = 459, + CLEAR_ICON_COMPOSITES = 460, + ICON_NIF_LOADED = 461, + ICON_KFM_LOADED = 462, + GET_OVERHEAD_ICON_PROPERTIES_FROM_PARENT = 463, + BOUNCE_PLAYER = 464, + SET_USER_CTRL_COMP_PAUSE = 466, + HAS_COLLIDED = 467, + GET_TOOLTIP_FLAG = 468, + SET_TOOLTIP_FLAG = 469, + GET_FLAG = 470, + SET_FLAG = 471, + NOTIFY_CLIENT_FLAG_CHANGE = 472, + CURSOR_ON = 473, + CURSOR_OFF = 474, + HELP = 475, + VENDOR_TRANSACTION_RESULT = 476, + PERFORM_SPECIAL_DEATH = 477, + GET_SHADER_ID = 478, + GET_RENDER_ENVIRONMENT = 479, + FINISHED_LOADING_SCENE = 480, + GET_SKILL_INFO = 481, + ACTIVITY_CANCEL = 482, + MISSION_USES_OBJECT = 483, + GET_POSITIONAL_ID = 484, + SET_COLLECTIBLE_STATUS = 485, + HAS_BEEN_COLLECTED = 486, + HAS_BEEN_COLLECTED_BY_CLIENT = 487, + GET_POS_UPDATE_STATS = 488, + GET_NUM_VIEWERS_SCOPING_THIS = 489, + GET_ACTIVITY_USER = 490, + GET_ALL_ACTIVITY_USERS = 491, + GET_MISSION_FOR_PLAYER = 492, + SET_FACTION = 493, + SET_PLATFORM_IDLE_STATE = 494, + DISPLAY_CHAT_BUBBLE = 495, + REQUEST_CHAT_BUBBLE_ELEMENT = 496, + GET_MISSION_DATA = 497, + SPAWN_PET = 498, + DESPAWN_PET = 499, + SET_LOCAL_SPACE_STATE = 500, + GET_LOCAL_SPACE_STATE = 501, + SET_POSITION_TO_LOCAL_POSITION = 502, + ALLOW_LOCAL_SPACE_UPDATE = 503, + TOGGLE_FREE_CAM_MODE = 504, + PLAYER_LOADED = 505, + PLAYER_ADDED_TO_WORLD_LOCAL = 506, + OBJECT_LOADED = 507, + GET_PLAYER_READY = 508, + PLAYER_READY = 509, + SET_SMASHABLE_PARAMS = 510, + IS_LOOTABLE_CHEST = 511, + LOOT_OPEN_WINDOW = 512, + LOOT_SELECTION_UPDATE = 513, + TAKE_LOOT_CHEST_ITEM = 514, + REQUEST_LINKED_MISSION = 515, + TRANSFER_TO_ZONE = 516, + TRANSFER_TO_ZONE_CHECKED_IM = 517, + SECURED_TRANSFER_TO_ZONE = 518, + INVALID_ZONE_TRANSFER_LIST = 519, + MISSION_DIALOGUE_OK = 520, + GET_OBJECT_IN_SCOPE = 521, + SET_LAUNCHED_STATE = 522, + P_CREATE_EFFECT_FINISHED = 523, + SMASHED_OBJECT = 524, + CHECK_SMASHCHAIN_OVERRIDE = 525, + DISPLAY_REBUILD_ACTIVATOR = 526, + TRANSFER_TO_LAST_NON_INSTANCE = 527, + SET_ACTIVE_LOCAL_CHARACTER_ID = 528, + DISPLAY_MESSAGE_BOX = 529, + MESSAGE_BOX_RESPOND = 530, + CHOICE_BOX_RESPOND = 531, + SERVER_SET_USER_CTRL_COMP_PAUSE = 532, + SET_CHARACTER_AUTO_RUN = 533, + FOLLOW_WAYPOINTS = 534, + SWAP_DECAL_AND_COLOR = 535, + CONTINUE_WAYPOINTS = 536, + SMASH = 537, + UN_SMASH = 538, + GET_IS_SMASHED = 539, + GET_UP_VECTOR = 540, + SET_GRAVITY_SCALE = 541, + SET_GRAVITY_SCALE_FOR_RIGID_BODY = 542, + STOP_MOVING = 543, + SET_PATHING_SPEED = 544, + SET_SHIELDED = 545, + SET_SHOOTING_GALLERY_RETICULE_EFFECT = 546, + PLACE_MODEL_RESPONSE = 547, + SET_DODGE_INFO = 548, + GET_DODGE_INFO = 549, + SET_SKILL_ATTACK_SPEED = 550, + GET_SKILL_COOLDOWN_GROUP = 551, + GET_INITIAL_SKILL_COOLDOWN = 552, + GET_SKILL_COOLDOWN_REMAINING = 553, + GET_GLOBAL_COOLDOWN = 554, + SET_GLOBAL_COOLDOWN = 555, + RESET_GLOBAL_COOLDOWN = 556, + FINDINVENTORY_ITEM = 558, + PATH_STUCK = 559, + SET_CURRENT_PATH = 560, + SET_JET_PACK_MODE = 561, + SET_JET_PACK_TIME = 562, + PET_FOLLOW_OWNER = 563, + PLAYER_DIED = 564, + REGISTER_PET_ID = 565, + REGISTER_PET_DBID = 566, + GET_PET_ID = 567, + SHOW_ACTIVITY_COUNTDOWN = 568, + DISPLAY_TOOLTIP = 569, + SET_PHANTOM_BASE = 570, + GET_MOTION_STATE = 571, + GET_MOTION_CONFIG = 572, + SET_ACTIVE_PROJECTILE_SKILL = 573, + INITIALIZE_MISSION_VISUALS = 574, + GET_MISSIONS = 575, + START_ACTIVITY_TIME = 576, + ADD_ACTIVITY_TIME = 577, + GUILD_GET_SIZE = 578, + GUILD_CAN_WE_INVITE = 579, + GUILD_CAN_WE_KICK = 580, + SET_CHAR_GUILD_INFO = 581, + GET_CHAR_GUILD_INFO = 582, + GET_CHAR_IS_IN_GUILD = 583, + RE_RENDER_NAME_BILLBOARD = 584, + IS_IN_LOCAL_CHAR_PROXIMITY = 585, + GUILD_SET_STATUS = 586, + GUILD_ADD_PLAYER = 587, + GUILD_REMOVE_PLAYER = 588, + GUILD_UPDATE_PLAYER_NAME = 589, + GUILD_SET_PLAYER_RANK = 590, + GUILD_SET_ONLINE_STATUS = 591, + GUILD_INVITE = 592, + REQUEST_GUILD_DATA = 593, + POPULATE_GUILD_DATA = 594, + GET_CACHED_GUILD_DATA = 595, + GUILD_RENDER_NAME = 596, + GET_IS_SUPPORTED = 600, + CHARACTER_SUPPORT_CHANGED = 601, + ACTIVITY_PAUSE = 602, + USE_NON_EQUIPMENT_ITEM = 603, + REQUEST_USE_ITEM_ON = 604, + REQUEST_USE_ITEM_ON_TARGET = 605, + USE_ITEM_ON = 606, + USE_ITEM_RESULT = 607, + GET_PARENT_OBJ = 608, + SET_PARENT_OBJ = 609, + GET_UPDATES_WITH_PARENT_POSITION = 610, + PARENT_REMOVED = 611, + PARENT_LEFT_SCOPE = 612, + PARENT_ENTERED_SCOPE = 613, + CHILD_LOADED = 614, + CHILD_REMOVED = 615, + CHILD_DETACHED = 616, + CHILD_ENTERED_SCOPE = 617, + CHILD_LEFT_SCOPE = 618, + GET_CHILD_OBJECTS = 619, + ZONE_TRANSFER_FINISHED = 621, + CHAT_CONNECTION_UPDATE = 622, + PLATFORM_AT_LAST_WAYPOINT = 623, + LOOT_TAKE_ALL = 624, + GET_EQUIPPED_ITEM_INFO = 625, + DISPLAY_GUILD_CREATE_BOX = 626, + GET_EDITOR_LEVEL = 627, + GET_ACCOUNT_ID = 628, + GET_LAST_LOGOUT = 629, + GET_LAST_PROP_MOD_DISPLAY_TIME = 630, + SET_LAST_PROP_MOD_DISPLAY_TIME = 631, + SHOW_ACTIVITY_SUMMARY = 632, + CAN_RECEIVE_ALL_REWARDS = 633, + GET_ACTIVITY_REWARD = 634, + LOOT_CLOSE_WINDOW = 635, + GET_BLUEPRINT_ID = 636, + NOTIFY_BLUEPRINT_UPDATE = 637, + FETCH_MODEL_METADATA_REQUEST = 638, + FETCH_MODEL_METADATA_RESPONSE = 639, + COMMAND_PET = 640, + PET_RESPONSE = 641, + GET_ICON_ABOVE_HEAD_STATE = 642, + GET_ICON_ABOVE_HEAD = 643, + ICON_FINISHED_LOADING = 644, + ADD_PET_STATE = 645, + REMOVE_PET_STATE = 646, + SET_PET_STATE = 647, + REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA = 648, + SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA = 649, + SET_ON_TEAM = 650, + GET_PET_HAS_STATE = 651, + FIND_PROPERTY = 652, + SET_PET_MOVEMENT_STATE = 653, + GET_ITEM_TYPE = 654, + GET_ITEM_INFO_KEY = 655, + NOTIFY_OBJECT = 656, + IS_PET_WILD = 657, + CLIENT_NOTIFY_PET = 659, + NOTIFY_PET = 660, + NOTIFY_PET_TAMING_MINIGAME = 661, + START_SERVER_PET_MINIGAME_TIMER = 662, + CLIENT_EXIT_TAMING_MINIGAME = 663, + GET_BUILDMODE_ACTIVE = 664, + GET_PET_TAMING_MINIGAME_ACTIVE = 665, + PET_TAMING_OBJECT_PICKED = 666, + PET_TAMING_MINIGAME_RESULT = 667, + PET_TAMING_TRY_BUILD_RESULT = 668, + SET_PET_TAMING_MODEL = 669, + GET_PET_TAMING_MODEL = 670, + PET_ON_SWITCH = 671, + PET_OFF_SWITCH = 672, + NOTIFY_TAMING_BUILD_SUCCESS = 673, + NOTIFY_TAMING_MODEL_LOADED_ON_SERVER = 674, + NOTIFY_TAMING_PUZZLE_SELECTED = 675, + GET_INSTRUCTION_COUNT = 676, + GET_IS_NPC = 677, + ACTIVATE_BUBBLE_BUFF = 678, + DECTIVATE_BUBBLE_BUFF = 679, // thanks netdevil + EXHIBIT_VOTE = 680, + ADD_PET_TO_PLAYER = 681, + REMOVE_PET_FROM_PLAYER = 682, + REQUEST_SET_PET_NAME = 683, + SET_PET_NAME = 684, + PET_NAME_CHANGED = 686, + GET_PET_AT_INDEX = 687, + GET_LOT_FOR_PET_BY_DBID = 688, + GET_NAME_FOR_PET_BY_DBID = 689, + GET_ACTIVE_PET_OBJ_ID = 690, + GET_ACTIVE_PET_INVENTORY_OBJ_ID = 691, + SHOW_PET_ACTION_BUTTON = 692, + SET_EMOTE_LOCK_STATE = 693, + GET_EMOTE_LOCK_STATE = 694, + LEAVE_TEAM_MSG = 695, + TEAM_KICK_PLAYER_MSG = 697, + TEAM_SET_LEADER_SEND_MSG = 698, + USE_ITEM_ON_CLIENT = 699, + DOES_FORWARD_TARGET_CLICKING = 700, + CHECK_USE_REQUIREMENTS = 701, + USE_REQUIREMENTS_RESPONSE = 702, + USE_ITEM_REQUIREMENTS_RESPONSE = 703, + PET_ADDED_TO_WORLD = 704, + BOUNCER_TRIGGERED = 705, + EXHIBIT_QUERY_CURRENT_MODEL = 706, + EXHIBIT_QUERY_CURRENT_MODEL_RESPONSE = 707, + EXHIBIT_ATTEMPT_VOTE = 708, + EXHIBIT_VOTE_RESPONSE = 709, + EHIBIT_REQUERYMODELS = 710, + IS_SKILL_ACTIVE = 711, + TOGGLE_ACTIVE_SKILL = 712, + PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT = 713, + EXHIBIT_GET_INFO = 714, + GET_PROPERTY_DATA = 715, + DOWNLOAD_PROPERTY_DATA = 716, + QUERY_PROPERTY_DATA = 717, + MODEL_MODERATION_ACTION = 719, + NOTIFY_SERVER_UGC_REVIEW_READY = 720, + NOTIFY_CLIENT_UGC_REVIEW_READY = 721, + OLD_USE_ITEM_ON = 722, + FIND_PROPERTY_FOR_SALE_RESPONSE = 723, + PROPERTY_EDITOR_BEGIN = 724, + PROPERTY_EDITOR_END = 725, + PROPERTY_EDITOR_SET_MODE = 726, + TOGGLE_TRIGGER = 727, + FIRE_EVENT = 728, + IS_MINIFIG_IN_A_BUBBLE = 729, + GET_ITEM_INFO = 730, + MISSION_NEEDS_LOT = 731, + STOP_PATHING = 732, + START_PATHING = 733, + ACTIVATE_BUBBLE_BUFF_FROM_SERVER = 734, + DEACTIVATE_BUBBLE_BUFF_FROM_SERVER = 735, + HAS_SKILL = 736, + NOTIFY_CLIENT_ZONE_OBJECT = 737, + MOVE_OBJECT = 738, + ROTATE_OBJECT = 739, + GET_SPAWNER_CONFIG_DATA = 740, + UPDATE_SPAWNER_CONFIG_DATA = 741, + TURN_AROUND = 743, + GO_FORWARD = 744, + GO_BACKWARD = 745, + UPDATE_REPUTATION = 746, + GET_REPUTATION = 747, + ADD_REPUTATION = 748, + UPDATE_PROPERTY_DATA = 749, + PROPERTY_RENTAL_RESPONSE = 750, + EXHIBIT_PLACEMENT_RESPONSE = 751, + SQUIRT_WITH_WATERGUN = 752, + GET_VOTES_LEFT = 753, + ADJUST_VOTES_LEFT = 754, + EVADE_TARGET = 755, + STOPPED_EVADING = 756, + GET_PET_HAS_ABILITY = 757, + REQUEST_PLATFORM_RESYNC = 760, + PLATFORM_RESYNC = 761, + PLAY_CINEMATIC = 762, + END_CINEMATIC = 763, + CINEMATIC_UPDATE = 764, + ATTACH_CAMERA_TO_RAIL = 765, + DETACH_CAMERA_FROM_RAIL = 766, + TOGGLE_GHOST_REFERENCE_OVERRIDE = 767, + SET_GHOST_REFERENCE_POSITION = 768, + GET_GHOST_REFERENCE_POSITION = 769, + FIRE_EVENT_SERVER_SIDE = 770, + GET_PET_ABILITY_OBJECT = 771, + TEAM_INVITE_MSG_FROM_UI = 772, + ADD_CAMERA_EFFECT = 773, + REMOVE_CAMERA_EFFECT = 774, + REMOVE_ALL_CAMERA_EFFECTS = 775, + GET_MY_PROPERTIES_IN_THIS_ZONE = 776, + IS_MODEL_WITHIN_PROPERTY_BOUNDS = 777, + PROPERTY_DATA_RESULTS = 778, + ON_UN_SERIALIZE = 779, + SCRIPT_NETWORK_VAR_UPDATE = 781, + ADD_OBJECT_TO_GROUP = 783, + REMOVE_OBJECT_FROM_GROUP = 784, + IS_OBJECT_STATIC = 785, + GET_HAS_MISSION = 786, + GET_MISSION_TARGET_LOT = 787, + GET_MISSION_OFFERER_LOT = 788, + USE_UNIQUE_ITEM = 789, + GET_IS_PET = 790, + DELETE_PROPERTY = 791, + CREATEMODEL_FROM_CLIENT = 792, + UPDATE_MODEL_FROM_CLIENT = 793, + DELETE_MODEL_FROM_CLIENT = 794, + SHOW_PROPERTY_BOUNDS = 795, + SET_PROPERTY_I_DS = 796, + PLAY_FACE_DECAL_ANIMATION = 797, + ADD_ACTIVITY_USER = 798, + REMOVE_ACTIVITY_USER = 799, + GET_NUM_ACTIVITY_USERS = 800, + ACTIVITY_USER_EXISTS = 801, + DO_COMPLETE_ACTIVITY_EVENTS = 805, + SET_ACTIVITY_PARAMS = 806, + SET_ACTIVITY_USER_DATA = 807, + GET_ACTIVITY_USER_DATA = 808, + DO_CALCULATE_ACTIVITY_RATING = 809, + ND_AUDIO_POST_SETUP = 812, + ND_AUDIO_PRE_SHUTDOWN = 813, + SET_ND_AUDION_LISTENER_STANCE = 814, + SET_UP_ND_AUDIO_EMIITTER = 815, + SHUT_DOWN_ND_AUDIO_EMITTER = 816, + METAIFY_ND_AUDIO_EMITTER = 817, + UN_METAIFY_ND_AUDIO_EMITTER = 818, + METAIFY_ND_AUDIO_EMITTERS = 819, + UN_METAIFY_ND_AUDIO_EMITTERS = 820, + PLAY_ND_AUDIO_EMITTER = 821, + STOP_ND_AUDIO_EMITTER = 822, + STOP_ND_AUDIO_EMITTER_ALL = 823, + SET_ND_AUDIO_EMITTER_PARAMETER = 824, + SET_ND_AUDIO_EMITTERS_PARAMETER = 825, + ND_AUDIO_CALLBACK = 826, + ACTIVATE_ND_AUDIO_MUSIC_CUE = 827, + DEACTIVATE_ND_AUDIO_MUSIC_CUE = 828, + FLASH_ND_AUDIO_MUSIC_CUE = 829, + SET_ND_AUDIO_MUSIC_PARAMETER = 830, + PLAY2_D_AMBIENT_SOUND = 831, + STOP2_D_AMBIENT_SOUND = 832, + PLAY3_D_AMBIENT_SOUND = 834, + STOP3_D_AMBIENT_SOUND = 835, + ACTIVATE_ND_AUDIO_MIXER_PROGRAM = 836, + DEACTIVATE_ND_AUDIO_MIXER_PROGRAM = 837, + UPDATE_ACTIVITY_LEADERBOARD = 838, + ACTIVITY_LEADERBOARD_UPDATED = 839, + ENTER_PROPERTY1 = 840, + ENTER_PROPERTY2 = 841, + PROPERTY_ENTRANCE_SYNC = 842, + SEND_PROPERTY_POPULATION_TO_CLIENT = 843, + SEN_PROPERTY_PLAQUE_VIS_UPDATE = 844, + PROPERTY_SELECT_QUERY = 845, + CREATE_POSITION_STRING = 848, + GET_PARALLEL_POSITION = 849, + PARSE_CHAT_MESSAGE = 850, + SET_MISSION_TYPE_STATE = 851, + GET_LOCATIONS_VISITED = 852, + GET_MISSION_TYPE_STATES = 853, + GET_TIME_PLAYED = 854, + SET_MISSION_VIEWED = 855, + SLASH_COMMAND_TEXT_FEEDBACK = 856, + HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 857, + BROADCAST_TEXT_TO_CHATBOX = 858, + OPEN_PROPERTY_MANAGEMENT = 860, + OPEN_PROPERTY_VENDOR = 861, + VOTE_ON_PROPERTY = 862, + UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK = 863, + NOTIFY_PLAYER_OF_PROPERTY_SUBMISSION = 865, + NOTIFY_PLAYER_OF_MODEL_SUBMISSION = 866, + PHYSICS_SYSTEM_LOADED = 867, + CLIENT_TRADE_REQUEST = 868, SERVER_TRADE_REQUEST = 869, - SERVER_TRADE_INVITE = 870, - CLIENT_TRADE_REPLY = 871, + SERVER_TRADE_INVITE = 870, + CLIENT_TRADE_REPLY = 871, SERVER_TRADE_REPLY = 872, - SERVER_TRADE_INITIAL_REPLY = 873, - SERVER_TRADE_FINAL_REPLY = 874, - CLIENT_TRADE_UPDATE = 875, + SERVER_TRADE_INITIAL_REPLY = 873, + SERVER_TRADE_FINAL_REPLY = 874, + CLIENT_TRADE_UPDATE = 875, SERVER_SIDE_TRADE_UPDATE = 876, - SERVER_TRADE_UPDATE = 877, - CLIENT_TRADE_CANCEL = 878, - CLIENT_SIDE_TRADE_CANCEL = 879, - CLIENT_TRADE_ACCEPT = 880, + SERVER_TRADE_UPDATE = 877, + CLIENT_TRADE_CANCEL = 878, + CLIENT_SIDE_TRADE_CANCEL = 879, + CLIENT_TRADE_ACCEPT = 880, SERVER_SIDE_TRADE_ACCEPT = 881, SERVER_SIDE_TRADE_CANCEL = 882, - SERVER_TRADE_CANCEL = 883, - SERVER_TRADE_ACCEPT = 884, - READY_FOR_UPDATES = 888, - ORIENT_TO_OBJECT = 905, - ORIENT_TO_POSITION = 906, - ORIENT_TO_ANGLE = 907, - BOUNCER_ACTIVE_STATUS = 942, - UN_USE_BBB_MODEL = 999, - BBB_LOAD_ITEM_REQUEST = 1000, - BBB_SAVE_REQUEST = 1001, - BBB_SAVE_RESPONSE = 1006, - NOTIFY_CLIENT_OBJECT = 1042, - DISPLAY_ZONE_SUMMARY = 1043, - ZONE_SUMMARY_DISMISSED = 1044, - ACTIVITY_STATE_CHANGE_REQUEST = 1053, - MODIFY_PLAYER_ZONE_STATISTIC = 1046, - START_BUILDING_WITH_ITEM = 1057, - START_ARRANGING_WITH_ITEM = 1061, - FINISH_ARRANGING_WITH_ITEM = 1062, - DONE_ARRANGING_WITH_ITEM = 1063, - SET_BUILD_MODE = 1068, - BUILD_MODE_SET = 1069, - SET_BUILD_MODE_CONFIRMED = 1073, - NOTIFY_CLIENT_FAILED_PRECONDITION = 1081, - MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1093, - MODULAR_BUILD_BEGIN = 1094, - MODULAR_BUILD_END = 1095, - MODULAR_BUILD_MOVE_AND_EQUIP = 1096, - MODULAR_BUILD_FINISH = 1097, - REPORT_BUG = 1198, - MISSION_DIALOGUE_CANCELLED = 1129, - ECHO_SYNC_SKILL = 1144, - SYNC_SKILL = 1145, - REQUEST_SERVER_PROJECTILE_IMPACT = 1148, - DO_CLIENT_PROJECTILE_IMPACT = 1151, - MODULAR_BUILD_CONVERT_MODEL = 1155, - SET_PLAYER_ALLOWED_RESPAWN = 1165, - UI_MESSAGE_SERVER_TO_SINGLE_CLIENT = 1184, - UI_MESSAGE_SERVER_TO_ALL_CLIENTS = 1185, - PET_TAMING_TRY_BUILD = 1197, - REQUEST_SMASH_PLAYER = 1202, - FIRE_EVENT_CLIENT_SIDE = 1213, - TOGGLE_GM_INVIS = 1218, - CHANGE_OBJECT_WORLD_STATE = 1223, - VEHICLE_LOCK_INPUT = 1230, - VEHICLE_UNLOCK_INPUT = 1231, - RACING_RESET_PLAYER_TO_LAST_RESET = 1252, + SERVER_TRADE_CANCEL = 883, + SERVER_TRADE_ACCEPT = 884, + GET_TRADE_INFO = 885, + KF_LOADED = 886, + BRICKS_LOADED = 887, + READY_FOR_UPDATES = 888, + SEND_READY_FOR_UPDATES = 889, + SET_LAST_CUSTOM_BUILD = 890, + GET_LAST_CUSTOM_BUILD = 891, + GET_STATUS_EFFECT_BY_ID = 892, + GET_ALL_STATUS_EFFECTS = 893, + CHILD_RENDER_COMPONENT_READY = 894, + NOTIFY_APPEARANCE_CHANGED_MSG = 895, + SET_PHYSICS_MOTION_STATE = 896, + GET_PHYSICS_MOTION_STATE = 897, + ATTACH_GRAYSCALE_EFFECT = 898, + ATTACH_FADE_EFFECT = 899, + ATTACH_CHANGE_RENDER_ENVIRONMENT_EFFECT = 900, + FORCE_MOVEMENT = 901, + CANCEL_FORCE_MOVEMENT = 902, + SET_IGNORE_PROJECTILE_COLLISION = 903, + GET_IGNORE_PROJECTILE_COLLISION = 904, + ORIENT_TO_OBJECT = 905, + ORIENT_TO_POSITION = 906, + ORIENT_TO_ANGLE = 907, + NOTIFY_CLIENT_UGC_MODEL_READY = 909, + NOTIFY_CLIENT_UGC_ICON_READY = 911, + PROPERTY_BUILD_MODE_CHANGED = 912, + PROPERTY_BUILD_MODE_UPDATE = 913, + PROPERTY_DELETION_ACTION = 914, + PROPERTY_MODERATION_STATUS_ACTION = 915, + PROPERTY_MODERATION_STATUS_ACTION_RESPONSE = 916, + PROPERTY_MODERATION_STATUS_UPDATE = 917, + PROPERTY_NEEDS_GM_ATTENTION = 918, + PROPERTY_MODERATION_CHANGED = 919, + INVENTORY_REFRESH_ITEM_DETAILS = 922, + INVENTORY_LOAD_CUSTOM_ICON = 923, + GET_STATUS_EFFECT_BY_TYPE = 924, + RELEASE_CHARGED_SKILL = 925, + PROPERTY_RELOAD_DB = 926, + SET_PLAYER_TARGET = 927, + GET_PLAYER_TARGET = 928, + LOCK_CAMERA_NETWORKED = 929, + MOVE_CAMERA_NETWORKED = 930, + REBUILD_ACTIVATED = 931, + BOUNCE_NOTIFICATION = 932, + REQUEST_CLIENT_BOUNCE = 934, + GET_RECENT_BOUNCED = 935, + SET_RECENT_BOUNCED = 936, + SET_ACTIVE_STATE = 937, + GET_ACTIVE_STATE = 938, + HAS_COMPONENT_TYPE = 939, + GET_COMPONENT_LIST = 940, + RESPONDS_TO_FACTION = 941, + BOUNCER_ACTIVE_STATUS = 942, + HF_ATTRIBUTES_PUSH = 943, + HF_ATTRIBUTES_PULL = 944, + HF_ATTRIBUTES_PATH_DISPLAY = 945, + HF_CONTROLS_PULL = 946, + HF_OBJECT_SELECTED = 947, + HF_PLACEHOLDER_UPDATE = 948, + HF_PLACEHOLDER_TOGGLE = 949, + HF_GET_ASSOCIATED_PATHS = 950, + HF_GETS_WANT_PATH = 951, + GET_RECENT_MOVEMENT_KEYS = 952, + TRACK_RECENT_MOVEMENT_KEYS = 953, + PHYSICS_MOVEMENT_NOTIFICATION_REQUEST = 954, + PHYSICS_MOVEMENT_NOTIFICATION = 955, + MOVE_INVENTORY_SINGLE = 956, + MOVE_INVENTORY_BATCH = 957, + MINI_GAME_SET_PARAMETERS = 958, + MINI_GAME_GET_TEAM_SKILLS = 961, + MINI_GAME_GET_TEAM_SCORE = 963, + MINI_GAME_GET_PLAYER_SCORE = 967, + MINI_GAME_GET_TEAM_COLOR = 972, + MINI_GAME_GET_TEAM_PLAYERS = 975, + MINI_GAME_UPDATE_CLIENT = 976, + MINI_GAME_GET_TEAM = 977, + MINI_GAME_GET_PARAMETERS = 978, + OBJECT_ACTIVATED_CLIENT = 980, + IS_RESURRECTING = 983, + GET_ITEM_OWNER = 984, + GET_STORED_CONFIG_DATA = 985, + SET_STORED_CONFIG_DATA = 986, + ON_PLAYER_RESSURECTED = 988, + PLAYER_RESURRECTION_FINISHED = 989, + TRANSFORM_CHANGELING_BUILD = 990, + RETURN_CHANGELING_BUILD_ID = 991, + SPEND_BRICK_INVENTORY_FOR_LXFML = 992, + BRICK_INVENTORY_FOR_LXFML_SPENT = 993, + REBUILD_BBB_AUTOSAVE_MSG = 995, + SET_BBB_AUTOSAVE = 996, + USE_BBB_INVENTORY = 998, + UN_USE_BBB_MODEL = 999, + BBB_LOAD_ITEM_REQUEST = 1000, + BBB_SAVE_REQUEST = 1001, + BBBLUP_SAVE_REQUEST = 1002, + BBB_GET_METADATA_SOURCE_ITEM = 1003, + BBB_RESET_METADATA_SOURCE_ITEM = 1004, + BBB_SAVE_RESPONSE = 1005, + PLAYER_EXIT = 1006, + SET_PVP_STATUS = 1008, + GET_PVP_STATUS = 1009, + IS_VALID_PVP_TARGET = 1010, + PVP_RENDER_NAME = 1011, + ATTACH_OBJECT = 1012, + DETACH_OBJECT = 1013, + BOUNCE_SUCCEEDED = 1014, + GET_GAME_OBJECT_POINTER = 1015, + PHANTOM_HKX_LOADED = 1016, + DELAY_CREATE_EFFECT = 1017, + CHOICE_BUILD_SELECTION_CONFIRMED = 1018, + NOTIFY_FADE_UP_VIS_COMPLETE = 1019, + ITEM_HAS_NEW_INFO = 1020, + RESET_SECONDARY_ANIMATION = 1021, + GET_PICK_TYPE = 1022, + SET_PICK_TYPE = 1023, + GET_PRIORITY_PICK_LIST_TYPE = 1024, + REQUEST_PICK_TYPE_UPDATE = 1025, + GET_OVERRIDE_PICK_TYPE = 1026, + REQUEST_DISPLAY_OBJECT_INFO = 1027, + REQUEST_SERVER_OBJECT_INFO = 1028, + REQUEST_OBJECT_INFO_AS_XML = 1029, + GET_OBJECT_REPORT_INFO = 1030, + GET_OBJECT_REPORT_WINDOW_CLOSE = 1031, + GET_OBJECT_REPORT_STATUS = 1032, + GET_MISSION_DATA_FOR_OBJECT_REPORT = 1033, + GET_OBJECT_ROLLOVER_INFO = 1034, + PERFORM_ZONE_ANALYSIS = 1035, + UPDATE_HK_VISUAL_IZATION = 1036, + CLEAR_ITEMS_OWNER = 1037, + APPLY_LINEAR_IMPULSE = 1038, + APPLY_ANGULAR_IMPULSE = 1039, + GET_CONTACT_NORMALS = 1040, + IS_WATCHING_FOR_EMOTE = 1041, + NOTIFY_CLIENT_OBJECT = 1042, + DISPLAY_ZONE_SUMMARY = 1043, + ZONE_SUMMARY_DISMISSED = 1044, + GET_PLAYER_ZONE_STATISTIC = 1045, + MODIFY_PLAYER_ZONE_STATISTIC = 1046, + APPLY_EXTERNAL_FORCE = 1049, + GET_APPLIED_EXTERNAL_FORCE = 1050, + ITEM_EQUIPPED = 1052, + ACTIVITY_STATE_CHANGE_REQUEST = 1053, + OVERRIDE_FRICTION = 1054, + ARRANGE_WITH_ITEM = 1055, + CHECK_CAN_BUILD_WITH_ITEM = 1056, + START_BUILDING_WITH_ITEM = 1057, + START_BUILD_SESSION = 1058, + FINISH_BUILD_SESSION = 1059, + DONE_BUILD_SESSION = 1060, + START_ARRANGING_WITH_ITEM = 1061, + FINISH_ARRANGING_WITH_ITEM = 1062, + DONE_ARRANGING_WITH_ITEM = 1063, + START_ARRANGE_MODE = 1064, + ARRANGE_MODE_WITH_ITEM = 1065, + FINISH_ARRANGE_MODE = 1066, + DONE_ARRANGE_MODE = 1067, + SET_BUILD_MODE = 1068, + BUILD_MODE_SET = 1069, + CONFIRM_BUILD_MODE = 1070, + BUILD_MODE_CONFIRMATION = 1071, + BUILD_EXIT_CONFIRMATION = 1072, + SET_BUILD_MODE_CONFIRMED = 1073, + BUILD_MODE_NOTIFICATION = 1074, + BUILD_MODE_NOTIFICATION_REPORT = 1075, + CLIENT_USE_MODULE_ON = 1076, + SET_MODEL_TO_BUILD = 1077, + SPAWN_MODEL_BRICKS = 1078, + CHECK_PRECONDITION = 1079, + CHECK_ALL_PRECONDITIONS = 1080, + NOTIFY_CLIENT_FAILED_PRECONDITION = 1081, + GET_IS_ITEM_EQUIPPED_BY_LOT = 1082, + GET_IS_ITEM_EQUIPPED_BY_ID = 1083, + GET_OBJECT_DIRECTION_VECTORS = 1084, + GET_CASTABLE_SKILLS = 1085, + CHOICEBUILD_COMPLETE = 1086, + GET_MISSION_CHAT = 1087, + GET_MISSION_AUDIO = 1088, + MODULE_EQUIPPED = 1089, + MODULE_DROPPED = 1090, + MODULE_PICKED_UP = 1091, + MODULE_INFO = 1092, + MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1093, + MODULAR_BUILD_BEGIN = 1094, + MODULAR_BUILD_END = 1095, + MODULAR_BUILD_MOVE_AND_EQUIP = 1096, + MODULAR_BUILD_FINISH = 1097, + SET_REGISTRATION_FOR_UI_UPDATE = 1114, + GO_TO_WAYPOINT = 1115, + ARRIVED_AT_DESIRED_WAYPOINT = 1116, + CHECK_WITHIN_BOUNDS = 1117, + ATTACH_TO_BUILD_ASSEMBLY = 1118, + SET_BUILD_ASSEMBLY = 1119, + RESET_BUILD_ASSEMBLY = 1120, + GET_INVENTORY_ITEM_INFO = 1125, + GET_ITEM_DETAILS = 1126, + GET_BUILD_ACTIVATOR = 1127, + GET_MISSION_ANIMATION = 1128, + MISSION_DIALOGUE_CANCELLED = 1129, + MODULE_ASSEMBLY_DB_DATA = 1130, + MODULE_ASSEMBLY_DB_DATA_FOR_CLIENT = 1131, + MODULE_ASSEMBLY_QUERY_DATA = 1132, + MODULE_ASSEMBLY_HKX_LOADED = 1133, + MODULE_ASSEMBLY_NIF_LOADED = 1134, + MODULE_ASSEMBLY_MAIN_NIF_LOADED = 1135, + MODULE_ASSEMBLY_KFM_LOADED = 1136, + GET_PRECONDITION_INFO = 1137, + GET_MODEL_LOT = 1138, + ANIMATION_FINISHED_PRELOADING = 1139, + CHILD_BUILD_ASSEMBLY_COMPLETE = 1140, + CHARACTER_UNSERIALIZED = 1141, + CHARACTER_NEEDS_TRANSITION = 1142, + SET_NEEDS_TRANSITION = 1143, + ECHO_SYNC_SKILL = 1144, + SYNC_SKILL = 1145, + GET_BEHAVIOR_HANDLE = 1146, + ADD_OUTSTANDING_BEHAVIOR = 1147, + REQUEST_SERVER_PROJECTILE_IMPACT = 1148, + OFF_WORLD_IMPACT_REQUEST = 1149, + SERVER_IMPACT_REQUEST = 1150, + DO_CLIENT_PROJECTILE_IMPACT = 1151, + MODULE_ASSEMBLY_PART_INFO = 1152, + GET_BUILD_TYPE = 1153, + CHECK_BUILD_TYPE = 1154, + MODULAR_BUILD_CONVERT_MODEL = 1155, + DO_NPC_SHOWCASE_MODEL_SUBMISSION = 1156, + GET_MISSION_I_DS_LIST = 1157, + SET_SHOWCASE_MISSION_NPC_VALS = 1158, + NOTIFY_SHOWCASE_MISSION_NP_COF_SUCCESS = 1159, + SEND_LUA_NOTIFICATION_REQUEST = 1160, + SEND_LUA_NOTIFICATION_CANCEL = 1161, + ACTIVATOR_TOGGLE = 1162, + MAKE_PHYSICS = 1163, + SET_RESPAWN_GROUP = 1164, + SET_PLAYER_ALLOWED_RESPAWN = 1165, + TOGGLE_SENDING_POSITION_UPDATES = 1166, + TOGGLE_RECEIVING_POSITION_UPDATES = 1167, + GET_ENEMY_PRECONDITIONS = 1168, + START_MODEL_VISUALIZATION = 1169, + PLACE_PROPERTY_MODEL = 1170, + PROPERTY_MODEL_PLACED = 1171, + OPEN_EXHIBIT_REPLACE_MODEL_UI = 1172, + REPLACE_SHOWCASEMODEL = 1173, + CLEAR_UI_HOOK_EXHIBIT_REPLACEMENT = 1174, + ATTACH_FLYTO_SCREEN_POS = 1175, + VEHICLE_GET_DEBUG_INFO = 1176, + VEHICLE_GET_MOVEMENT_INPUT_VALUES = 1177, + ACTIVITY_TIMER_SET = 1178, + ACTIVITY_TIMER_UPDATE = 1179, + ACTIVITY_TIMER_GET = 1180, + ACTIVITY_TIMER_STOP = 1181, + ACTIVITY_TIMER_DONE = 1182, + GET_ATTACK_PRIORITY = 1183, + UI_MESSAGE_SERVER_TO_SINGLE_CLIENT = 1184, + UI_MESSAGE_SERVER_TO_ALL_CLIENTS = 1185, + SET_LOSE_COINS_ON_DEATH = 1186, + LOAD_EFFECTS = 1187, + SET_CUSTOM_BUILD = 1188, + ACTIVITY_TIMER_RESET = 1189, + ACTIVITY_TIMER_STOP_ALL_TIMERS = 1190, + ACTIVITY_TIMER_MODIFY = 1191, + SET_KEYFRAM_TRANSFORM = 1192, + ADD_ACTIVITY_OWNER = 1193, + REMOVE_ACTIVITY_OWNER = 1194, + GET_CURRENT_ACTIVITY_OWNERS = 1195, + TOGGLE_SKILL_DEBUGGING = 1196, + PET_TAMING_TRY_BUILD = 1197, + REPORT_BUG = 1198, + REPORT_OFFENSIVE_MODEL = 1199, + REPORT_OFFENSIVE_PROPERTY = 1200, + GET_ACTIVITY_ID = 1201, + REQUEST_SMASH_PLAYER = 1202, + GET_TIMES_REQUESTED_SMASH = 1203, + RESPONSE_SMASH_PLAYER = 1204, + MODIFY_DAMAGE_ABSORPTION = 1205, + UNCAST_SKILL = 1206, + GET_SHOWCASE_MODEL_READY = 1207, + IS_SKILL_NEEDED = 1208, + GET_COMPONENT_DATA = 1209, + VEHICLE_SET_POWERSLIDE_METHOD = 1210, + SHOWS_NAMETAG = 1211, + FIRE_EVENT_CLIENT_SIDE = 1213, + GET_REQUIRES_NAME_RESUBMISSION = 1216, + SET_REQUIRES_NAME_RESUBMISSION = 1217, + TOGGLE_GM_INVIS = 1218, + GET_GM_INVIS = 1219, + KILLED_PLAYER = 1220, + GET_PICKUP_SKILLS = 1221, + GET_FACTION_SKILL = 1222, + CHANGE_OBJECT_WORLD_STATE = 1223, + GET_OBJECT_WORLD_STATE = 1224, + VISIBILITY_CHANGED = 1225, + MOTION_EFFECT_COMPLETE = 1226, + TOGGLE_FREEZE_MODE = 1227, + SHADER_RENDER_MSG_APPLIED = 1228, + PLAYER_RENAME_REQUEST = 1229, + VEHICLE_LOCK_INPUT = 1230, + VEHICLE_UNLOCK_INPUT = 1231, + SET_AIR_MOVEMENT = 1232, + MOVEMENT_STATE_CHANGED = 1233, + SKILL_MOVEMENT_CANCELLED = 1234, + AIR_MOVEMENT_COMPLETE = 1235, + CANCEL_AIR_MOVEMENT = 1236, + FORCE_MINIFIGURE_TEXTURE_UPDATE = 1237, + RESYNC_EQUIPMENT = 1238, + ADD_COMPONENT_TO_OBJECT = 1239, + VEHICLE_GET_MAX_GAME_SPEED = 1240, + VEHICLE_GET_MAX_GAME_SPEED_WITH_BOOST = 1241, + GET_SPEED_FACTOR = 1242, + FREEZE_INVENTORY = 1243, + ADD_STAT_TRIGGER = 1244, + ADD_STAT_TRIGGER_CHILD = 1245, + CHECK_TRIGGERS_AND_FIRE_IF_NEEDED = 1246, + STAT_EVENT_TRIGGERED = 1247, + GET_CURRENT_SPEED = 1248, + RACING_PLAYER_RANK_CHANGED = 1249, + RACING_PLAYER_WRONG_WAY_STATUS_CHANGED = 1250, + RACING_PLAYER_CROSSED_FINISH_LINE = 1251, + RACING_RESET_PLAYER_TO_LAST_RESET = 1252, RACING_SERVER_SET_PLAYER_LAP_AND_PLANE = 1253, - RACING_SET_PLAYER_RESET_INFO = 1254, - RACING_PLAYER_INFO_RESET_FINISHED = 1255, - LOCK_NODE_ROTATION = 1260, - VEHICLE_SET_WHEEL_LOCK_STATE = 1273, - NOTIFY_VEHICLE_OF_RACING_OBJECT = 1276, - SET_NAME_BILLBOARD_STATE = 1284, - PLAYER_REACHED_RESPAWN_CHECKPOINT = 1296, - HANDLE_UGC_EQUIP_POST_DELETE_BASED_ON_EDIT_MODE = 1300, - HANDLE_UGC_EQUIP_PRE_CREATE_BASED_ON_EDIT_MODE = 1301, - PROPERTY_CONTENTS_FROM_CLIENT = 1305, - GET_MODELS_ON_PROPERTY = 1306, - MATCH_REQUEST = 1308, - MATCH_RESPONSE = 1309, - MATCH_UPDATE = 1310, - MODULE_ASSEMBLY_DB_DATA_FOR_CLIENT = 1131, - MODULE_ASSEMBLY_QUERY_DATA = 1132, - SHOW_BILLBOARD_INTERACT_ICON = 1337, - CHANGE_IDLE_FLAGS = 1338, - VEHICLE_ADD_PASSIVE_BOOST_ACTION = 1340, - VEHICLE_REMOVE_PASSIVE_BOOST_ACTION = 1341, - VEHICLE_NOTIFY_SERVER_ADD_PASSIVE_BOOST_ACTION = 1342, - VEHICLE_NOTIFY_SERVER_REMOVE_PASSIVE_BOOST_ACTION = 1343, - VEHICLE_ADD_SLOWDOWN_ACTION = 1344, - VEHICLE_REMOVE_SLOWDOWN_ACTION = 1345, - VEHICLE_NOTIFY_SERVER_ADD_SLOWDOWN_ACTION = 1346, - VEHICLE_NOTIFY_SERVER_REMOVE_SLOWDOWN_ACTION = 1347, - BUYBACK_FROM_VENDOR = 1350, - SET_PROPERTY_ACCESS = 1366, + RACING_SET_PLAYER_RESET_INFO = 1254, + RACING_PLAYER_INFO_RESET_FINISHED = 1255, + RACING_PLAYER_OUT_OF_TRACK_BOUNDS = 1256, + RACING_SYNC_INFO = 1257, + RACING_PLAYER_KEEP_ALIVE = 1258, + RACING_SERVER_KEEP_ALIVE = 1259, + LOCK_NODE_ROTATION = 1260, + GET_PHYSICS_COLLIDABLE = 1261, + SET_PHYSICS_COLOR_FOR_DEBUG = 1262, + GET_PHYSICS_COLOR_FOR_DEBUG = 1263, + SET_PHYSICS_TEXT_AND_STATE_FOR_DEBUG = 1264, + REQUEST_INFO_FOR_PHYSICS_DEBUGGER = 1265, + GET_COLLIDABLE_AT_ADDRESS = 1266, + REQUEST_SERVER_GET_COLLIDABLE_REPORT = 1267, + COLLISION_POINT_ADDED = 1268, + COLLISION_POINT_REMOVED = 1269, + SET_ATTACHED = 1270, + SET_DESTROYABLE_MODEL_BRICKS = 1271, + VEHICLE_SET_POWERSLIDE_LOCK_WHEELS = 1272, + VEHICLE_SET_WHEEL_LOCK_STATE = 1273, + SHOW_HEALTH_BAR = 1274, + GET_SHOWS_HEALTH_BAR = 1275, + NOTIFY_VEHICLE_OF_RACING_OBJECT = 1276, + ENABLE_CLIENT_EQUIP_MODE = 1278, + CLIENT_EQUIP_MODE_WAS_CHANGED = 1279, + VEHICLE_GET_SPAWN_HEIGHT = 1281, + SET_NAME_BILLBOARD_STATE = 1284, + CHECK_TARGETING_REQUIREMENTS = 1285, + VEHICLE_CAN_WRECK = 1286, + ATTACH_RENDER_EFFECT = 1287, + DETACH_RENDER_EFFECT = 1288, + IS_PET_USING_ABILITY = 1289, + SET_BLOCKING = 1290, + GET_BLOCKING = 1291, + UPDATE_BLOCKING = 1292, + CHECK_DAMAGE_RESULTS = 1293, + GET_OBJECT_IS_IN_RENDER_PIPE = 1294, + ATTACH_MOTION_FX_ARC = 1295, + PLAYER_REACHED_RESPAWN_CHECKPOINT = 1296, + GET_LAST_RESPAWN_CHECKPOINT = 1297, + GET_VEHICLE_DEBUG_COLLISIONS = 1298, + VISITING_PROPERTY = 1299, + HANDLE_UGC_POST_DELETE_BASED_ON_EDIT_MODE = 1300, + HANDLE_UGC_POST_CREATE_BASED_ON_EDIT_MODE = 1301, + WORLD_CHECK_RESPONSE = 1302, + ADD_DAMAGE_REDUCTION = 1303, + REMOVE_DAMAGE_REDUCTION = 1304, + PROPERTY_CONTENTS_FROM_CLIENT = 1305, + GET_MODELS_ON_PROPERTY = 1306, + IS_SHOWCASE_DISPLAY_PEDESTAL = 1307, + MATCH_REQUEST = 1308, + MATCH_RESPONSE = 1309, + MATCH_UPDATE = 1310, + IS_DEFAULT_SKILL_ACTIVE = 1311, + PROPERTY_EDITOR_CARRY = 1312, + GET_LOOT_OWNER_ID = 1313, + GET_ENEMY_LOOT_TAG = 1314, + GET_NUM_SPAWNED_BRICKS = 1315, + SET_ITEM_EQUIP_TRANSFORM = 1316, + GET_ITEM_EQUIP_TRANSFORM = 1317, + GET_PROPERTY_BUDGET_INFO = 1318, + CHATBOX_IS_INIT = 1319, + GET_SPAWNED_I_DS = 1320, + GET_IMMUNITY = 1321, + GET_GM_IMMUNITY = 1322, + PROCESS_REMOTE_SLASH_COMMAND = 1323, + IS_FRIEND_MSG = 1324, + RACING_PLAYER_EVENT = 1325, + GET_PROPERTY_EDIT_VALID = 1326, + REFRESH_RENDER_ASSET = 1327, + VEHICLE_APPLY_STAT_CHANGE = 1328, + ZONE_LOADED_INFO = 1329, + B3_INTERFACE_ACTION = 1330, + RACING_STAT_MODIFIERS_FROM_CLIENT = 1332, + GET_RACING_STAT_MODIFIERS = 1333, + SET_RACING_STAT_MODIFIERS = 1334, + GET_RACING_LICENSE_LEVEL = 1335, + ADD_EQUIP_CAST = 1336, + SHOW_BILLBOARD_INTERACT_ICON = 1337, + CHANGE_IDLE_FLAGS = 1338, + GET_ANIMATION_FLAG = 1339, + VEHICLE_ADD_PASSIVE_BOOST_ACTION = 1340, + VEHICLE_REMOVE_PASSIVE_BOOST_ACTION = 1341, + NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION = 1342, + NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION = 1343, + VEHICLE_ADD_SLOWDOWN_ACTION = 1344, + VEHICLE_REMOVE_SLOWDOWN_ACTION = 1345, + NOTIFY_SERVER_VEHICLE_ADD_SLOWDOWN_ACTION = 1346, + NOTIFY_SERVER_VEHICLE_REMOVE_SLOWDOWN_ACTION = 1347, + FORCE_UPDATE_ANIMATIONS = 1348, + MATCH_GET_DATA_FOR_PLAYER = 1349, + BUYBACK_FROM_VENDOR = 1350, + SET_INVENTORY_FILTER = 1351, + GET_INVENTORY_FILTER = 1352, + GET_INVENTORY_GROUPS = 1353, + GET_INVENTORY_GROUP = 1354, + UPDATE_INVENTORY_GROUP = 1355, + UPDATE_INVENTORY_UI = 1356, + UPDATE_INVENTORY_GROUP_CONTENTS = 1357, + CAN_REMOVE_ITEM_FROM_INVENTORY = 1362, + DRIVE_THIS_CAR = 1363, + VEHICLE_CAN_ADD_ACTIVE_BOOST = 1364, + VEHICLE_ADD_ACTIVE_BOOST = 1365, + SET_PROPERTY_ACCESS = 1366, ZONE_PROPERTY_MODEL_PLACED = 1369, - ZONE_PROPERTY_MODEL_ROTATED = 1370, - ZONE_PROPERTY_MODEL_REMOVED_WHILE_EQUIPPED = 1371, - ZONE_PROPERTY_MODEL_EQUIPPED = 1372, + ZONE_PROPERTY_MODEL_ROTATED = 1370, + ZONE_PROPERTY_MODEL_REMOVED_WHILE_EQUIPPED = 1371, + ZONE_PROPERTY_MODEL_EQUIPPED = 1372, ZONE_PROPERTY_MODEL_PICKED_UP = 1373, ZONE_PROPERTY_MODEL_REMOVED = 1374, - NOTIFY_RACING_CLIENT = 1390, - RACING_PLAYER_HACK_CAR = 1391, - RACING_PLAYER_LOADED = 1392, - RACING_CLIENT_READY = 1393, - UPDATE_CHAT_MODE = 1395, - VEHICLE_NOTIFY_FINISHED_RACE = 1396, - SET_CONSUMABLE_ITEM = 1409, - SET_STATUS_IMMUNITY = 1435, - SET_PET_NAME_MODERATED = 1448, - MODIFY_LEGO_SCORE = 1459, - RESTORE_TO_POST_LOAD_STATS = 1468, - SET_RAIL_MOVEMENT = 1471, - START_RAIL_MOVEMENT = 1472, - CANCEL_RAIL_MOVEMENT = 1474, - CLIENT_RAIL_MOVEMENT_READY = 1476, - PLAYER_RAIL_ARRIVED_NOTIFICATION = 1477, - UPDATE_PLAYER_STATISTIC = 1481, - MODULAR_ASSEMBLY_NIF_COMPLETED = 1498, - NOTIFY_NOT_ENOUGH_INV_SPACE = 1516, - TEAM_SET_LEADER = 1557, - TEAM_INVITE_CONFIRM = 1558, - TEAM_GET_STATUS_RESPONSE = 1559, - TEAM_ADD_PLAYER = 1562, - TEAM_REMOVE_PLAYER = 1563, - START_CELEBRATION_EFFECT = 1618, - ADD_BUFF = 1647, - SERVER_DONE_LOADING_ALL_OBJECTS = 1642, - PLACE_PROPERTY_MODEL = 1170, - VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER = 1606, - ADD_RUN_SPEED_MODIFIER = 1505, - HANDLE_HOT_PROPERTY_DATA = 1511, - SEND_HOT_PROPERTY_DATA = 1510, - REMOVE_RUN_SPEED_MODIFIER = 1506, - UPDATE_PROPERTY_PERFORMANCE_COST = 1547, - PROPERTY_ENTRANCE_BEGIN = 1553, - SET_RESURRECT_RESTORE_VALUES = 1591, - VEHICLE_STOP_BOOST = 1617, - REMOVE_BUFF = 1648, - REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, - RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, - PLAYER_SET_CAMERA_CYCLING_MODE = 1676, - SET_MOUNT_INVENTORY_ID = 1726, - NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734, - NOTIFY_LEVEL_REWARDS = 1735, - DISMOUNT_COMPLETE = 1756, - MARK_INVENTORY_ITEM_AS_ACTIVE = 1767, - END + GET_VERSIONING_INFO = 1381, + OPEN_UG_BEHAVIOR_UI = 1382, + VEHICLE_NOTIFY_HIT_SMASHABLE = 1383, + GET_TETHER_RADIUS = 1384, + VEHICLE_NOTIFY_HIT_EXPLODER = 1385, + CHECK_NEAREST_ROCKET_LAUNCH_PRE_CONDITIONS = 1386, + REQUEST_NEAREST_ROCKET_LAUNCH_PRE_CONDITIONS = 1387, + CONFIGURE_RACING_CONTROL_CLIENT = 1389, + NOTIFY_RACING_CLIENT = 1390, + RACING_PLAYER_HACK_CAR = 1391, + RACING_PLAYER_LOADED = 1392, + RACING_CLIENT_READY = 1393, + POSSESSION_FINISHED_ATTACH = 1394, + UPDATE_CHAT_MODE = 1395, + VEHICLE_NOTIFY_FINISHED_RACE = 1396, + EQUIPPED_ITEM_STARTUP = 1397, + FACTION_TRIGGER_ITEM_EQUIPPED = 1400, + FACTION_TRIGGER_ITEM_UNEQUIPPED = 1401, + TOGGLE_PROPERTY_BEHAVIORS = 1402, + GET_UG_OBJECT_INFO = 1405, + RESET_PROPERTY_BEHAVIORS = 1406, + IS_PROPERTY_MODEL_RESET = 1407, + SET_UG_OBJECT_NAME_AND_DESCRIPTION = 1408, + SET_CONSUMABLE_ITEM = 1409, + VEHICLE_GET_CURRENT_LAP = 1410, + GET_UGID = 1411, + SET_UGID = 1412, + UGID_CHANGED = 1413, + RACING_GET_CURRENT_LAP_FOR_PLAYER = 1414, + SUB_ITEM_UN_EQUIPPED = 1415, + SET_CUSTOM_DROP_SHADOW_TEXTURE = 1416, + GET_PLAYER_KIT_FACTION = 1418, + USED_INFORMATION_PLAQUE = 1419, + RACING_ENABLE_WRONG_WAY_RESET = 1420, + RACING_TOGGLE_RUBBER_BANDING = 1421, + GET_RACING_CONTROL_DEBUG_INFO = 1422, + SET_PROPERTY_BOUNDS_VISIBILITY = 1423, + SET_PROPERTY_VENDOR_VISIBILITY = 1424, + SET_EQUIP_STATE = 1425, + NOTIFY_COMBAT_AI_STATE_CHANGE = 1426, + SET_PROPERTY_MODEL_INTERACTIVE = 1430, + SERVER_STATE_NOTIFY = 1431, + GET_SERVER_STATE = 1432, + GET_ICON_FOR_PROXIMITY = 1433, + GET_LEGO_CLUB_MEMBERSHIP_STATUS = 1434, + SET_STATUS_IMMUNITY = 1435, + GET_STATUS_IMMUNITY = 1436, + TEAM_IS_MEMBER = 1437, + ACTIVATE_BRICK_MODE = 1438, + GET_BUILD_OBJECT_ID = 1439, + SET_ANIMATION_ENABLED = 1444, + PAUSE_COOLDOWNS = 1446, + FORCE_UPDATE_RENDER_NODE = 1447, + SET_PET_NAME_MODERATED = 1448, + TOGGLE_STRAFE_MODE = 1449, + SET_SCHEME_SPEED_SCALE = 1450, + CANCEL_SKILL_CAST = 1451, + CHECK_PLAYER_ASSEMBLY_FOR_UNIQUE_MODULE_BY_LOT = 1454, + MODULE_ASSEMBLY_DB_DATA_TO_LUA = 1455, + IS_ALLY = 1458, + MODIFY_LEGO_SCORE = 1459, + GET_LEGO_SCORE = 1460, + GET_PLAYER_LEVEL = 1461, + NOTIFY_LEGO_SCORE_UPDATE = 1462, + SET_LEGO_SCORE = 1463, + UPDATE_BEHAVIOR_EXECUTION_DETAILS = 1466, + RESTORE_TO_POST_LOAD_STATS = 1468, + PICKUP_OBJECT_ERROR = 1469, + CHECK_AND_SHOW_INVENTORY_FULL_TIP = 1470, + SET_RAIL_MOVEMENT = 1471, + START_RAIL_MOVEMENT = 1472, + SET_UP_VECTOR = 1473, + CANCEL_RAIL_MOVEMENT = 1474, + GET_RAIL_INFO = 1475, + CLIENT_RAIL_MOVEMENT_READY = 1476, + PLAYER_RAIL_ARRIVED_NOTIFICATION = 1477, + NOTIFY_RAIL_ACTOVATOR_STATE_CHANGE = 1478, + REQUEST_RAIL_ACTIVATOR_STATE = 1479, + NOTIFY_REWARD_MAILED = 1480, + UPDATE_PLAYER_STATISTIC = 1481, + IS_IN_COMBAT = 1482, + IS_PRIMITIVE_MODEL_MSG = 1483, + SCALE_PRIMITICE_MODEL_MSG = 1484, + MODIFY_GHOSTING_DISTANCE = 1485, + PRIMITIVE_MODEL_CHANGED_MSG = 1487, + GET_PROPRTY_CLONE_ID = 1488, + REQUEST_LEAVE_PROPERTY = 1489, + REQUERY_PROPERTY_MODELS = 1491, + GET_BEHAVIOR_COUNT = 1492, + UPDATE_BEHAVIOR_CONTROLS = 1493, + MODULE_ASSEMBLY_LXFML_LOADED = 1494, + REQUEST_ASSEMBLED_LXFML = 1495, + ASSEMBLED_LXFML_LOADED = 1496, + GET_REORIENT_UP_VECTOR = 1497, + MODULAR_ASSEMBLY_NIF_COMPLETED = 1498, + CHARACTER_DISCONNECT_BEFORE_CREATE = 1499, + SEND_LAUNCH_TO_PREVIOUS_ZONE_TO_CLIENT = 1500, + ROCKETLAUNCH_REQUEST_DEFAULT_MAP_ID = 1501, + BEGIN_LAUNCH = 1502, + PROCESS_CLAIM_CODES = 1503, + GET_LAST_ZONE_ID = 1504, + ADD_RUN_SPEED_MODIFIER = 1505, + REMOVE_RUN_SPEED_MODIFIER = 1506, + SKILL_EVENT_FIRED = 1507, + SEND_HOT_PROPERTY_DATA = 1510, + GET_HOT_PROPERTY_DATA = 1511, + GET_EQUIPPED_ITEMS_IN_SET = 1512, + IS_ITEM_IN_SET = 1513, + GET_INVENTORY_TYPE_FOR_LOT = 1514, + GET_BANK_TYPE_FOR_LOT = 1515, + NOTIFY_NOT_ENOUGH_INV_SPACE = 1516, + IMPORT_MODEL_TO_BBB = 1517, + SEARCH_NEARBY_OBJECTS = 1518, + SEARCH_NEARBY_OBJECTS_REQUEST_BY_LOT = 1519, + REQUEST_OBJECT_POSITION_BY_ID = 1520, + SEARCH_NEARBY_OBJECTS_REQUEST_BY_COMPONENT = 1521, + SEARCH_NEARBY_OBJECTS_RESPONSE = 1522, + BROADCAST_NON_STANDARD_COLLISIONS = 1523, + GET_REGISTERED_NON_STANDARD_COLLISION_GROUP = 1524, + BROADCAST_CRUSHED_NOTIFICATIONS = 1525, + GET_REGISTERED_CRUSHED_COLLISION_GROUPS = 1526, + IS_BEING_CRUSHED = 1527, + GET_SUPPORTING_OBJECT = 1528, + TREAT_RIGID_BODY_COLLSIONS_AS_FIXED = 1529, + BROADCAST_TELEPORTED_WITHIN_NOTIFICATION = 1530, + GET_REGISTERED_TELEPORTED_WITHIN_OBJECT_GROUP = 1531, + GET_INTERPENTRATING_INFORMATION = 1532, + OBJECT_TELEPORTED_WITHIN = 1533, + SET_PHYSICS_SOLVER_PROPERTIES = 1534, + HAS_BEHAVIORS = 1535, + PLAY_BEHAVIOR_SOUND = 1536, + GET_PLAYER_BEHAVIOR_TIER = 1537, + GET_EMOTE_ANIMATION_TIME = 1538, + GET_CHARACTER_STAT_TRACKING = 1539, + PLAYER_INVENTORY_READY = 1540, + SET_PRECONDITIONS = 1541, + DETACH_SHADOW = 1542, + GET_LOOT_INFO = 1543, + GET_PLAYERS_ON_PROPERTY = 1544, + PROPERTY_SPAWN_BY_BEHAVIOR = 1545, + NOTIFY_PROPERTY_OF_EDIT_MODE = 1546, + UPDATE_PROPERTY_PERFORMANCE_COST = 1547, + GET_PROPERTY_PERFORMANCE_COST = 1548, + GET_INVENTORY_ITEM_WITH_SUBKEY = 1549, + DISPLAY_PROPERTY_SUMMARY_SCREEN = 1550, + VALIDATE_BBB_MODEL = 1551, + BBB_MODEL_VALIDATION = 1552, + PROPERTY_ENTRANCE_BEGIN = 1553, + CHECK_LIST_OF_PRECONDITIONS_FROM_LUA = 1554, + GET_PROPERTYIN_ZONE = 1555, + GET_ZONE_ID_FROM_MULTI_ZONE_ENTRANCE = 1556, + TEAM_SET_LEADER = 1557, + TEAM_INVITE_CONFIRM = 1558, + TEAM_GET_STATUS_RESPONSE = 1559, + MINI_GAME_ENABLE_LOCAL_TEAMS = 1560, + TEAM_INVITE_FINAL_RESPONSE = 1561, + TEAM_ADD_PLAYER = 1562, + TEAM_REMOVE_PLAYER = 1563, + TEAM_CREATE_LOCAL = 1564, + TEAM_GET_LOOT = 1565, + TEAM_SET_LOOT = 1566, + SET_ZERO_IMPULSE_AGAINST_COLLISION_GROUPS = 1567, + SET_CENTER_OF_MASS_TO_PHYSICAL_CENTER = 1568, + SET_INERTIA_INVERSE = 1569, + ADD_REMOVE_CLIMBING_LISTENER = 1570, + GET_INVENTORYITEM_DETAILS = 1571, + PERFORM_CLIENT_SIDE_DEATH = 1572, + LEGO_CLUB_ACCESS_RESULT = 1573, + VEHICLE_GET_IS_REVERSING = 1574, + CHECK_CLAIM_CODE = 1575, + GET_HOLIDAY_EVENT = 1576, + SET_EMOTES_ENABLED = 1577, + GET_EMOTES_ENABLED = 1578, + FREEZE_ANIMATION = 1579, + LOCALIZED_ANNOUNCEMENT_SERVER_TO_SINGLE_CLIENT = 1580, + ANCHOR_FX_NODE = 1581, + WS_GET_FRIEND_LIST_MESSAGE = 1582, + WS_ADD_FRIEND_RESPONSE = 1583, + WS_REMOVE_FRIEND_REPSONSE = 1584, + WS_UPDATE_FRIEND_STATUS = 1585, + WS_UPDATE_FRIEND_NAME = 1586, + IS_BEST_FRIEND = 1587, + TEAM_NOTIFY_UPDATE_MISSION_TASK = 1588, + VEHICLE_ADD_SLIPPERY_ACTION = 1589, + VEHICLE_REMOVE_SLIPPERY_ACTION = 1590, + SET_RESURRECT_RESTORE_VALUES = 1591, + GET_MASS = 1592, + SET_PROPERTY_MODERATION_STATUS = 1593, + UPDATE_PROPERTY_MODEL_DEFAULTS = 1594, + UPDATE_PROPERTYMODEL_COUNT = 1595, + GET_PROPERTY_MODEL_COUNT = 1596, + IS_PLAYER_LOADED = 1597, + ATTACH_RENDER_EFFECT_FROM_LUA = 1598, + DETACH_RENDER_EFFECT_FROM_LUA = 1599, + TEAM_IS_LOCAL = 1600, + CREATE_CAMERA_PARTICLES = 1602, + SET_SMASHABLE_GRAVITY_FACTOR = 1603, + VEHICLE_SET_SURFACE_TYPE_OVERRIDE = 1604, + VEHICLE_NOTIFY_HIT_IMAGINATION = 1605, + VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER = 1606, + GET_SPAWNED_OBJECT_SPAWNER_INFO = 1607, + SAVE_PROPERTY = 1608, + SET_PROPERTY_DIRTY = 1609, + GET_PROPERTY_DIRTY = 1610, + GET_MODEL_LIST_FROM_PLAQUE = 1611, + GET_ORIGINAL_POSITION_AND_ROTATION = 1612, + VEHICLE_SET_MASS_FOR_COLLISION = 1613, + GET_INVENTORY_GROUP_COUNT = 1614, + GET_LATEST_CHAT_CHANNEL_USED = 1615, + SET_SUGGEST_LIST_LANGUAGE = 1616, + VEHICLE_STOP_BOOST = 1617, + START_CELEBRATION_EFFECT = 1618, + LOCK_PLAYER = 1619, + VEHICLE_IS_INPUT_LOCKED = 1620, + GET_MULTI_NODE = 1621, + RENEW_PROPERTY = 1622, + RENEW_PROPERTY_RESULT = 1623, + CHARGE_ACTIVITY_COST = 1624, + CAN_RECEIVE_LOOT = 1625, + JOIN_PLAYER_FACTION = 1626, + SET_PROXIMITY_UPDATE_RATE = 1627, + BBB_MODELS_TO_SAVE = 1628, + BELONGS_TO_FACTION = 1629, + MODIFY_FACTION = 1630, + FACTION_UPDATE = 1631, + CELEBRATION_COMPLETED = 1632, + PLAY_PRIMARY_MODULE_SOUNDS = 1633, + STOP_PRIMARY_MODULE_SOUNDS = 1634, + REQUEST_TEAM_PLAYER_UI_UPDATE = 1635, + SET_LOCAL_TEAM = 1636, + TEAM_GET_WORLD_MEMBERS_IN_RADIUS = 1637, + GET_PARENTAL_LEVEL = 1638, + GET_OBJECTS_MESSAGE_HANDLERS = 1639, + PROPERTY_FEATURED = 1640, + PROPERTY_NOTIFY_MODEL_SPAWNED = 1641, + SERVER_DONE_LOADING_ALL_OBJECTS = 1642, + GET_DONATION_TOTAL = 1643, + UPDATE_DONATION_VALUES = 1644, + DELAYED_DELETE_DROP_EFFECT_BRICK = 1645, + SET_CAMERA_UNLOCK_ROTATION_STATE = 1646, + ADD_BUFF = 1647, + REMOVE_BUFF = 1648, + CHECK_FOR_BUFF = 1649, + TEAM_MEMBERS_DISOWNS_LOOT = 1650, + GET_WHEEL_TEMPLATE = 1651, + ADD_SKILL_IN_PROGRESS = 1652, + REMOVE_SKILL_IN_PROGRESS = 1653, + SET_OVERHEAD_ICON_OFFSET = 1654, + SET_BILLBOARD_OFFSET = 1655, + SET_CHAT_BUBBLE_OFFSET = 1656, + SET_NO_TEAM_INVITES = 1657, + RESET_MODEL_TO_DEFAULTS = 1658, + IS_PROPERTY_IN_EDIT_MODE = 1659, + GET_OBJECTS_IN_PHYSICS_BOUNDS = 1660, + ENABLE_LU_REMOTE = 1661, + SET_IS_USING_FREE_TRIAL = 1662, + GET_IS_USING_FREE_TRIAL = 1663, + GET_ACCOUNT_FREE_TRIAL_MODE = 1664, + TOGGLE_INVENTORY_ITEM_LOCK = 1665, + REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, + RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, + REMOVE_SUB_COMPONENT = 1668, + TEAM_GET_LOOT_MEMBERS = 1669, + GET_FACTION_TOKEN_TYPE = 1670, + GET_SUBSCRIPTION_PRICING = 1671, + INFORM_AFK = 1672, + OVERHEAD_INDICATOR_CREATED = 1673, + SET_OVERHEAD_INDICATOR_GRID_LOCATION = 1674, + PLAYSTREAM_LOAD_PENDING = 1675, + PLAYER_SET_CAMERA_CYCLING_MODE = 1676, + PLAYER_GET_CAMERA_CYCLING_MODE = 1677, + FORCE_CAMERA_TARGET_CYCLE = 1678, + GET_OBJECT_CONFIG_DATA = 1679, + GET_OBJECT_CONFIG_DATA_NON_CONST = 1680, + SCOPE_CHANGED = 1681, + SET_ALLOW_JUMP_WITHOUT_SUPPORT = 1682, + GET_ALLOW_JUMP_WITHOUT_SUPPORT = 1683, + SET_JUMP_HEIGHT_SCALE = 1684, + GET_JUMP_HEIGHT_SCALE = 1685, + SET_VELOCITY_RESISTANCE = 1686, + GET_VELOCITY_RESISTANCE = 1687, + GATE_RUSH_VEHICLE_HIT_GATE = 1688, + GATE_RUSH_PLAYER_COLLECTED_GATE = 1689, + GATE_RUSH_ADD_GATE = 1690, + GATE_RUSH_REMOVE_GATE = 1691, + NOTIFY_VEHICLE_UPDATED = 1692, + VEHICLE_NOTIFY_HIT_WEAPON_POWERUP = 1693, + VEHICLE_NOTIFY_HIT_WEAPON_POWERUP_SERVER = 1694, + LOCAL_PLAYER_TARGETED = 1696, + SKILL_COUNT_CHANGED = 1697, + DO_YAW_ROTATION = 1698, + DO_PITCH_ROTATION = 1699, + DO_ROLL_ROTATION = 1700, + GET_CURRENT_LOOT_MATRIX = 1701, + SEND_MULTI_MISSION_OFFER_UPDATE_I_DS = 1702, + SET_AIR_SPEED_VALUES = 1703, + USE_LAUNCHER = 1704, + START_LAUNCHER = 1705, + STOP_LAUNCHER = 1706, + CAN_USE_JET_PACK = 1707, + JET_PACK_STATE_CHANGED = 1708, + TURN_OFF_JET_PACK = 1709, + ADD_PLAYER_JET_PACK_PAD = 1710, + SET_JET_PACK_WARNING = 1711, + JET_PACK_DISABLED = 1712, + JET_PACK_PAD_ENTERED = 1713, + UPDATE_RENDER_POSSESSION_FLAG = 1714, + POSSESSABLE_GET_ATTACH_OFFSET = 1715, + ATTEMPT_TO_CRAFT_ITEM = 1718, + CRAFT_ATTEMPT_RESPONSE = 1719, + SET_C_SCORE = 1720, + FILL_IN_RENDERER = 1721, + TOGGLE_CRAFTING_WINDOW = 1722, + REMOVE_TEAM_BUFFS = 1724, + REQUEST_FREE_TRIAL_STATUS_REFRESH = 1725, + REMOVE_BUFFS_APPLIED_BY_OBJECT = 1726, + SET_MOUNT_INVENTORY_ID = 1727, + GET_MOUNT_INVENTORY_ID = 1728, + GET_BUILD_CINEMATIC_TIME_REMAINING = 1730, + JET_PACK_FLYING = 1731, + NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734, + NOTIFY_LEVEL_REWARDS = 1735, + CHARACTER_VERSION_CHANGED = 1736, + SET_FREE_TRIAL_RENAME_AVAILABLE = 1737, + SET_PROJECTILE_LAUNCHER_PARAMS = 1738, + RACE_PRECOUNTDOWN_DONE = 1739, + CHECK_INVITE_SPAMMING = 1740, + GET_RESPAWN_VOLUME_INFO = 1741, + INVITE_ACCEPTED = 1742, + TELEPORT_TO_NEAREST_RESPAWN = 1743, + SET_SKILL_CANCEL_ON_MOVE = 1744, + CANCEL_MOVE_SKILL = 1745, + SERVER_CANCEL_MOVE_SKILL = 1746, + CLIENT_CANCEL_MOVE_SKILL = 1747, + END_LAUNCH_SEQUENCE = 1748, + CANCEL_QUEUE = 1749, + UPDATE_PROJECTILE_LAUNCHER_ROTATION = 1750, + GET_CHARACTER_VERSION_INFO = 1751, + GET_CON_INFO = 1753, + GET_SKILLS_FOR_LOT = 1755, + DISMOUNT_COMPLETE = 1756, + MOUNT_FAILURE_RESPONSE = 1757, + CLEAR_BILLBOARD_OFFSET = 1758, + GET_INVENTORY_ITEM_ANIMATION_FLAG = 1759, + SET_JET_PACK_ALLOWED = 1760, + GET_BUILD_TIME_DETAILS = 1761, + USE_SKILL_SET = 1762, + SET_SKILL_SET_POSSESSOR = 1763, + POPULATE_ACTION_BAR = 1764, + GET_COMPONENT_TEMPLATE_ID = 1765, + GET_POSSESSABLE_SKILL_SET = 1766, + MARK_INVENTORY_ITEM_AS_ACTIVE = 1767, + UPDATE_FORGED_ITEM = 1768, + CAN_ITEMS_BE_REFORGED = 1769, + NOTIFY_CLIENT_RAIL_START_FAILED = 1771, + GET_IS_ON_RAIL = 1772 }; #endif //!__EGAMEMESSAGETYPE__H__ diff --git a/dCommon/dEnums/eReplicaComponentType.h b/dCommon/dEnums/eReplicaComponentType.h index 2d24c19e4..a0be9dd45 100644 --- a/dCommon/dEnums/eReplicaComponentType.h +++ b/dCommon/dEnums/eReplicaComponentType.h @@ -101,7 +101,7 @@ enum class eReplicaComponentType : uint32_t { TRADE, USER_CONTROL, IGNORE_LIST, - ROCKET_LAUNCH_LUP, + MULTI_ZONE_ENTRANCE, BUFF_REAL, // the real buff component, should just be name BUFF INTERACTION_MANAGER, DONATION_VENDOR, diff --git a/dDatabase/Tables/CDBehaviorParameterTable.cpp b/dDatabase/Tables/CDBehaviorParameterTable.cpp index edfc3cc3d..708bec4c0 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.cpp +++ b/dDatabase/Tables/CDBehaviorParameterTable.cpp @@ -1,26 +1,30 @@ #include "CDBehaviorParameterTable.h" #include "GeneralUtils.h" +uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) { + uint64_t key = behaviorID; + key <<= 31U; + key |= parameterID; + + return key; +} + void CDBehaviorParameterTable::LoadValuesFromDatabase() { auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); - uint32_t uniqueParameterId = 0; - uint64_t hash = 0; while (!tableData.eof()) { - CDBehaviorParameter entry; - entry.behaviorID = tableData.getIntField("behaviorID", -1); + uint32_t behaviorID = tableData.getIntField("behaviorID", -1); auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", "")); auto parameter = m_ParametersList.find(candidateStringToAdd); + uint32_t parameterId; if (parameter != m_ParametersList.end()) { - entry.parameterID = parameter; + parameterId = parameter->second; } else { - entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first; - uniqueParameterId++; + parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second; } - hash = entry.behaviorID; - hash = (hash << 31U) | entry.parameterID->second; - entry.value = tableData.getFloatField("value", -1.0f); + uint64_t hash = GetKey(behaviorID, parameterId); + float value = tableData.getFloatField("value", -1.0f); - m_Entries.insert(std::make_pair(hash, entry)); + m_Entries.insert(std::make_pair(hash, value)); tableData.nextRow(); } @@ -30,25 +34,21 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() { float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { auto parameterID = this->m_ParametersList.find(name); if (parameterID == this->m_ParametersList.end()) return defaultValue; - - uint64_t hash = behaviorID; - - hash = (hash << 31U) | parameterID->second; + auto hash = GetKey(behaviorID, parameterID->second); // Search for specific parameter - const auto& it = m_Entries.find(hash); - return it != m_Entries.end() ? it->second.value : defaultValue; + auto it = m_Entries.find(hash); + return it != m_Entries.end() ? it->second : defaultValue; } std::map CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { uint64_t hashBase = behaviorID; std::map returnInfo; - uint64_t hash; - for (auto& parameterCandidate : m_ParametersList) { - hash = (hashBase << 31U) | parameterCandidate.second; + for (auto& [parameterString, parameterId] : m_ParametersList) { + uint64_t hash = GetKey(hashBase, parameterId); auto infoCandidate = m_Entries.find(hash); if (infoCandidate != m_Entries.end()) { - returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value)); + returnInfo.insert(std::make_pair(parameterString, infoCandidate->second)); } } return returnInfo; diff --git a/dDatabase/Tables/CDBehaviorParameterTable.h b/dDatabase/Tables/CDBehaviorParameterTable.h index 69928a89f..3daa3aa32 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.h +++ b/dDatabase/Tables/CDBehaviorParameterTable.h @@ -5,15 +5,11 @@ #include #include -struct CDBehaviorParameter { - unsigned int behaviorID; //!< The Behavior ID - std::unordered_map::iterator parameterID; //!< The Parameter ID - float value; //!< The value of the behavior template -}; - class CDBehaviorParameterTable : public CDTable { private: - std::unordered_map m_Entries; + typedef uint64_t BehaviorParameterHash; + typedef float BehaviorParameterValue; + std::unordered_map m_Entries; std::unordered_map m_ParametersList; public: void LoadValuesFromDatabase(); diff --git a/dDatabase/Tables/CDLootMatrixTable.cpp b/dDatabase/Tables/CDLootMatrixTable.cpp index 50c326abb..dd71d08ac 100644 --- a/dDatabase/Tables/CDLootMatrixTable.cpp +++ b/dDatabase/Tables/CDLootMatrixTable.cpp @@ -1,6 +1,21 @@ #include "CDLootMatrixTable.h" void CDLootMatrixTable::LoadValuesFromDatabase() { + + // First, get the size of the table + unsigned int size = 0; + auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM LootMatrix"); + while (!tableSize.eof()) { + size = tableSize.getIntField(0, 0); + + tableSize.nextRow(); + } + + tableSize.finalize(); + + // Reserve the size + this->entries.reserve(size); + // Now get the data auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix"); while (!tableData.eof()) { diff --git a/dDatabase/Tables/CDLootTableTable.cpp b/dDatabase/Tables/CDLootTableTable.cpp index 77c6de26e..e45900adc 100644 --- a/dDatabase/Tables/CDLootTableTable.cpp +++ b/dDatabase/Tables/CDLootTableTable.cpp @@ -1,6 +1,21 @@ #include "CDLootTableTable.h" void CDLootTableTable::LoadValuesFromDatabase() { + + // First, get the size of the table + unsigned int size = 0; + auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM LootTable"); + while (!tableSize.eof()) { + size = tableSize.getIntField(0, 0); + + tableSize.nextRow(); + } + + tableSize.finalize(); + + // Reserve the size + this->entries.reserve(size); + // Now get the data auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable"); while (!tableData.eof()) { diff --git a/dDatabase/Tables/CDVendorComponentTable.cpp b/dDatabase/Tables/CDVendorComponentTable.cpp index d01fdea2f..0f963b045 100644 --- a/dDatabase/Tables/CDVendorComponentTable.cpp +++ b/dDatabase/Tables/CDVendorComponentTable.cpp @@ -21,7 +21,7 @@ void CDVendorComponentTable::LoadValuesFromDatabase() { while (!tableData.eof()) { CDVendorComponent entry; entry.id = tableData.getIntField("id", -1); - entry.buyScalar = tableData.getFloatField("buyScalar", -1.0f); + entry.buyScalar = tableData.getFloatField("buyScalar", 0.0f); entry.sellScalar = tableData.getFloatField("sellScalar", -1.0f); entry.refreshTimeSeconds = tableData.getFloatField("refreshTimeSeconds", -1.0f); entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index a06bb5723..b3a0a3cc1 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -30,7 +30,7 @@ #include "Component.h" #include "ControllablePhysicsComponent.h" #include "RenderComponent.h" -#include "RocketLaunchLupComponent.h" +#include "MultiZoneEntranceComponent.h" #include "CharacterComponent.h" #include "DestroyableComponent.h" #include "BuffComponent.h" @@ -51,6 +51,7 @@ #include "BuildBorderComponent.h" #include "MovementAIComponent.h" #include "VendorComponent.h" +#include "DonationVendorComponent.h" #include "RocketLaunchpadControlComponent.h" #include "PropertyComponent.h" #include "BaseCombatAIComponent.h" @@ -70,6 +71,7 @@ #include "ShootingGalleryComponent.h" #include "RailActivatorComponent.h" #include "LUPExhibitComponent.h" +#include "RacingSoundTriggerComponent.h" #include "TriggerComponent.h" #include "eGameMasterLevel.h" #include "eReplicaComponentType.h" @@ -317,6 +319,9 @@ void Entity::Initialize() { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) { auto* comp = new SoundTriggerComponent(this); m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp)); + } else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) { + auto* comp = new RacingSoundTriggerComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::RACING_SOUND_TRIGGER, comp)); } //Also check for the collectible id: @@ -447,9 +452,9 @@ void Entity::Initialize() { m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp)); } // if this component exists, then we initialize it. it's value is always 0 - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH_LUP, -1) != -1) { - auto comp = new RocketLaunchLupComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH_LUP, comp)); + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) { + auto comp = new MultiZoneEntranceComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::MULTI_ZONE_ENTRANCE, comp)); } /** @@ -580,6 +585,9 @@ void Entity::Initialize() { if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) { VendorComponent* comp = new VendorComponent(this); m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp)); + } else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) { + DonationVendorComponent* comp = new DonationVendorComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::DONATION_VENDOR, comp)); } if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) { @@ -1014,57 +1022,60 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType */ bool destroyableSerialized = false; - bool bIsInitialUpdate = false; - if (packetType == eReplicaPacketType::CONSTRUCTION) bIsInitialUpdate = true; - unsigned int flags = 0; + bool bIsInitialUpdate = packetType == eReplicaPacketType::CONSTRUCTION; PossessableComponent* possessableComponent; if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) { - possessableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + possessableComponent->Serialize(outBitStream, bIsInitialUpdate); } ModuleAssemblyComponent* moduleAssemblyComponent; if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) { - moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate); } ControllablePhysicsComponent* controllablePhysicsComponent; if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) { - controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate); } SimplePhysicsComponent* simplePhysicsComponent; if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) { - simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate); } RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics; if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) { - rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate, flags); + rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate); } VehiclePhysicsComponent* vehiclePhysicsComponent; if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) { - vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate); } PhantomPhysicsComponent* phantomPhysicsComponent; if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) { - phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate); } SoundTriggerComponent* soundTriggerComponent; if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) { - soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate); + } + + RacingSoundTriggerComponent* racingSoundTriggerComponent; + if (TryGetComponent(eReplicaComponentType::RACING_SOUND_TRIGGER, racingSoundTriggerComponent)) { + racingSoundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate); } BuffComponent* buffComponent; if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) { - buffComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + buffComponent->Serialize(outBitStream, bIsInitialUpdate); DestroyableComponent* destroyableComponent; if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + destroyableComponent->Serialize(outBitStream, bIsInitialUpdate); } destroyableSerialized = true; } @@ -1072,7 +1083,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType if (HasComponent(eReplicaComponentType::COLLECTIBLE)) { DestroyableComponent* destroyableComponent; if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + destroyableComponent->Serialize(outBitStream, bIsInitialUpdate); } destroyableSerialized = true; outBitStream->Write(m_CollectibleID); // Collectable component @@ -1080,7 +1091,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType PetComponent* petComponent; if (TryGetComponent(eReplicaComponentType::PET, petComponent)) { - petComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + petComponent->Serialize(outBitStream, bIsInitialUpdate); } CharacterComponent* characterComponent; @@ -1088,7 +1099,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType PossessorComponent* possessorComponent; if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) { - possessorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + possessorComponent->Serialize(outBitStream, bIsInitialUpdate); } else { // Should never happen, but just to be safe outBitStream->Write0(); @@ -1096,7 +1107,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType LevelProgressionComponent* levelProgressionComponent; if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) { - levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate); } else { // Should never happen, but just to be safe outBitStream->Write0(); @@ -1104,13 +1115,13 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType PlayerForcedMovementComponent* playerForcedMovementComponent; if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) { - playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate); } else { // Should never happen, but just to be safe outBitStream->Write0(); } - characterComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + characterComponent->Serialize(outBitStream, bIsInitialUpdate); } if (HasComponent(eReplicaComponentType::ITEM)) { @@ -1119,88 +1130,93 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType InventoryComponent* inventoryComponent; if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) { - inventoryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + inventoryComponent->Serialize(outBitStream, bIsInitialUpdate); } ScriptComponent* scriptComponent; if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) { - scriptComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + scriptComponent->Serialize(outBitStream, bIsInitialUpdate); } SkillComponent* skillComponent; if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) { - skillComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + skillComponent->Serialize(outBitStream, bIsInitialUpdate); } BaseCombatAIComponent* baseCombatAiComponent; if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) { - baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate); } RebuildComponent* rebuildComponent; if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) { DestroyableComponent* destroyableComponent; if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + destroyableComponent->Serialize(outBitStream, bIsInitialUpdate); } destroyableSerialized = true; - rebuildComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + rebuildComponent->Serialize(outBitStream, bIsInitialUpdate); } MovingPlatformComponent* movingPlatformComponent; if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) { - movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate); } SwitchComponent* switchComponent; if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) { - switchComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + switchComponent->Serialize(outBitStream, bIsInitialUpdate); } VendorComponent* vendorComponent; if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) { - vendorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + vendorComponent->Serialize(outBitStream, bIsInitialUpdate); + } + + DonationVendorComponent* donationVendorComponent; + if (TryGetComponent(eReplicaComponentType::DONATION_VENDOR, donationVendorComponent)) { + donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate); } BouncerComponent* bouncerComponent; if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) { - bouncerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + bouncerComponent->Serialize(outBitStream, bIsInitialUpdate); } ScriptedActivityComponent* scriptedActivityComponent; if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) { - scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate); } ShootingGalleryComponent* shootingGalleryComponent; if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) { - shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate); } RacingControlComponent* racingControlComponent; if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) { - racingControlComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + racingControlComponent->Serialize(outBitStream, bIsInitialUpdate); } LUPExhibitComponent* lupExhibitComponent; if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) { - lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate); } ModelComponent* modelComponent; if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) { - modelComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + modelComponent->Serialize(outBitStream, bIsInitialUpdate); } RenderComponent* renderComponent; if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) { - renderComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + renderComponent->Serialize(outBitStream, bIsInitialUpdate); } if (modelComponent) { DestroyableComponent* destroyableComponent; if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); + destroyableComponent->Serialize(outBitStream, bIsInitialUpdate); destroyableSerialized = true; } } @@ -1215,10 +1231,6 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType outBitStream->Write0(); } -void Entity::ResetFlags() { - // Unused -} - void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { //This function should only ever be called from within Character, meaning doc should always exist when this is called. //Naturally, we don't include any non-player components in this update function. diff --git a/dGame/Entity.h b/dGame/Entity.h index 90f2a34fb..8680653fb 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -85,6 +85,7 @@ class Entity { bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; } bool GetIsGhostingCandidate() const; + void SetIsGhostingCandidate(bool value) { m_IsGhostingCandidate = value; }; int8_t GetObservers() const; @@ -173,7 +174,6 @@ class Entity { void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); - void ResetFlags(); void UpdateXMLDoc(tinyxml2::XMLDocument* doc); void Update(float deltaTime); diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 28b5f5268..699cc2a18 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -583,12 +583,6 @@ bool EntityManager::GetGhostingEnabled() const { return m_GhostingEnabled; } -void EntityManager::ResetFlags() { - for (const auto& e : m_Entities) { - e.second->ResetFlags(); - } -} - void EntityManager::ScheduleForKill(Entity* entity) { // Deactivate switches if they die if (!entity) diff --git a/dGame/EntityManager.h b/dGame/EntityManager.h index 9bea0618a..693a4cc01 100644 --- a/dGame/EntityManager.h +++ b/dGame/EntityManager.h @@ -59,8 +59,6 @@ class EntityManager { Entity* GetGhostCandidate(int32_t id); bool GetGhostingEnabled() const; - void ResetFlags(); - void ScheduleForKill(Entity* entity); void ScheduleForDeletion(LWOOBJID entity); diff --git a/dGame/LeaderboardManager.cpp b/dGame/LeaderboardManager.cpp index a4c6ec1a7..0e64b6b35 100644 --- a/dGame/LeaderboardManager.cpp +++ b/dGame/LeaderboardManager.cpp @@ -131,8 +131,8 @@ void Leaderboard::QueryToLdf(std::unique_ptr& rows) { // Time:1 break; case Type::Donations: - entry.push_back(new LDFData(u"Points", rows->getInt("primaryScore"))); - // Score:1 + entry.push_back(new LDFData(u"Score", rows->getInt("primaryScore"))); + // Score:1 break; case Type::None: // This type is included here simply to resolve a compiler warning on mac about unused enum types @@ -170,32 +170,32 @@ void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t r resultEnd++; // We need everything except 1 column so i'm selecting * from leaderboard const std::string queryBase = - R"QUERY( - WITH leaderboardsRanked AS ( - SELECT leaderboard.*, charinfo.name, - RANK() OVER - ( + R"QUERY( + WITH leaderboardsRanked AS ( + SELECT leaderboard.*, charinfo.name, + RANK() OVER + ( ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC - ) AS ranking - FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id - WHERE game_id = ? %s - ), - myStanding AS ( - SELECT - ranking as myRank - FROM leaderboardsRanked - WHERE id = ? - ), - lowestRanking AS ( - SELECT MAX(ranking) AS lowestRank - FROM leaderboardsRanked - ) - SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking - WHERE leaderboardsRanked.ranking - BETWEEN - LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9) - AND - LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank) + ) AS ranking + FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id + WHERE game_id = ? %s + ), + myStanding AS ( + SELECT + ranking as myRank + FROM leaderboardsRanked + WHERE id = ? + ), + lowestRanking AS ( + SELECT MAX(ranking) AS lowestRank + FROM leaderboardsRanked + ) + SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking + WHERE leaderboardsRanked.ranking + BETWEEN + LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9) + AND + LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank) ORDER BY ranking ASC; )QUERY"; @@ -277,15 +277,15 @@ std::string FormatInsert(const Leaderboard::Type& type, const Score& score, cons if (useUpdate) { insertStatement = R"QUERY( - UPDATE leaderboard - SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f, + UPDATE leaderboard + SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?; )QUERY"; } else { insertStatement = R"QUERY( - INSERT leaderboard SET - primaryScore = %f, secondaryScore = %f, tertiaryScore = %f, + INSERT leaderboard SET + primaryScore = %f, secondaryScore = %f, tertiaryScore = %f, character_id = ?, game_id = ?; )QUERY"; } @@ -300,9 +300,8 @@ std::string FormatInsert(const Leaderboard::Type& type, const Score& score, cons void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) { const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId); - auto* lookup = "SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;"; - std::unique_ptr query(Database::CreatePreppedStmt(lookup)); + std::unique_ptr query(Database::CreatePreppedStmt("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;")); query->setInt(1, playerID); query->setInt(2, activityId); std::unique_ptr myScoreResult(query->executeQuery()); @@ -337,6 +336,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi case Leaderboard::Type::UnusedLeaderboard4: case Leaderboard::Type::Donations: { oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore")); + newScore.SetPrimaryScore(oldScore.GetPrimaryScore() + newScore.GetPrimaryScore()); break; } case Leaderboard::Type::Racing: { @@ -382,7 +382,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi saveStatement->setInt(1, playerID); saveStatement->setInt(2, activityId); saveStatement->execute(); - + // track wins separately if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) { std::unique_ptr winUpdate(Database::CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;")); diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 9e409019c..90e44187c 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -28,6 +28,8 @@ #include "eRenameResponse.h" #include "eConnectionType.h" #include "eChatInternalMessageType.h" +#include "BitStreamUtils.h" +#include "CheatDetection.h" UserManager* UserManager::m_Address = nullptr; @@ -203,40 +205,38 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) { stmt->setUInt(1, u->GetAccountID()); sql::ResultSet* res = stmt->executeQuery(); - if (res->rowsCount() > 0) { - std::vector& chars = u->GetCharacters(); + std::vector& chars = u->GetCharacters(); - for (size_t i = 0; i < chars.size(); ++i) { - if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save - { - delete chars[i]; - - continue; - } + for (size_t i = 0; i < chars.size(); ++i) { + if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save + { + delete chars[i]; - auto* skillComponent = chars[i]->GetEntity()->GetComponent(); + continue; + } - if (skillComponent != nullptr) { - skillComponent->Reset(); - } + auto* skillComponent = chars[i]->GetEntity()->GetComponent(); - Game::entityManager->DestroyEntity(chars[i]->GetEntity()); + if (skillComponent != nullptr) { + skillComponent->Reset(); + } - chars[i]->SaveXMLToDatabase(); + Game::entityManager->DestroyEntity(chars[i]->GetEntity()); - chars[i]->GetEntity()->SetCharacter(nullptr); + chars[i]->SaveXMLToDatabase(); - delete chars[i]; - } + chars[i]->GetEntity()->SetCharacter(nullptr); + + delete chars[i]; + } - chars.clear(); + chars.clear(); - while (res->next()) { - LWOOBJID objID = res->getUInt64(1); - Character* character = new Character(uint32_t(objID), u); - character->SetIsNewLogin(); - chars.push_back(character); - } + while (res->next()) { + LWOOBJID objID = res->getUInt64(1); + Character* character = new Character(uint32_t(objID), u); + character->SetIsNewLogin(); + chars.push_back(character); } delete res; @@ -251,21 +251,21 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) std::string name = PacketUtils::ReadString(8, packet, true); - uint32_t firstNameIndex = PacketUtils::ReadPacketU32(74, packet); - uint32_t middleNameIndex = PacketUtils::ReadPacketU32(78, packet); - uint32_t lastNameIndex = PacketUtils::ReadPacketU32(82, packet); + uint32_t firstNameIndex = PacketUtils::ReadU32(74, packet); + uint32_t middleNameIndex = PacketUtils::ReadU32(78, packet); + uint32_t lastNameIndex = PacketUtils::ReadU32(82, packet); std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex); - uint32_t shirtColor = PacketUtils::ReadPacketU32(95, packet); - uint32_t shirtStyle = PacketUtils::ReadPacketU32(99, packet); - uint32_t pantsColor = PacketUtils::ReadPacketU32(103, packet); - uint32_t hairStyle = PacketUtils::ReadPacketU32(107, packet); - uint32_t hairColor = PacketUtils::ReadPacketU32(111, packet); - uint32_t lh = PacketUtils::ReadPacketU32(115, packet); - uint32_t rh = PacketUtils::ReadPacketU32(119, packet); - uint32_t eyebrows = PacketUtils::ReadPacketU32(123, packet); - uint32_t eyes = PacketUtils::ReadPacketU32(127, packet); - uint32_t mouth = PacketUtils::ReadPacketU32(131, packet); + uint32_t shirtColor = PacketUtils::ReadU32(95, packet); + uint32_t shirtStyle = PacketUtils::ReadU32(99, packet); + uint32_t pantsColor = PacketUtils::ReadU32(103, packet); + uint32_t hairStyle = PacketUtils::ReadU32(107, packet); + uint32_t hairColor = PacketUtils::ReadU32(111, packet); + uint32_t lh = PacketUtils::ReadU32(115, packet); + uint32_t rh = PacketUtils::ReadU32(119, packet); + uint32_t eyebrows = PacketUtils::ReadU32(123, packet); + uint32_t eyes = PacketUtils::ReadU32(127, packet); + uint32_t mouth = PacketUtils::ReadU32(131, packet); LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle); LOT pantsLOT = FindCharPantsID(pantsColor); @@ -387,20 +387,19 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) return; } - LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet); + LWOOBJID objectID = PacketUtils::ReadS64(8, packet); uint32_t charID = static_cast(objectID); Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)", objectID, charID); - //Check if this user has this character: - bool hasCharacter = false; - std::vector& characters = u->GetCharacters(); - for (size_t i = 0; i < characters.size(); ++i) { - if (characters[i]->GetID() == charID) { hasCharacter = true; } - } + bool hasCharacter = CheatDetection::VerifyLwoobjidIsSender( + objectID, + sysAddr, + CheckType::User, + "User %i tried to delete a character that it does not own!", + u->GetAccountID()); if (!hasCharacter) { - Game::logger->Log("UserManager", "User %i tried to delete a character that it does not own!", u->GetAccountID()); WorldPackets::SendCharacterDeleteResponse(sysAddr, false); } else { Game::logger->Log("UserManager", "Deleting character %i", charID); @@ -423,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) stmt->execute(); delete stmt; CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); bitStream.Write(objectID); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } @@ -483,7 +482,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) return; } - LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet); + LWOOBJID objectID = PacketUtils::ReadS64(8, packet); GeneralUtils::ClearBit(objectID, eObjectBits::CHARACTER); GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT); @@ -495,16 +494,24 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet) Character* character = nullptr; //Check if this user has this character: - bool hasCharacter = false; - std::vector& characters = u->GetCharacters(); - for (size_t i = 0; i < characters.size(); ++i) { - if (characters[i]->GetID() == charID) { hasCharacter = true; character = characters[i]; } - } + bool ownsCharacter = CheatDetection::VerifyLwoobjidIsSender( + objectID, + sysAddr, + CheckType::User, + "User %i tried to rename a character that it does not own!", + u->GetAccountID()); + + std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) { + if (c->GetID() == charID) { + character = c; + return true; + } + return false; + }); - if (!hasCharacter || !character) { - Game::logger->Log("UserManager", "User %i tried to rename a character that it does not own!", u->GetAccountID()); + if (!ownsCharacter || !character) { WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR); - } else if (hasCharacter && character) { + } else if (ownsCharacter && character) { if (newName == character->GetName()) { WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE); return; diff --git a/dGame/dBehaviors/BehaviorContext.cpp b/dGame/dBehaviors/BehaviorContext.cpp index 43ba8457e..91276b801 100644 --- a/dGame/dBehaviors/BehaviorContext.cpp +++ b/dGame/dBehaviors/BehaviorContext.cpp @@ -6,7 +6,7 @@ #include "Game.h" #include "dLogger.h" #include "dServer.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include @@ -253,7 +253,7 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime) { // Write message RakNet::BitStream message; - PacketUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); + BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); message.Write(this->originator); echo.Serialize(&message); diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 77f7a4930..3afd3cc94 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -318,7 +318,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { // Speed towards start position if (m_MovementAI != nullptr) { m_MovementAI->SetHaltDistance(0); - m_MovementAI->SetSpeed(m_PursuitSpeed); + m_MovementAI->SetMaxSpeed(m_PursuitSpeed); m_MovementAI->SetDestination(m_StartPosition); } @@ -382,8 +382,6 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { } LWOOBJID BaseCombatAIComponent::FindTarget() { - //const auto reference = m_MovementAI == nullptr ? m_StartPosition : m_MovementAI->ApproximateLocation(); - NiPoint3 reference = m_StartPosition; if (m_MovementAI) reference = m_MovementAI->ApproximateLocation(); @@ -522,7 +520,7 @@ bool BaseCombatAIComponent::IsMech() { } -void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_DirtyStateOrTarget || bIsInitialUpdate); if (m_DirtyStateOrTarget || bIsInitialUpdate) { outBitStream->Write(uint32_t(m_State)); @@ -660,17 +658,17 @@ void BaseCombatAIComponent::Wander() { destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination); } - if (Vector3::DistanceSquared(destination, m_MovementAI->GetCurrentPosition()) < 2 * 2) { + if (Vector3::DistanceSquared(destination, m_MovementAI->GetParent()->GetPosition()) < 2 * 2) { m_MovementAI->Stop(); return; } - m_MovementAI->SetSpeed(m_TetherSpeed); + m_MovementAI->SetMaxSpeed(m_TetherSpeed); m_MovementAI->SetDestination(destination); - m_Timer += (m_MovementAI->GetCurrentPosition().x - destination.x) / m_TetherSpeed; + m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / m_TetherSpeed; } void BaseCombatAIComponent::OnAggro() { @@ -685,21 +683,21 @@ void BaseCombatAIComponent::OnAggro() { m_MovementAI->SetHaltDistance(m_AttackRadius); NiPoint3 targetPos = target->GetPosition(); - NiPoint3 currentPos = m_MovementAI->GetCurrentPosition(); + NiPoint3 currentPos = m_MovementAI->GetParent()->GetPosition(); // If the player's position is within range, attack if (Vector3::DistanceSquared(currentPos, targetPos) <= m_AttackRadius * m_AttackRadius) { m_MovementAI->Stop(); } else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far { - m_MovementAI->SetSpeed(m_PursuitSpeed); + m_MovementAI->SetMaxSpeed(m_PursuitSpeed); m_MovementAI->SetDestination(m_StartPosition); } else //Chase the player's new position { if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return; - m_MovementAI->SetSpeed(m_PursuitSpeed); + m_MovementAI->SetMaxSpeed(m_PursuitSpeed); m_MovementAI->SetDestination(targetPos); @@ -725,7 +723,7 @@ void BaseCombatAIComponent::OnTether() { m_MovementAI->Stop(); } else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far { - m_MovementAI->SetSpeed(m_PursuitSpeed); + m_MovementAI->SetMaxSpeed(m_PursuitSpeed); m_MovementAI->SetDestination(m_StartPosition); @@ -733,7 +731,7 @@ void BaseCombatAIComponent::OnTether() { } else { if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return; - m_MovementAI->SetSpeed(m_PursuitSpeed); + m_MovementAI->SetMaxSpeed(m_PursuitSpeed); m_MovementAI->SetDestination(targetPos); } diff --git a/dGame/dComponents/BaseCombatAIComponent.h b/dGame/dComponents/BaseCombatAIComponent.h index 8bf6140ab..17b74e9cc 100644 --- a/dGame/dComponents/BaseCombatAIComponent.h +++ b/dGame/dComponents/BaseCombatAIComponent.h @@ -53,7 +53,7 @@ class BaseCombatAIComponent : public Component { ~BaseCombatAIComponent() override; void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Get the current behavioral state of the enemy diff --git a/dGame/dComponents/BouncerComponent.cpp b/dGame/dComponents/BouncerComponent.cpp index bbf928dca..a9a278e80 100644 --- a/dGame/dComponents/BouncerComponent.cpp +++ b/dGame/dComponents/BouncerComponent.cpp @@ -22,7 +22,7 @@ BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) { BouncerComponent::~BouncerComponent() { } -void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_PetEnabled); if (m_PetEnabled) { outBitStream->Write(m_PetBouncerEnabled); diff --git a/dGame/dComponents/BouncerComponent.h b/dGame/dComponents/BouncerComponent.h index 15665cc1f..d372f5c74 100644 --- a/dGame/dComponents/BouncerComponent.h +++ b/dGame/dComponents/BouncerComponent.h @@ -17,7 +17,7 @@ class BouncerComponent : public Component { BouncerComponent(Entity* parentEntity); ~BouncerComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; Entity* GetParentEntity() const; diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index 68b5182c7..564804388 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -20,7 +20,7 @@ BuffComponent::BuffComponent(Entity* parent) : Component(parent) { BuffComponent::~BuffComponent() { } -void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (!bIsInitialUpdate) return; if (m_Buffs.empty()) { outBitStream->Write0(); diff --git a/dGame/dComponents/BuffComponent.h b/dGame/dComponents/BuffComponent.h index d91758835..61e7be5d6 100644 --- a/dGame/dComponents/BuffComponent.h +++ b/dGame/dComponents/BuffComponent.h @@ -54,7 +54,7 @@ class BuffComponent : public Component { void UpdateXml(tinyxml2::XMLDocument* doc) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/CMakeLists.txt b/dGame/dComponents/CMakeLists.txt index b396829ab..6c02cf0bf 100644 --- a/dGame/dComponents/CMakeLists.txt +++ b/dGame/dComponents/CMakeLists.txt @@ -6,6 +6,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp" "Component.cpp" "ControllablePhysicsComponent.cpp" "DestroyableComponent.cpp" + "DonationVendorComponent.cpp" "InventoryComponent.cpp" "LevelProgressionComponent.cpp" "LUPExhibitComponent.cpp" @@ -30,7 +31,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp" "RebuildComponent.cpp" "RenderComponent.cpp" "RigidbodyPhantomPhysicsComponent.cpp" - "RocketLaunchLupComponent.cpp" + "MultiZoneEntranceComponent.cpp" "RocketLaunchpadControlComponent.cpp" "ScriptedActivityComponent.cpp" "ShootingGalleryComponent.cpp" diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 10a4e9db0..d56329895 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -70,7 +70,7 @@ bool CharacterComponent::LandingAnimDisabled(int zoneID) { CharacterComponent::~CharacterComponent() { } -void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { outBitStream->Write0(); diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index e5ca6da5d..3a5c033b7 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -70,7 +70,7 @@ class CharacterComponent : public Component { void LoadFromXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument* doc) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Updates the rocket configuration using a LOT string separated by commas @@ -276,6 +276,10 @@ class CharacterComponent : public Component { */ void UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const; + void SetCurrentInteracting(LWOOBJID objectID) {m_CurrentInteracting = objectID;}; + + LWOOBJID GetCurrentInteracting() {return m_CurrentInteracting;}; + /** * Character info regarding this character, including clothing styles, etc. */ @@ -560,6 +564,8 @@ class CharacterComponent : public Component { * ID of the last rocket used */ LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY; + + LWOOBJID m_CurrentInteracting = LWOOBJID_EMPTY; }; #endif // CHARACTERCOMPONENT_H diff --git a/dGame/dComponents/Component.cpp b/dGame/dComponents/Component.cpp index ca018c29c..1136456cf 100644 --- a/dGame/dComponents/Component.cpp +++ b/dGame/dComponents/Component.cpp @@ -28,3 +28,7 @@ void Component::UpdateXml(tinyxml2::XMLDocument* doc) { void Component::LoadFromXml(tinyxml2::XMLDocument* doc) { } + +void Component::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) { + +} diff --git a/dGame/dComponents/Component.h b/dGame/dComponents/Component.h index 9b0df9fdf..c0debb0bc 100644 --- a/dGame/dComponents/Component.h +++ b/dGame/dComponents/Component.h @@ -43,6 +43,8 @@ class Component */ virtual void LoadFromXml(tinyxml2::XMLDocument* doc); + virtual void Serialize(RakNet::BitStream* outBitStream, bool isConstruction); + protected: /** diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index a658ccd72..de27149ef 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -74,7 +74,7 @@ void ControllablePhysicsComponent::Update(float deltaTime) { } -void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { //If this is a creation, then we assume the position is dirty, even when it isn't. //This is because new clients will still need to receive the position. //if (bIsInitialUpdate) m_DirtyPosition = true; @@ -181,12 +181,6 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { m_DirtyPosition = true; } -void ControllablePhysicsComponent::ResetFlags() { - m_DirtyAngularVelocity = false; - m_DirtyPosition = false; - m_DirtyVelocity = false; -} - void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) { tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); if (!character) { diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index 470a7af44..384dfdac0 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -27,9 +27,8 @@ class ControllablePhysicsComponent : public Component { ~ControllablePhysicsComponent() override; void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void LoadFromXml(tinyxml2::XMLDocument* doc) override; - void ResetFlags(); void UpdateXml(tinyxml2::XMLDocument* doc) override; /** diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 6e9b38808..6f245b362 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -119,7 +119,7 @@ void DestroyableComponent::Reinitialize(LOT templateID) { } } -void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) { +void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { outBitStream->Write1(); // always write these on construction outBitStream->Write(m_ImmuneToBasicAttackCount); diff --git a/dGame/dComponents/DestroyableComponent.h b/dGame/dComponents/DestroyableComponent.h index 5e5133b73..ed0910664 100644 --- a/dGame/dComponents/DestroyableComponent.h +++ b/dGame/dComponents/DestroyableComponent.h @@ -24,7 +24,7 @@ class DestroyableComponent : public Component { DestroyableComponent(Entity* parentEntity); ~DestroyableComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void LoadFromXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument* doc) override; diff --git a/dGame/dComponents/DonationVendorComponent.cpp b/dGame/dComponents/DonationVendorComponent.cpp new file mode 100644 index 000000000..7f85ea97c --- /dev/null +++ b/dGame/dComponents/DonationVendorComponent.cpp @@ -0,0 +1,50 @@ +#include "DonationVendorComponent.h" +#include "Database.h" + +DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) { + //LoadConfigData + m_PercentComplete = 0.0; + m_TotalDonated = 0; + m_TotalRemaining = 0; + + // custom attribute to calculate other values + m_Goal = m_Parent->GetVar(u"donationGoal"); + if (m_Goal == 0) m_Goal = INT32_MAX; + + // Default to the nexus tower jawbox activity and setup settings + m_ActivityId = m_Parent->GetVar(u"activityID"); + if ((m_ActivityId == 0) || (m_ActivityId == 117)) { + m_ActivityId = 117; + m_PercentComplete = 1.0; + m_TotalDonated = INT32_MAX; + m_TotalRemaining = 0; + m_Goal = INT32_MAX; + return; + } + + std::unique_ptr query(Database::CreatePreppedStmt("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;")); + query->setInt(1, m_ActivityId); + std::unique_ptr donation_total(query->executeQuery()); + if (donation_total->next()) m_TotalDonated = donation_total->getInt("donation_total"); + m_TotalRemaining = m_Goal - m_TotalDonated; + m_PercentComplete = m_TotalDonated/static_cast(m_Goal); +} + +void DonationVendorComponent::SubmitDonation(uint32_t count) { + if (count <= 0 && ((m_TotalDonated + count) > 0)) return; + m_TotalDonated += count; + m_TotalRemaining = m_Goal - m_TotalDonated; + m_PercentComplete = m_TotalDonated/static_cast(m_Goal); + m_DirtyDonationVendor = true; +} + +void DonationVendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { + VendorComponent::Serialize(outBitStream, bIsInitialUpdate); + outBitStream->Write(bIsInitialUpdate || m_DirtyDonationVendor); + if (bIsInitialUpdate || m_DirtyDonationVendor) { + outBitStream->Write(m_PercentComplete); + outBitStream->Write(m_TotalDonated); + outBitStream->Write(m_TotalRemaining); + if (!bIsInitialUpdate) m_DirtyDonationVendor = false; + } +} diff --git a/dGame/dComponents/DonationVendorComponent.h b/dGame/dComponents/DonationVendorComponent.h new file mode 100644 index 000000000..d1743118d --- /dev/null +++ b/dGame/dComponents/DonationVendorComponent.h @@ -0,0 +1,27 @@ +#ifndef __DONATIONVENDORCOMPONENT__H__ +#define __DONATIONVENDORCOMPONENT__H__ + +#include "VendorComponent.h" +#include "eReplicaComponentType.h" + +class Entity; + +class DonationVendorComponent final : public VendorComponent { +public: + inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR; + DonationVendorComponent(Entity* parent); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; + uint32_t GetActivityID() {return m_ActivityId;}; + void SubmitDonation(uint32_t count); + +private: + bool m_DirtyDonationVendor = false; + float m_PercentComplete = 0.0; + int32_t m_TotalDonated = 0; + int32_t m_TotalRemaining = 0; + uint32_t m_ActivityId = 0; + int32_t m_Goal = 0; +}; + + +#endif //!__DONATIONVENDORCOMPONENT__H__ diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 66b47e529..3625defce 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -116,6 +116,9 @@ Inventory* InventoryComponent::GetInventory(const eInventoryType type) { case eInventoryType::VENDOR_BUYBACK: size = 27u; break; + case eInventoryType::DONATION: + size = 24u; + break; default: break; } @@ -709,7 +712,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) { } } -void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool bIsInitialUpdate, unsigned& flags) { +void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool bIsInitialUpdate) { if (bIsInitialUpdate || m_Dirty) { outBitStream->Write(true); @@ -767,10 +770,6 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b outBitStream->Write(false); } -void InventoryComponent::ResetFlags() { - m_Dirty = false; -} - void InventoryComponent::Update(float deltaTime) { for (auto* set : m_Itemsets) { set->Update(deltaTime); diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 801f9f51e..ffb7a3603 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -42,10 +42,9 @@ class InventoryComponent : public Component explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr); void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void LoadXml(tinyxml2::XMLDocument* document); void UpdateXml(tinyxml2::XMLDocument* document) override; - void ResetFlags(); /** * Returns an inventory of the specified type, if it exists diff --git a/dGame/dComponents/LUPExhibitComponent.cpp b/dGame/dComponents/LUPExhibitComponent.cpp index deb3cc8c8..151f28977 100644 --- a/dGame/dComponents/LUPExhibitComponent.cpp +++ b/dGame/dComponents/LUPExhibitComponent.cpp @@ -38,7 +38,7 @@ void LUPExhibitComponent::NextExhibit() { Game::entityManager->SerializeEntity(m_Parent); } -void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) { +void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write1(); // Dirty flag? outBitStream->Write(m_Exhibit); } diff --git a/dGame/dComponents/LUPExhibitComponent.h b/dGame/dComponents/LUPExhibitComponent.h index 587d1b2f9..510c42fe1 100644 --- a/dGame/dComponents/LUPExhibitComponent.h +++ b/dGame/dComponents/LUPExhibitComponent.h @@ -16,7 +16,7 @@ class LUPExhibitComponent : public Component LUPExhibitComponent(Entity* parent); ~LUPExhibitComponent(); void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * After the timer runs out, this changes the currently exhibited LOT to the next one diff --git a/dGame/dComponents/LevelProgressionComponent.cpp b/dGame/dComponents/LevelProgressionComponent.cpp index 000ed0dc4..9930bdef6 100644 --- a/dGame/dComponents/LevelProgressionComponent.cpp +++ b/dGame/dComponents/LevelProgressionComponent.cpp @@ -37,7 +37,7 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { m_CharacterVersion = static_cast(characterVersion); } -void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(bIsInitialUpdate || m_DirtyLevelInfo); if (bIsInitialUpdate || m_DirtyLevelInfo) outBitStream->Write(m_Level); m_DirtyLevelInfo = false; diff --git a/dGame/dComponents/LevelProgressionComponent.h b/dGame/dComponents/LevelProgressionComponent.h index 06908a810..17ca81173 100644 --- a/dGame/dComponents/LevelProgressionComponent.h +++ b/dGame/dComponents/LevelProgressionComponent.h @@ -21,7 +21,7 @@ class LevelProgressionComponent : public Component { */ LevelProgressionComponent(Entity* parent); - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Save data from this componennt to character XML diff --git a/dGame/dComponents/ModelComponent.cpp b/dGame/dComponents/ModelComponent.cpp index 74f614d10..ccdad2817 100644 --- a/dGame/dComponents/ModelComponent.cpp +++ b/dGame/dComponents/ModelComponent.cpp @@ -8,7 +8,7 @@ ModelComponent::ModelComponent(Entity* parent) : Component(parent) { m_userModelID = m_Parent->GetVarAs(u"userModelID"); } -void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { // ItemComponent Serialization. Pets do not get this serialization. if (!m_Parent->HasComponent(eReplicaComponentType::PET)) { outBitStream->Write1(); diff --git a/dGame/dComponents/ModelComponent.h b/dGame/dComponents/ModelComponent.h index b52248697..c961bff04 100644 --- a/dGame/dComponents/ModelComponent.h +++ b/dGame/dComponents/ModelComponent.h @@ -17,7 +17,7 @@ class ModelComponent : public Component { ModelComponent(Entity* parent); - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Returns the original position of the model diff --git a/dGame/dComponents/ModuleAssemblyComponent.cpp b/dGame/dComponents/ModuleAssemblyComponent.cpp index 8e197f0c2..9089c14c1 100644 --- a/dGame/dComponents/ModuleAssemblyComponent.cpp +++ b/dGame/dComponents/ModuleAssemblyComponent.cpp @@ -46,7 +46,7 @@ const std::u16string& ModuleAssemblyComponent::GetAssemblyPartsLOTs() const { return m_AssemblyPartsLOTs; } -void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { outBitStream->Write1(); diff --git a/dGame/dComponents/ModuleAssemblyComponent.h b/dGame/dComponents/ModuleAssemblyComponent.h index 39670c9a2..6ee5f5052 100644 --- a/dGame/dComponents/ModuleAssemblyComponent.h +++ b/dGame/dComponents/ModuleAssemblyComponent.h @@ -17,7 +17,7 @@ class ModuleAssemblyComponent : public Component { ModuleAssemblyComponent(Entity* parent); ~ModuleAssemblyComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; /** diff --git a/dGame/dComponents/MovementAIComponent.cpp b/dGame/dComponents/MovementAIComponent.cpp index 0743e8f69..1966638d9 100644 --- a/dGame/dComponents/MovementAIComponent.cpp +++ b/dGame/dComponents/MovementAIComponent.cpp @@ -10,85 +10,77 @@ #include "EntityManager.h" #include "SimplePhysicsComponent.h" #include "CDClientManager.h" +#include "Game.h" +#include "dZoneManager.h" #include "CDComponentsRegistryTable.h" #include "CDPhysicsComponentTable.h" -std::map MovementAIComponent::m_PhysicsSpeedCache = {}; +namespace { + /** + * Cache of all lots and their respective speeds + */ + std::map m_PhysicsSpeedCache; +} MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) { - m_Info = std::move(info); - m_Done = true; + m_Info = info; + m_AtFinalWaypoint = true; m_BaseCombatAI = nullptr; - m_BaseCombatAI = reinterpret_cast(m_Parent->GetComponent(eReplicaComponentType::BASE_COMBAT_AI)); + m_BaseCombatAI = m_Parent->GetComponent(); //Try and fix the insane values: - if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius = m_Info.wanderRadius * 0.5f; + if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f; if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f; - if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed = m_Info.wanderSpeed * 0.5f; + if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f; m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT()); - m_NextWaypoint = GetCurrentPosition(); + m_NextWaypoint = m_Parent->GetPosition(); m_Acceleration = 0.4f; - m_Interrupted = false; - m_PullPoint = {}; + m_PullingToPoint = false; + m_PullPoint = NiPoint3::ZERO; m_HaltDistance = 0; - m_Timer = 0; + m_TimeToTravel = 0; + m_TimeTravelled = 0; m_CurrentSpeed = 0; - m_Speed = 0; - m_TotalTime = 0; + m_MaxSpeed = 0; m_LockRotation = false; } -MovementAIComponent::~MovementAIComponent() = default; - void MovementAIComponent::Update(const float deltaTime) { - if (m_Interrupted) { + if (m_PullingToPoint) { const auto source = GetCurrentWaypoint(); const auto speed = deltaTime * 2.5f; - NiPoint3 velocity; - - velocity.x = (m_PullPoint.x - source.x) * speed; - velocity.y = (m_PullPoint.y - source.y) * speed; - velocity.z = (m_PullPoint.z - source.z) * speed; + NiPoint3 velocity = (m_PullPoint - source) * speed; SetPosition(source + velocity); - if (Vector3::DistanceSquared(GetCurrentPosition(), m_PullPoint) < 2 * 2) { - m_Interrupted = false; + if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) { + m_PullingToPoint = false; } return; } - if (AtFinalWaypoint()) // Are we done? - { - return; - } + // Are we done? + if (AtFinalWaypoint()) return; if (m_HaltDistance > 0) { - if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < m_HaltDistance * m_HaltDistance) // Prevent us from hugging the target - { + // Prevent us from hugging the target + if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < std::pow(m_HaltDistance, 2)) { Stop(); - return; } } - if (m_Timer > 0) { - m_Timer -= deltaTime; - - if (m_Timer > 0) { - return; - } - - m_Timer = 0; - } + m_TimeTravelled += deltaTime; + if (m_TimeTravelled < m_TimeToTravel) return; + m_TimeTravelled = 0.0f; const auto source = GetCurrentWaypoint(); @@ -101,48 +93,44 @@ void MovementAIComponent::Update(const float deltaTime) { m_NextWaypoint = GetCurrentWaypoint(); if (m_NextWaypoint == source) { - m_Timer = 0; + m_TimeToTravel = 0.0f; goto nextAction; } - if (m_CurrentSpeed < m_Speed) { + if (m_CurrentSpeed < m_MaxSpeed) { m_CurrentSpeed += m_Acceleration; } - if (m_CurrentSpeed > m_Speed) { - m_CurrentSpeed = m_Speed; + if (m_CurrentSpeed > m_MaxSpeed) { + m_CurrentSpeed = m_MaxSpeed; } - const auto speed = m_CurrentSpeed * m_BaseSpeed; + const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed const auto delta = m_NextWaypoint - source; // Normalize the vector - const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); - + const auto length = delta.Length(); if (length > 0) { - velocity.x = (delta.x / length) * speed; - velocity.y = (delta.y / length) * speed; - velocity.z = (delta.z / length) * speed; + velocity = (delta / length) * speed; } // Calclute the time it will take to reach the next waypoint with the current speed - m_TotalTime = m_Timer = length / speed; + m_TimeTravelled = 0.0f; + m_TimeToTravel = length / speed; SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint)); } else { // Check if there are more waypoints in the queue, if so set our next destination to the next waypoint - if (!m_Queue.empty()) { - SetDestination(m_Queue.top()); - - m_Queue.pop(); - } else { - // We have reached our final waypoint + if (m_CurrentPath.empty()) { Stop(); return; } + SetDestination(m_CurrentPath.top()); + + m_CurrentPath.pop(); } nextAction: @@ -157,7 +145,7 @@ const MovementAIInfo& MovementAIComponent::GetInfo() const { } bool MovementAIComponent::AdvanceWaypointIndex() { - if (m_PathIndex >= m_CurrentPath.size()) { + if (m_PathIndex >= m_InterpolatedWaypoints.size()) { return false; } @@ -167,37 +155,19 @@ bool MovementAIComponent::AdvanceWaypointIndex() { } NiPoint3 MovementAIComponent::GetCurrentWaypoint() const { - if (m_PathIndex >= m_CurrentPath.size()) { - return GetCurrentPosition(); - } - - return m_CurrentPath[m_PathIndex]; -} - -NiPoint3 MovementAIComponent::GetNextWaypoint() const { - return m_NextWaypoint; -} - -NiPoint3 MovementAIComponent::GetCurrentPosition() const { - return m_Parent->GetPosition(); + return m_PathIndex >= m_InterpolatedWaypoints.size() ? m_Parent->GetPosition() : m_InterpolatedWaypoints[m_PathIndex]; } NiPoint3 MovementAIComponent::ApproximateLocation() const { - auto source = GetCurrentPosition(); + auto source = m_Parent->GetPosition(); - if (m_Done) { - return source; - } + if (AtFinalWaypoint()) return source; auto destination = m_NextWaypoint; - auto factor = m_TotalTime > 0 ? (m_TotalTime - m_Timer) / m_TotalTime : 0; + auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0; - auto x = source.x + factor * (destination.x - source.x); - auto y = source.y + factor * (destination.y - source.y); - auto z = source.z + factor * (destination.z - source.z); - - NiPoint3 approximation = NiPoint3(x, y, z); + auto approximation = source + ((destination - source) * percentageToWaypoint); if (dpWorld::Instance().IsLoaded()) { approximation.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(approximation); @@ -226,28 +196,20 @@ bool MovementAIComponent::Warp(const NiPoint3& point) { return true; } -float MovementAIComponent::GetTimer() const { - return m_Timer; -} - -bool MovementAIComponent::AtFinalWaypoint() const { - return m_Done; -} - void MovementAIComponent::Stop() { - if (m_Done) { - return; - } + if (AtFinalWaypoint()) return; SetPosition(ApproximateLocation()); SetVelocity(NiPoint3::ZERO); - m_TotalTime = m_Timer = 0; + m_TimeToTravel = 0; + m_TimeTravelled = 0; - m_Done = true; + m_AtFinalWaypoint = true; - m_CurrentPath = {}; + m_InterpolatedWaypoints.clear(); + while (!m_CurrentPath.empty()) m_CurrentPath.pop(); m_PathIndex = 0; @@ -259,20 +221,17 @@ void MovementAIComponent::Stop() { void MovementAIComponent::PullToPoint(const NiPoint3& point) { Stop(); - m_Interrupted = true; + m_PullingToPoint = true; m_PullPoint = point; } void MovementAIComponent::SetPath(std::vector path) { - std::reverse(path.begin(), path.end()); - - for (const auto& point : path) { - m_Queue.push(point); - } + if (path.empty()) return; + std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) { + this->m_CurrentPath.push(point); + }); - SetDestination(m_Queue.top()); - - m_Queue.pop(); + SetDestination(path.front()); } float MovementAIComponent::GetBaseSpeed(LOT lot) { @@ -291,26 +250,14 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) { componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::CONTROLLABLE_PHYSICS, -1); - if (componentID != -1) { - physicsComponent = physicsComponentTable->GetByID(componentID); - - goto foundComponent; - } - - componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1); - - if (componentID != -1) { - physicsComponent = physicsComponentTable->GetByID(componentID); - - goto foundComponent; + if (componentID == -1) { + componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1); } -foundComponent: + physicsComponent = physicsComponentTable->GetByID(componentID); // Client defaults speed to 10 and if the speed is also null in the table, it defaults to 10. - float speed = 10.0f; - - if (physicsComponent) speed = physicsComponent->speed; + float speed = physicsComponent != nullptr ? physicsComponent->speed : 10.0f; float delta = fabs(speed) - 1.0f; @@ -322,39 +269,11 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) { } void MovementAIComponent::SetPosition(const NiPoint3& value) { - auto* controllablePhysicsComponent = m_Parent->GetComponent(); - - if (controllablePhysicsComponent != nullptr) { - controllablePhysicsComponent->SetPosition(value); - - return; - } - - auto* simplePhysicsComponent = m_Parent->GetComponent(); - - if (simplePhysicsComponent != nullptr) { - simplePhysicsComponent->SetPosition(value); - } + m_Parent->SetPosition(value); } void MovementAIComponent::SetRotation(const NiQuaternion& value) { - if (m_LockRotation) { - return; - } - - auto* controllablePhysicsComponent = m_Parent->GetComponent(); - - if (controllablePhysicsComponent != nullptr) { - controllablePhysicsComponent->SetRotation(value); - - return; - } - - auto* simplePhysicsComponent = m_Parent->GetComponent(); - - if (simplePhysicsComponent != nullptr) { - simplePhysicsComponent->SetRotation(value); - } + if (!m_LockRotation) m_Parent->SetRotation(value); } void MovementAIComponent::SetVelocity(const NiPoint3& value) { @@ -373,15 +292,8 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) { } } -void MovementAIComponent::SetDestination(const NiPoint3& value) { - if (m_Interrupted) { - return; - } - - /*if (Vector3::DistanceSquared(value, GetDestination()) < 2 * 2) - { - return; - }*/ +void MovementAIComponent::SetDestination(const NiPoint3& destination) { + if (m_PullingToPoint) return; const auto location = ApproximateLocation(); @@ -390,97 +302,53 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) { } std::vector computedPath; - if (dpWorld::Instance().IsLoaded()) { - computedPath = dpWorld::Instance().GetNavMesh()->GetPath(GetCurrentPosition(), value, m_Info.wanderSpeed); - } else { + computedPath = dpWorld::Instance().GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed); + } + + // Somehow failed + if (computedPath.empty()) { // Than take 10 points between the current position and the destination and make that the path - auto point = location; + auto start = location; - auto delta = value - point; + auto delta = destination - start; - auto step = delta / 10; + auto step = delta / 10.0f; for (int i = 0; i < 10; i++) { - point = point + step; + // TODO: Replace this with += when the NiPoint3::operator+= is fixed + start = start + step; - computedPath.push_back(point); + computedPath.push_back(start); } } - if (computedPath.empty()) // Somehow failed - { - return; - } - - m_CurrentPath.clear(); - - m_CurrentPath.push_back(location); + m_InterpolatedWaypoints.clear(); // Simply path - for (auto point : computedPath) { + for (auto& point : computedPath) { if (dpWorld::Instance().IsLoaded()) { point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point); } - m_CurrentPath.push_back(point); + m_InterpolatedWaypoints.push_back(point); } - m_CurrentPath.push_back(computedPath[computedPath.size() - 1]); - m_PathIndex = 0; - m_TotalTime = m_Timer = 0; + m_TimeTravelled = 0; + m_TimeToTravel = 0; - m_Done = false; + m_AtFinalWaypoint = false; } NiPoint3 MovementAIComponent::GetDestination() const { - if (m_CurrentPath.empty()) { - return GetCurrentPosition(); - } - - return m_CurrentPath[m_CurrentPath.size() - 1]; + return m_InterpolatedWaypoints.empty() ? m_Parent->GetPosition() : m_InterpolatedWaypoints.back(); } -void MovementAIComponent::SetSpeed(const float value) { - m_Speed = value; +void MovementAIComponent::SetMaxSpeed(const float value) { + if (value == m_MaxSpeed) return; + m_MaxSpeed = value; m_Acceleration = value / 5; } - -float MovementAIComponent::GetSpeed() const { - return m_Speed; -} - -void MovementAIComponent::SetAcceleration(const float value) { - m_Acceleration = value; -} - -float MovementAIComponent::GetAcceleration() const { - return m_Acceleration; -} - -void MovementAIComponent::SetHaltDistance(const float value) { - m_HaltDistance = value; -} - -float MovementAIComponent::GetHaltDistance() const { - return m_HaltDistance; -} - -void MovementAIComponent::SetCurrentSpeed(float value) { - m_CurrentSpeed = value; -} - -float MovementAIComponent::GetCurrentSpeed() const { - return m_CurrentSpeed; -} - -void MovementAIComponent::SetLockRotation(bool value) { - m_LockRotation = value; -} - -bool MovementAIComponent::GetLockRotation() const { - return m_LockRotation; -} diff --git a/dGame/dComponents/MovementAIComponent.h b/dGame/dComponents/MovementAIComponent.h index 3c9044aae..4a4e4c0a9 100644 --- a/dGame/dComponents/MovementAIComponent.h +++ b/dGame/dComponents/MovementAIComponent.h @@ -1,6 +1,6 @@ /* * Darkflame Universe - * Copyright 2018 + * Copyright 2023 */ #ifndef MOVEMENTAICOMPONENT_H @@ -60,7 +60,6 @@ class MovementAIComponent : public Component { static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI; MovementAIComponent(Entity* parentEntity, MovementAIInfo info); - ~MovementAIComponent() override; void Update(float deltaTime) override; @@ -86,61 +85,55 @@ class MovementAIComponent : public Component { * Sets the max speed at which this entity may run * @param value the speed value to set */ - void SetSpeed(float value); - - /** - * Returns the max speed at which this entity may run - * @return the max speed at which this entity may run - */ - float GetSpeed() const; + void SetMaxSpeed(float value); /** * Sets how fast the entity will accelerate when not running at full speed * @param value the acceleration to set */ - void SetAcceleration(float value); + void SetAcceleration(float value) { m_Acceleration = value; }; /** * Returns the current speed at which this entity accelerates when not running at full speed * @return the current speed at which this entity accelerates when not running at full speed */ - float GetAcceleration() const; + float GetAcceleration() const { return m_Acceleration; }; /** * Sets the halting distance (the distance at which we consider the target to be reached) * @param value the halting distance to set */ - void SetHaltDistance(float value); + void SetHaltDistance(float value) { m_HaltDistance = value; } /** * Returns the current halting distance (the distance at which we consider the target to be reached) * @return the current halting distance */ - float GetHaltDistance() const; + float GetHaltDistance() const { return m_HaltDistance; } /** * Sets the speed the entity is currently running at * @param value the speed value to set */ - void SetCurrentSpeed(float value); + void SetCurrentSpeed(float value) { m_CurrentSpeed = value; } /** * Returns the speed the entity is currently running at * @return the speed the entity is currently running at */ - float GetCurrentSpeed() const; + float GetCurrentSpeed() const { return m_CurrentSpeed; } /** * Locks the rotation of this entity in place, depending on the argument * @param value if true, the entity will be rotationally locked */ - void SetLockRotation(bool value); + void SetLockRotation(bool value) { m_LockRotation = value; } /** * Returns whether this entity is currently rotationally locked * @return true if the entity is rotationally locked, false otherwise */ - bool GetLockRotation() const; + bool GetLockRotation() const { return m_LockRotation; }; /** * Attempts to update the waypoint index, making the entity move to the next waypoint @@ -158,13 +151,7 @@ class MovementAIComponent : public Component { * Returns the waypoint this entity is supposed to move towards next * @return the waypoint this entity is supposed to move towards next */ - NiPoint3 GetNextWaypoint() const; - - /** - * Returns the current position of this entity - * @return the current position of this entity - */ - NiPoint3 GetCurrentPosition() const; + NiPoint3 GetNextWaypoint() const { return m_NextWaypoint; } /** * Returns the approximate current location of the entity, including y coordinates @@ -180,17 +167,11 @@ class MovementAIComponent : public Component { */ bool Warp(const NiPoint3& point); - /** - * Returns the time it will take to reach the final waypoint according to the current speed - * @return the time it will take to reach the final waypoint according to the current speed - */ - float GetTimer() const; - /** * Returns if the entity is at its final waypoint * @return if the entity is at its final waypoint */ - bool AtFinalWaypoint() const; + bool AtFinalWaypoint() const { return m_AtFinalWaypoint; } /** * Renders the entity stationary @@ -250,17 +231,12 @@ class MovementAIComponent : public Component { /** * The max speed this entity may move at */ - float m_Speed; + float m_MaxSpeed; /** * The time it will take to reach the next waypoint using the current speed */ - float m_Timer; - - /** - * The total time it will take to reach the waypoint form its starting point - */ - float m_TotalTime; + float m_TimeTravelled; /** * The path this entity is currently traversing @@ -270,7 +246,7 @@ class MovementAIComponent : public Component { /** * If the entity has reached it last waypoint */ - bool m_Done; + bool m_AtFinalWaypoint; /** * The speed the entity is currently moving at @@ -287,6 +263,11 @@ class MovementAIComponent : public Component { */ float m_HaltDistance; + /** + * The total time it will take to reach the waypoint form its starting point + */ + float m_TimeToTravel; + /** * The base speed this entity has */ @@ -295,7 +276,7 @@ class MovementAIComponent : public Component { /** * If the AI is currently turned of (e.g. when teleporting to some location) */ - bool m_Interrupted; + bool m_PullingToPoint; /** * A position that the entity is currently moving towards while being interrupted @@ -315,17 +296,12 @@ class MovementAIComponent : public Component { /** * The path the entity is currently following */ - std::vector m_CurrentPath; - - /** - * Queue of positions to traverse - */ - std::stack m_Queue; + std::vector m_InterpolatedWaypoints; /** - * Cache of all lots and their respective speeds + * The path from the current position to the destination. */ - static std::map m_PhysicsSpeedCache; + std::stack m_CurrentPath; }; #endif // MOVEMENTAICOMPONENT_H diff --git a/dGame/dComponents/MovingPlatformComponent.cpp b/dGame/dComponents/MovingPlatformComponent.cpp index f4dcdbe98..60d320f44 100644 --- a/dGame/dComponents/MovingPlatformComponent.cpp +++ b/dGame/dComponents/MovingPlatformComponent.cpp @@ -32,7 +32,7 @@ MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) { MoverSubComponent::~MoverSubComponent() = default; -void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const { +void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(true); outBitStream->Write(static_cast(mState)); @@ -71,7 +71,7 @@ MovingPlatformComponent::~MovingPlatformComponent() { delete static_cast(m_MoverSubComponent); } -void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { // Here we don't serialize the moving platform to let the client simulate the movement if (!m_Serialize) { @@ -112,7 +112,7 @@ void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bI if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) { // TODO } else { - mover->Serialize(outBitStream, bIsInitialUpdate, flags); + mover->Serialize(outBitStream, bIsInitialUpdate); } } } diff --git a/dGame/dComponents/MovingPlatformComponent.h b/dGame/dComponents/MovingPlatformComponent.h index 9e4c1ecfe..bb83a5381 100644 --- a/dGame/dComponents/MovingPlatformComponent.h +++ b/dGame/dComponents/MovingPlatformComponent.h @@ -38,7 +38,7 @@ class MoverSubComponent { MoverSubComponent(const NiPoint3& startPos); ~MoverSubComponent(); - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const; + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate); /** * The state the platform is currently in @@ -111,7 +111,7 @@ class MovingPlatformComponent : public Component { MovingPlatformComponent(Entity* parent, const std::string& pathName); ~MovingPlatformComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Stops all pathing, called when an entity starts a quick build associated with this platform diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/MultiZoneEntranceComponent.cpp similarity index 69% rename from dGame/dComponents/RocketLaunchLupComponent.cpp rename to dGame/dComponents/MultiZoneEntranceComponent.cpp index 3c3265408..7c2e2b790 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/MultiZoneEntranceComponent.cpp @@ -1,9 +1,9 @@ -#include "RocketLaunchLupComponent.h" +#include "MultiZoneEntranceComponent.h" #include "RocketLaunchpadControlComponent.h" #include "InventoryComponent.h" #include "CharacterComponent.h" -RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) { +MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Component(parent) { m_Parent = parent; std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar(u"MultiZoneIDs")); std::stringstream ss(zoneString); @@ -14,17 +14,17 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(p } } -RocketLaunchLupComponent::~RocketLaunchLupComponent() {} +MultiZoneEntranceComponent::~MultiZoneEntranceComponent() {} -void RocketLaunchLupComponent::OnUse(Entity* originator) { +void MultiZoneEntranceComponent::OnUse(Entity* originator) { auto* rocket = originator->GetComponent()->RocketEquip(originator); if (!rocket) return; // the LUP world menu is just the property menu, the client knows how to handle it - GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress()); + GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), originator->GetSystemAddress()); } -void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) { +void MultiZoneEntranceComponent::OnSelectWorld(Entity* originator, uint32_t index) { auto* rocketLaunchpadControlComponent = m_Parent->GetComponent(); if (!rocketLaunchpadControlComponent) return; diff --git a/dGame/dComponents/RocketLaunchLupComponent.h b/dGame/dComponents/MultiZoneEntranceComponent.h similarity index 84% rename from dGame/dComponents/RocketLaunchLupComponent.h rename to dGame/dComponents/MultiZoneEntranceComponent.h index 226fa1b23..9c1f4360b 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.h +++ b/dGame/dComponents/MultiZoneEntranceComponent.h @@ -1,7 +1,6 @@ #pragma once #include "Entity.h" -#include "GameMessages.h" #include "Component.h" #include "eReplicaComponentType.h" @@ -9,16 +8,16 @@ * Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds. * */ -class RocketLaunchLupComponent : public Component { +class MultiZoneEntranceComponent : public Component { public: - static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH_LUP; + static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE; /** * Constructor for this component, builds the m_LUPWorlds vector * @param parent parent that contains this component */ - RocketLaunchLupComponent(Entity* parent); - ~RocketLaunchLupComponent() override; + MultiZoneEntranceComponent(Entity* parent); + ~MultiZoneEntranceComponent() override; /** * Handles an OnUse event from some entity, preparing it for launch to some other world diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 167fbb2f4..5132af087 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -107,7 +107,7 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(pare result.finalize(); } -void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { const bool tamed = m_Owner != LWOOBJID_EMPTY; outBitStream->Write1(); // Always serialize as dirty for now @@ -395,7 +395,7 @@ void PetComponent::Update(float deltaTime) { } auto destination = owner->GetPosition(); - NiPoint3 position = m_MovementAI->GetCurrentPosition(); + NiPoint3 position = m_MovementAI->GetParent()->GetPosition(); float distanceToOwner = Vector3::DistanceSquared(position, destination); @@ -466,7 +466,7 @@ void PetComponent::Update(float deltaTime) { m_MovementAI->SetHaltDistance(haltDistance); - m_MovementAI->SetSpeed(2.5f); + m_MovementAI->SetMaxSpeed(2.5f); m_MovementAI->SetDestination(destination); @@ -822,17 +822,17 @@ void PetComponent::Wander() { destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination); } - if (Vector3::DistanceSquared(destination, m_MovementAI->GetCurrentPosition()) < 2 * 2) { + if (Vector3::DistanceSquared(destination, m_MovementAI->GetParent()->GetPosition()) < 2 * 2) { m_MovementAI->Stop(); return; } - m_MovementAI->SetSpeed(info.wanderSpeed); + m_MovementAI->SetMaxSpeed(info.wanderSpeed); m_MovementAI->SetDestination(destination); - m_Timer += (m_MovementAI->GetCurrentPosition().x - destination.x) / info.wanderSpeed; + m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / info.wanderSpeed; } void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { diff --git a/dGame/dComponents/PetComponent.h b/dGame/dComponents/PetComponent.h index b3d089a93..4ca6a49ef 100644 --- a/dGame/dComponents/PetComponent.h +++ b/dGame/dComponents/PetComponent.h @@ -26,7 +26,7 @@ class PetComponent : public Component explicit PetComponent(Entity* parentEntity, uint32_t componentId); ~PetComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; /** diff --git a/dGame/dComponents/PhantomPhysicsComponent.cpp b/dGame/dComponents/PhantomPhysicsComponent.cpp index 640281f88..866543b37 100644 --- a/dGame/dComponents/PhantomPhysicsComponent.cpp +++ b/dGame/dComponents/PhantomPhysicsComponent.cpp @@ -306,7 +306,7 @@ void PhantomPhysicsComponent::CreatePhysics() { m_HasCreatedPhysics = true; } -void PhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void PhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_PositionInfoDirty || bIsInitialUpdate); if (m_PositionInfoDirty || bIsInitialUpdate) { outBitStream->Write(m_Position.x); @@ -348,11 +348,6 @@ void PhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bI } } -void PhantomPhysicsComponent::ResetFlags() { - m_EffectInfoDirty = false; - m_PositionInfoDirty = false; -} - void PhantomPhysicsComponent::Update(float deltaTime) { if (!m_dpEntity) return; diff --git a/dGame/dComponents/PhantomPhysicsComponent.h b/dGame/dComponents/PhantomPhysicsComponent.h index cc0d18447..e5769f40e 100644 --- a/dGame/dComponents/PhantomPhysicsComponent.h +++ b/dGame/dComponents/PhantomPhysicsComponent.h @@ -32,8 +32,7 @@ class PhantomPhysicsComponent : public Component { PhantomPhysicsComponent(Entity* parent); ~PhantomPhysicsComponent() override; void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); - void ResetFlags(); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Creates the physics shape for this entity based on LDF data diff --git a/dGame/dComponents/PlayerForcedMovementComponent.cpp b/dGame/dComponents/PlayerForcedMovementComponent.cpp index 76993507f..d511ad782 100644 --- a/dGame/dComponents/PlayerForcedMovementComponent.cpp +++ b/dGame/dComponents/PlayerForcedMovementComponent.cpp @@ -6,7 +6,7 @@ PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : C PlayerForcedMovementComponent::~PlayerForcedMovementComponent() {} -void PlayerForcedMovementComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void PlayerForcedMovementComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_DirtyInfo || bIsInitialUpdate); if (m_DirtyInfo || bIsInitialUpdate) { outBitStream->Write(m_PlayerOnRail); diff --git a/dGame/dComponents/PlayerForcedMovementComponent.h b/dGame/dComponents/PlayerForcedMovementComponent.h index 90708c9aa..43781baba 100644 --- a/dGame/dComponents/PlayerForcedMovementComponent.h +++ b/dGame/dComponents/PlayerForcedMovementComponent.h @@ -19,7 +19,7 @@ class PlayerForcedMovementComponent : public Component { PlayerForcedMovementComponent(Entity* parent); ~PlayerForcedMovementComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * @brief Set the Player On Rail object diff --git a/dGame/dComponents/PossessableComponent.cpp b/dGame/dComponents/PossessableComponent.cpp index 5c45a6c19..509b1a07c 100644 --- a/dGame/dComponents/PossessableComponent.cpp +++ b/dGame/dComponents/PossessableComponent.cpp @@ -27,7 +27,7 @@ PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) result.finalize(); } -void PossessableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void PossessableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_DirtyPossessable || bIsInitialUpdate); if (m_DirtyPossessable || bIsInitialUpdate) { m_DirtyPossessable = false; // reset flag diff --git a/dGame/dComponents/PossessableComponent.h b/dGame/dComponents/PossessableComponent.h index 2026c11e8..be60bb778 100644 --- a/dGame/dComponents/PossessableComponent.h +++ b/dGame/dComponents/PossessableComponent.h @@ -18,7 +18,7 @@ class PossessableComponent : public Component { PossessableComponent(Entity* parentEntity, uint32_t componentId); - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * @brief mounts the Entity diff --git a/dGame/dComponents/PossessorComponent.cpp b/dGame/dComponents/PossessorComponent.cpp index 8019f91c8..0cb649564 100644 --- a/dGame/dComponents/PossessorComponent.cpp +++ b/dGame/dComponents/PossessorComponent.cpp @@ -26,7 +26,7 @@ PossessorComponent::~PossessorComponent() { } } -void PossessorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void PossessorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_DirtyPossesor || bIsInitialUpdate); if (m_DirtyPossesor || bIsInitialUpdate) { m_DirtyPossesor = false; diff --git a/dGame/dComponents/PossessorComponent.h b/dGame/dComponents/PossessorComponent.h index 4456af273..d21695f06 100644 --- a/dGame/dComponents/PossessorComponent.h +++ b/dGame/dComponents/PossessorComponent.h @@ -23,7 +23,7 @@ class PossessorComponent : public Component { PossessorComponent(Entity* parent); ~PossessorComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * @brief Mounts the entity diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index 63d57c3db..a7878b7f4 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -424,9 +424,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu } } -void RacingControlComponent::Serialize(RakNet::BitStream* outBitStream, - bool bIsInitialUpdate, - unsigned int& flags) { +void RacingControlComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { // BEGIN Scripted Activity outBitStream->Write1(); diff --git a/dGame/dComponents/RacingControlComponent.h b/dGame/dComponents/RacingControlComponent.h index a81121e16..c713a7597 100644 --- a/dGame/dComponents/RacingControlComponent.h +++ b/dGame/dComponents/RacingControlComponent.h @@ -110,8 +110,8 @@ class RacingControlComponent : public Component { RacingControlComponent(Entity* parentEntity); ~RacingControlComponent(); - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); - void Update(float deltaTime); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; + void Update(float deltaTime) override; /** * Invoked when a player loads into the zone. diff --git a/dGame/dComponents/RacingSoundTriggerComponent.h b/dGame/dComponents/RacingSoundTriggerComponent.h new file mode 100644 index 000000000..0f79c67f3 --- /dev/null +++ b/dGame/dComponents/RacingSoundTriggerComponent.h @@ -0,0 +1,15 @@ +#ifndef __RACINGSOUNDTRIGGERCOMPONENT__H__ +#define __RACINGSOUNDTRIGGERCOMPONENT__H__ + +#include "SoundTriggerComponent.h" +#include "eReplicaComponentType.h" + +class Entity; + +class RacingSoundTriggerComponent : public SoundTriggerComponent { +public: + inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER; + RacingSoundTriggerComponent(Entity* parent) : SoundTriggerComponent(parent){}; +}; + +#endif //!__RACINGSOUNDTRIGGERCOMPONENT__H__ diff --git a/dGame/dComponents/RebuildComponent.cpp b/dGame/dComponents/RebuildComponent.cpp index 21675e06e..da8a9a4b9 100644 --- a/dGame/dComponents/RebuildComponent.cpp +++ b/dGame/dComponents/RebuildComponent.cpp @@ -57,7 +57,7 @@ RebuildComponent::~RebuildComponent() { DespawnActivator(); } -void RebuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void RebuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (m_Parent->GetComponent(eReplicaComponentType::DESTROYABLE) == nullptr) { if (bIsInitialUpdate) { outBitStream->Write(false); @@ -180,7 +180,7 @@ void RebuildComponent::Update(float deltaTime) { { Entity* builder = GetBuilder(); - if (builder == nullptr) { + if (!builder) { ResetRebuild(false); return; @@ -198,16 +198,16 @@ void RebuildComponent::Update(float deltaTime) { if (!destComp) break; int newImagination = destComp->GetImagination(); - if (newImagination <= 0) { - CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true); - break; - } ++m_DrainedImagination; --newImagination; destComp->SetImagination(newImagination); Game::entityManager->SerializeEntity(builder); + if (newImagination <= 0) { + CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true); + break; + } } @@ -482,7 +482,7 @@ void RebuildComponent::CompleteRebuild(Entity* user) { if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId); } } - } else{ + } else { auto* missionComponent = builder->GetComponent(); if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId); } diff --git a/dGame/dComponents/RebuildComponent.h b/dGame/dComponents/RebuildComponent.h index 09dd0465c..cd266c1f8 100644 --- a/dGame/dComponents/RebuildComponent.h +++ b/dGame/dComponents/RebuildComponent.h @@ -27,7 +27,7 @@ class RebuildComponent : public Component { RebuildComponent(Entity* entity); ~RebuildComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; /** diff --git a/dGame/dComponents/RenderComponent.cpp b/dGame/dComponents/RenderComponent.cpp index 94f5fb5d0..44663a17a 100644 --- a/dGame/dComponents/RenderComponent.cpp +++ b/dGame/dComponents/RenderComponent.cpp @@ -54,7 +54,7 @@ RenderComponent::~RenderComponent() { m_Effects.clear(); } -void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (!bIsInitialUpdate) return; outBitStream->Write(m_Effects.size()); diff --git a/dGame/dComponents/RenderComponent.h b/dGame/dComponents/RenderComponent.h index cdf32160e..24cfd16d4 100644 --- a/dGame/dComponents/RenderComponent.h +++ b/dGame/dComponents/RenderComponent.h @@ -61,7 +61,7 @@ class RenderComponent : public Component { RenderComponent(Entity* entity, int32_t componentId = -1); ~RenderComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; /** diff --git a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp index babd19743..5390db3a7 100644 --- a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp +++ b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp @@ -15,7 +15,7 @@ RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* paren RigidbodyPhantomPhysicsComponent::~RigidbodyPhantomPhysicsComponent() { } -void RigidbodyPhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void RigidbodyPhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_IsDirty || bIsInitialUpdate); if (m_IsDirty || bIsInitialUpdate) { outBitStream->Write(m_Position.x); diff --git a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h index 480f9b812..ba6a54a08 100644 --- a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h +++ b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h @@ -24,7 +24,7 @@ class RigidbodyPhantomPhysicsComponent : public Component { RigidbodyPhantomPhysicsComponent(Entity* parent); ~RigidbodyPhantomPhysicsComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Returns the position of this entity diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.cpp b/dGame/dComponents/RocketLaunchpadControlComponent.cpp index 10908d9ef..34c34dd19 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.cpp +++ b/dGame/dComponents/RocketLaunchpadControlComponent.cpp @@ -13,9 +13,9 @@ #include "ChatPackets.h" #include "MissionComponent.h" #include "PropertyEntranceComponent.h" -#include "RocketLaunchLupComponent.h" +#include "MultiZoneEntranceComponent.h" #include "dServer.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "eObjectWorldState.h" #include "eConnectionType.h" #include "eMasterMessageType.h" @@ -94,7 +94,7 @@ void RocketLaunchpadControlComponent::OnUse(Entity* originator) { return; } - auto* rocketLaunchLUP = m_Parent->GetComponent(); + auto* rocketLaunchLUP = m_Parent->GetComponent(); if (rocketLaunchLUP) { return; } @@ -137,7 +137,7 @@ LWOCLONEID RocketLaunchpadControlComponent::GetSelectedCloneId(LWOOBJID player) void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PREP_ZONE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PREP_ZONE); bitStream.Write(zoneID); Game::server->SendToMaster(&bitStream); } diff --git a/dGame/dComponents/ScriptedActivityComponent.cpp b/dGame/dComponents/ScriptedActivityComponent.cpp index 60e2dfe0f..fa70139bc 100644 --- a/dGame/dComponents/ScriptedActivityComponent.cpp +++ b/dGame/dComponents/ScriptedActivityComponent.cpp @@ -11,7 +11,7 @@ #include "EntityManager.h" #include "ChatPackets.h" #include "Player.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "dServer.h" #include "GeneralUtils.h" #include "dZoneManager.h" @@ -82,7 +82,7 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit ScriptedActivityComponent::~ScriptedActivityComponent() = default; -void ScriptedActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const { +void ScriptedActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(true); outBitStream->Write(m_ActivityPlayers.size()); @@ -516,7 +516,7 @@ void ActivityInstance::StartZone() { // only make a team if we have more than one participant if (participants.size() > 1) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM); bitStream.Write(leader->GetObjectID()); bitStream.Write(m_Participants.size()); diff --git a/dGame/dComponents/ScriptedActivityComponent.h b/dGame/dComponents/ScriptedActivityComponent.h index 1d49a62d1..455ac6677 100644 --- a/dGame/dComponents/ScriptedActivityComponent.h +++ b/dGame/dComponents/ScriptedActivityComponent.h @@ -162,7 +162,7 @@ class ScriptedActivityComponent : public Component { ~ScriptedActivityComponent() override; void Update(float deltaTime) override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const; + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Makes some entity join the minigame, if it's a lobbied one, the entity will be placed in the lobby diff --git a/dGame/dComponents/ShootingGalleryComponent.cpp b/dGame/dComponents/ShootingGalleryComponent.cpp index ed91ac964..922085988 100644 --- a/dGame/dComponents/ShootingGalleryComponent.cpp +++ b/dGame/dComponents/ShootingGalleryComponent.cpp @@ -17,7 +17,7 @@ void ShootingGalleryComponent::SetDynamicParams(const DynamicShootingGalleryPara Game::entityManager->SerializeEntity(m_Parent); } -void ShootingGalleryComponent::Serialize(RakNet::BitStream* outBitStream, bool isInitialUpdate, uint32_t& flags) const { +void ShootingGalleryComponent::Serialize(RakNet::BitStream* outBitStream, bool isInitialUpdate) { // Start ScriptedActivityComponent outBitStream->Write(true); if (m_CurrentPlayerID == LWOOBJID_EMPTY) { diff --git a/dGame/dComponents/ShootingGalleryComponent.h b/dGame/dComponents/ShootingGalleryComponent.h index c31575f12..bc1aa090d 100644 --- a/dGame/dComponents/ShootingGalleryComponent.h +++ b/dGame/dComponents/ShootingGalleryComponent.h @@ -77,7 +77,7 @@ class ShootingGalleryComponent : public Component { explicit ShootingGalleryComponent(Entity* parent); ~ShootingGalleryComponent(); - void Serialize(RakNet::BitStream* outBitStream, bool isInitialUpdate, uint32_t& flags) const; + void Serialize(RakNet::BitStream* outBitStream, bool isInitialUpdate) override; /** * Returns the static params for the shooting gallery diff --git a/dGame/dComponents/SimplePhysicsComponent.cpp b/dGame/dComponents/SimplePhysicsComponent.cpp index 54a2e6163..3cd951691 100644 --- a/dGame/dComponents/SimplePhysicsComponent.cpp +++ b/dGame/dComponents/SimplePhysicsComponent.cpp @@ -33,7 +33,7 @@ SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* par SimplePhysicsComponent::~SimplePhysicsComponent() { } -void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { outBitStream->Write(m_ClimbableType != eClimbableType::CLIMBABLE_TYPE_NOT); outBitStream->Write(m_ClimbableType); diff --git a/dGame/dComponents/SimplePhysicsComponent.h b/dGame/dComponents/SimplePhysicsComponent.h index 513567105..4908c8efe 100644 --- a/dGame/dComponents/SimplePhysicsComponent.h +++ b/dGame/dComponents/SimplePhysicsComponent.h @@ -33,7 +33,7 @@ class SimplePhysicsComponent : public Component { SimplePhysicsComponent(uint32_t componentID, Entity* parent); ~SimplePhysicsComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Returns the position of this entity diff --git a/dGame/dComponents/SkillComponent.cpp b/dGame/dComponents/SkillComponent.cpp index 5c1d221ab..13cf98f6c 100644 --- a/dGame/dComponents/SkillComponent.cpp +++ b/dGame/dComponents/SkillComponent.cpp @@ -15,7 +15,7 @@ #include "dServer.h" #include "EntityManager.h" #include "Game.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "BaseCombatAIComponent.h" #include "ScriptComponent.h" #include "BuffComponent.h" @@ -304,7 +304,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c // Write message RakNet::BitStream message; - PacketUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); + BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); message.Write(this->m_Parent->GetObjectID()); start.Serialize(&message); @@ -437,7 +437,7 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry) RakNet::BitStream message; - PacketUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); + BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); message.Write(this->m_Parent->GetObjectID()); projectileImpact.Serialize(&message); @@ -485,7 +485,7 @@ SkillComponent::~SkillComponent() { Reset(); } -void SkillComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void SkillComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) outBitStream->Write0(); } diff --git a/dGame/dComponents/SkillComponent.h b/dGame/dComponents/SkillComponent.h index 034e65ce7..b157ad3dd 100644 --- a/dGame/dComponents/SkillComponent.h +++ b/dGame/dComponents/SkillComponent.h @@ -64,7 +64,7 @@ class SkillComponent : public Component { explicit SkillComponent(Entity* parent); ~SkillComponent() override; - static void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Computes skill updates. Invokes CalculateUpdate. diff --git a/dGame/dComponents/SoundTriggerComponent.cpp b/dGame/dComponents/SoundTriggerComponent.cpp index 21d30948f..dc7355db4 100644 --- a/dGame/dComponents/SoundTriggerComponent.cpp +++ b/dGame/dComponents/SoundTriggerComponent.cpp @@ -1,93 +1,114 @@ #include "SoundTriggerComponent.h" -#include "EntityManager.h" #include "Game.h" +#include "dLogger.h" -SoundTriggerComponent::SoundTriggerComponent(Entity* parent) : Component(parent) { - const auto musicCueName = parent->GetVar(u"NDAudioMusicCue_Name"); - const auto musicCueBoredomTime = parent->GetVar(u"NDAudioMusicCue_BoredomTime"); +void MusicCue::Serialize(RakNet::BitStream* outBitStream){ + outBitStream->Write(name.size()); + outBitStream->Write(name.c_str(), name.size()); + outBitStream->Write(result); + outBitStream->Write(boredomTime); +} - this->musicCues.push_back({ - musicCueName, - 1, - musicCueBoredomTime - }); +void MusicParameter::Serialize(RakNet::BitStream* outBitStream){ + outBitStream->Write(name.size()); + outBitStream->Write(name.c_str(), name.size()); + outBitStream->Write(value); +} - const auto mixerName = parent->GetVar(u"NDAudioMixerProgram_Name"); - this->mixerPrograms.push_back(mixerName); +void GUIDResults::Serialize(RakNet::BitStream* outBitStream){ + guid.Serialize(outBitStream); + outBitStream->Write(result); +} - const auto guid2String = parent->GetVar(u"NDAudioEventGUID2"); - if (!guid2String.empty()) { - this->guids.emplace_back(guid2String); - } +void MixerProgram::Serialize(RakNet::BitStream* outBitStream){ + outBitStream->Write(name.size()); + outBitStream->Write(name.c_str(), name.size()); + outBitStream->Write(result); } +SoundTriggerComponent::SoundTriggerComponent(Entity* parent) : Component(parent) { + + const auto musicCueName = parent->GetVar(u"NDAudioMusicCue_Name"); + if (!musicCueName.empty()) { + auto newCue = MusicCue(musicCueName); + const auto musicCueBoredomTime = parent->GetVar(u"NDAudioMusicCue_BoredomTime"); + if (musicCueBoredomTime) newCue.boredomTime = musicCueBoredomTime; + this->m_MusicCues.push_back(newCue); + } + + const auto musicParameterName = parent->GetVar(u"NDAudioMusicParameter_Name"); + if (!musicParameterName.empty()) { + auto newParams = MusicParameter(musicParameterName); + const auto musicParameterValue = parent->GetVar(u"NDAudioMusicParameter_Value"); + if (musicParameterValue) newParams.value = musicParameterValue; + this->m_MusicParameters.push_back(newParams); + } -SoundTriggerComponent::~SoundTriggerComponent() = default; + const auto guidString = parent->GetVar(u"NDAudioEventGUID"); + if (!guidString.empty()) + this->m_2DAmbientSounds.push_back(GUIDResults(guidString)); -void SoundTriggerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - if (bIsInitialUpdate) - dirty = true; + const auto guid2String = parent->GetVar(u"NDAudioEventGUID2"); + if (!guid2String.empty()) + this->m_3DAmbientSounds.push_back(GUIDResults(guid2String)); - outBitStream->Write(dirty); + const auto mixerName = parent->GetVar(u"NDAudioMixerProgram_Name"); + if (!mixerName.empty()) this->m_MixerPrograms.push_back(MixerProgram(mixerName)); +} - if (dirty) { - outBitStream->Write(this->musicCues.size()); - for (const auto& musicCue : this->musicCues) { - outBitStream->Write(musicCue.name.size()); - outBitStream->Write(musicCue.name.c_str(), musicCue.name.size()); - outBitStream->Write(musicCue.result); - outBitStream->Write(musicCue.boredomTime); +void SoundTriggerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { + outBitStream->Write(this->m_Dirty || bIsInitialUpdate); + if (this->m_Dirty || bIsInitialUpdate) { + outBitStream->Write(this->m_MusicCues.size()); + for (auto& musicCue : this->m_MusicCues) { + musicCue.Serialize(outBitStream); } - // Unknown part - outBitStream->Write(0); + outBitStream->Write(this->m_MusicParameters.size()); + for (auto& musicParam : this->m_MusicParameters) { + musicParam.Serialize(outBitStream); + } - // GUID part - outBitStream->Write(this->guids.size()); + outBitStream->Write(this->m_2DAmbientSounds.size()); + for (auto twoDAmbientSound : this->m_2DAmbientSounds) { + twoDAmbientSound.Serialize(outBitStream); + } - for (const auto guid : this->guids) { - outBitStream->Write(guid.GetData1()); - outBitStream->Write(guid.GetData2()); - outBitStream->Write(guid.GetData3()); - for (const auto& guidSubPart : guid.GetData4()) { - outBitStream->Write(guidSubPart); - } - outBitStream->Write(1); // Unknown + outBitStream->Write(this->m_3DAmbientSounds.size()); + for (auto threeDAmbientSound : this->m_3DAmbientSounds) { + threeDAmbientSound.Serialize(outBitStream); } - // Mixer program part - outBitStream->Write(this->mixerPrograms.size()); - for (const auto& mixerProgram : mixerPrograms) { - outBitStream->Write(mixerProgram.size()); - outBitStream->Write(mixerProgram.c_str(), mixerProgram.size()); - outBitStream->Write(1); // Unknown + outBitStream->Write(this->m_MixerPrograms.size()); + for (auto& mixerProgram : this->m_MixerPrograms) { + mixerProgram.Serialize(outBitStream); } - dirty = false; + if (!bIsInitialUpdate) this->m_Dirty = false; } } -void SoundTriggerComponent::ActivateMusicCue(const std::string& name) { - if (std::find_if(this->musicCues.begin(), this->musicCues.end(), [name](const MusicCue& musicCue) { +void SoundTriggerComponent::ActivateMusicCue(const std::string& name, float bordemTime) { + const auto musicCue = std::find_if(this->m_MusicCues.begin(), this->m_MusicCues.end(), [name](const MusicCue& musicCue) { return musicCue.name == name; - }) == this->musicCues.end()) { - this->musicCues.push_back({ - name, - 1, - -1.0f - }); - dirty = true; + } + ); + + if (musicCue == this->m_MusicCues.end()) { + this->m_MusicCues.push_back(MusicCue(name, bordemTime)); + this->m_Dirty = true; Game::entityManager->SerializeEntity(m_Parent); } } void SoundTriggerComponent::DeactivateMusicCue(const std::string& name) { - const auto musicCue = std::find_if(this->musicCues.begin(), this->musicCues.end(), [name](const MusicCue& musicCue) { + const auto musicCue = std::find_if(this->m_MusicCues.begin(), this->m_MusicCues.end(), [name](const MusicCue& musicCue) { return musicCue.name == name; - }); + } + ); - if (musicCue != this->musicCues.end()) { - this->musicCues.erase(musicCue); - dirty = true; + if (musicCue != this->m_MusicCues.end()) { + this->m_MusicCues.erase(musicCue); + this->m_Dirty = true; Game::entityManager->SerializeEntity(m_Parent); } } diff --git a/dGame/dComponents/SoundTriggerComponent.h b/dGame/dComponents/SoundTriggerComponent.h index 954d8495e..3873d6ed2 100644 --- a/dGame/dComponents/SoundTriggerComponent.h +++ b/dGame/dComponents/SoundTriggerComponent.h @@ -5,55 +5,72 @@ #include "Component.h" #include "eReplicaComponentType.h" -/** - * Music that should be played by the client - */ struct MusicCue { std::string name; uint32_t result; float boredomTime; + + MusicCue(std::string name, float boredomTime = -1.0, uint32_t result = 1){ + this->name = name; + this->result = result; + this->boredomTime = boredomTime; + }; + + void Serialize(RakNet::BitStream* outBitStream); }; -/** - * Handles specific music triggers like the instruments in Red Block - * Credits to https://github.com/SimonNitzsche/OpCrux-Server/blob/master/src/Entity/Components/SoundTriggerComponent.hpp - */ -class SoundTriggerComponent : public Component { -public: - static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER; +struct MusicParameter { + std::string name; + float value; - explicit SoundTriggerComponent(Entity* parent); - ~SoundTriggerComponent() override; + MusicParameter(std::string name, float value = 0.0){ + this->name = name; + this->value = value; + } + + void Serialize(RakNet::BitStream* outBitStream); +}; + +struct GUIDResults{ + GUID guid; + uint32_t result; + + GUIDResults(std::string guidString, uint32_t result = 1){ + this->guid = GUID(guidString); + this->result = result; + } - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream); +}; + +struct MixerProgram{ + std::string name; + uint32_t result; + + MixerProgram(std::string name, uint32_t result = 0){ + this->name = name; + this->result = result; + } + + void Serialize(RakNet::BitStream* outBitStream); +}; - /** - * Activates a music cue, making it played by any client in range - * @param name the name of the music to play - */ - void ActivateMusicCue(const std::string& name); - /** - * Deactivates a music cue (if active) - * @param name name of the music to deactivate - */ +class SoundTriggerComponent : public Component { +public: + static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER; + explicit SoundTriggerComponent(Entity* parent); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; + void ActivateMusicCue(const std::string& name, float bordemTime = -1.0); void DeactivateMusicCue(const std::string& name); private: - /** - * Currently active cues - */ - std::vector musicCues = {}; - - /** - * Currently active mixer programs - */ - std::vector mixerPrograms = {}; - - /** - * GUID found in the LDF - */ - std::vector guids = {}; - bool dirty = false; + std::vector m_MusicCues = {}; + std::vector m_MusicParameters = {}; + std::vector m_2DAmbientSounds = {}; + std::vector m_3DAmbientSounds = {}; + std::vector m_MixerPrograms = {}; + + bool m_Dirty = false; }; diff --git a/dGame/dComponents/SwitchComponent.cpp b/dGame/dComponents/SwitchComponent.cpp index eee543421..41dff9f5d 100644 --- a/dGame/dComponents/SwitchComponent.cpp +++ b/dGame/dComponents/SwitchComponent.cpp @@ -21,7 +21,7 @@ SwitchComponent::~SwitchComponent() { } } -void SwitchComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void SwitchComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_Active); } diff --git a/dGame/dComponents/SwitchComponent.h b/dGame/dComponents/SwitchComponent.h index fde3cfc0e..f262f44c8 100644 --- a/dGame/dComponents/SwitchComponent.h +++ b/dGame/dComponents/SwitchComponent.h @@ -25,7 +25,7 @@ class SwitchComponent : public Component { Entity* GetParentEntity() const; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Sets whether the switch is on or off. diff --git a/dGame/dComponents/VehiclePhysicsComponent.cpp b/dGame/dComponents/VehiclePhysicsComponent.cpp index 684b135bd..79b6cc829 100644 --- a/dGame/dComponents/VehiclePhysicsComponent.cpp +++ b/dGame/dComponents/VehiclePhysicsComponent.cpp @@ -72,7 +72,7 @@ void VehiclePhysicsComponent::SetDirtyAngularVelocity(bool val) { m_DirtyAngularVelocity = val; } -void VehiclePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void VehiclePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(bIsInitialUpdate || m_DirtyPosition); if (bIsInitialUpdate || m_DirtyPosition) { diff --git a/dGame/dComponents/VehiclePhysicsComponent.h b/dGame/dComponents/VehiclePhysicsComponent.h index e314bef14..602fc1358 100644 --- a/dGame/dComponents/VehiclePhysicsComponent.h +++ b/dGame/dComponents/VehiclePhysicsComponent.h @@ -33,7 +33,7 @@ class VehiclePhysicsComponent : public Component { VehiclePhysicsComponent(Entity* parentEntity); ~VehiclePhysicsComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index 288c046d2..e6f992452 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -1,26 +1,28 @@ #include "VendorComponent.h" - -#include - -#include "Game.h" +#include "BitStream.h" #include "dServer.h" - +#include "dZoneManager.h" +#include "WorldConfig.h" #include "CDComponentsRegistryTable.h" #include "CDVendorComponentTable.h" #include "CDLootMatrixTable.h" #include "CDLootTableTable.h" +#include "CDItemComponentTable.h" VendorComponent::VendorComponent(Entity* parent) : Component(parent) { + m_HasStandardCostItems = false; + m_HasMultiCostItems = false; SetupConstants(); RefreshInventory(true); } -VendorComponent::~VendorComponent() = default; - -void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - outBitStream->Write1(); - outBitStream->Write1(); // Has standard items (Required for vendors with missions.) - outBitStream->Write(HasCraftingStation()); // Has multi use items +void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { + outBitStream->Write(bIsInitialUpdate || m_DirtyVendor); + if (bIsInitialUpdate || m_DirtyVendor) { + outBitStream->Write(m_HasStandardCostItems); + outBitStream->Write(m_HasMultiCostItems); + if (!bIsInitialUpdate) m_DirtyVendor = false; + } } void VendorComponent::OnUse(Entity* originator) { @@ -28,96 +30,73 @@ void VendorComponent::OnUse(Entity* originator) { GameMessages::SendVendorStatusUpdate(m_Parent, originator->GetSystemAddress()); } -float VendorComponent::GetBuyScalar() const { - return m_BuyScalar; -} - -float VendorComponent::GetSellScalar() const { - return m_SellScalar; -} - -void VendorComponent::SetBuyScalar(float value) { - m_BuyScalar = value; -} - -void VendorComponent::SetSellScalar(float value) { - m_SellScalar = value; -} - -std::map& VendorComponent::GetInventory() { - return m_Inventory; -} - -bool VendorComponent::HasCraftingStation() { - // As far as we know, only Umami has a crafting station - return m_Parent->GetLOT() == 13800; -} - void VendorComponent::RefreshInventory(bool isCreation) { - //Custom code for Max vanity NPC - if (m_Parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { - if (!isCreation) return; - m_Inventory.insert({ 11909, 0 }); //Top hat w frog - m_Inventory.insert({ 7785, 0 }); //Flash bulb - m_Inventory.insert({ 12764, 0 }); //Big fountain soda - m_Inventory.insert({ 12241, 0 }); //Hot cocoa (from fb) + SetHasStandardCostItems(false); + SetHasMultiCostItems(false); + m_Inventory.clear(); + + // Custom code for Max vanity NPC and Mr.Ree cameras + if(isCreation && m_Parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { + SetupMaxCustomVendor(); return; } - m_Inventory.clear(); + auto* lootMatrixTable = CDClientManager::Instance().GetTable(); const auto& lootMatrices = lootMatrixTable->GetMatrix(m_LootMatrixID); if (lootMatrices.empty()) return; - // Done with lootMatrix table auto* lootTableTable = CDClientManager::Instance().GetTable(); + auto* itemComponentTable = CDClientManager::Instance().GetTable(); + auto* compRegistryTable = CDClientManager::Instance().GetTable(); for (const auto& lootMatrix : lootMatrices) { auto vendorItems = lootTableTable->GetTable(lootMatrix.LootTableIndex); if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) { - for (CDLootTable item : vendorItems) { - m_Inventory.insert({ item.itemid, item.sortPriority }); + for (const auto& item : vendorItems) { + if (!m_HasStandardCostItems || !m_HasMultiCostItems) { + auto itemComponentID = compRegistryTable->GetByIDAndType(item.itemid, eReplicaComponentType::ITEM, -1); + if (itemComponentID == -1) { + Game::logger->Log("VendorComponent", "Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT()); + continue; + } + auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID); + if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true); + if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true); + } + m_Inventory.push_back(SoldItem(item.itemid, item.sortPriority)); } } else { auto randomCount = GeneralUtils::GenerateRandomNumber(lootMatrix.minToDrop, lootMatrix.maxToDrop); for (size_t i = 0; i < randomCount; i++) { if (vendorItems.empty()) break; - auto randomItemIndex = GeneralUtils::GenerateRandomNumber(0, vendorItems.size() - 1); - - const auto& randomItem = vendorItems[randomItemIndex]; - + const auto& randomItem = vendorItems.at(randomItemIndex); vendorItems.erase(vendorItems.begin() + randomItemIndex); - - m_Inventory.insert({ randomItem.itemid, randomItem.sortPriority }); + if (!m_HasStandardCostItems || !m_HasMultiCostItems) { + auto itemComponentID = compRegistryTable->GetByIDAndType(randomItem.itemid, eReplicaComponentType::ITEM, -1); + if (itemComponentID == -1) { + Game::logger->Log("VendorComponent", "Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT()); + continue; + } + auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID); + if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true); + if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true); + } + m_Inventory.push_back(SoldItem(randomItem.itemid, randomItem.sortPriority)); } } } - - //Because I want a vendor to sell these cameras - if (m_Parent->GetLOT() == 13569) { - auto randomCamera = GeneralUtils::GenerateRandomNumber(0, 2); - - switch (randomCamera) { - case 0: - m_Inventory.insert({ 16253, 0 }); //Grungagroid - break; - case 1: - m_Inventory.insert({ 16254, 0 }); //Hipstabrick - break; - case 2: - m_Inventory.insert({ 16204, 0 }); //Megabrixel snapshot - break; - default: - break; - } - } + HandleMrReeCameras(); // Callback timer to refresh this inventory. - m_Parent->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { - RefreshInventory(); + if (m_RefreshTimeSeconds > 0.0) { + m_Parent->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { + RefreshInventory(); }); + } + Game::entityManager->SerializeEntity(m_Parent); GameMessages::SendVendorStatusUpdate(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); } @@ -128,12 +107,47 @@ void VendorComponent::SetupConstants() { auto* vendorComponentTable = CDClientManager::Instance().GetTable(); std::vector vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); }); if (vendorComps.empty()) return; - m_BuyScalar = vendorComps[0].buyScalar; - m_SellScalar = vendorComps[0].sellScalar; - m_RefreshTimeSeconds = vendorComps[0].refreshTimeSeconds; - m_LootMatrixID = vendorComps[0].LootMatrixIndex; + auto vendorData = vendorComps.at(0); + if (vendorData.buyScalar == 0.0) m_BuyScalar = Game::zoneManager->GetWorldConfig()->vendorBuyMultiplier; + else m_BuyScalar = vendorData.buyScalar; + m_SellScalar = vendorData.sellScalar; + m_RefreshTimeSeconds = vendorData.refreshTimeSeconds; + m_LootMatrixID = vendorData.LootMatrixIndex; } bool VendorComponent::SellsItem(const LOT item) const { - return m_Inventory.find(item) != m_Inventory.end(); + return std::count_if(m_Inventory.begin(), m_Inventory.end(), [item](const SoldItem& lhs) { + return lhs.lot == item; + }) > 0; +} + + +void VendorComponent::SetupMaxCustomVendor(){ + SetHasStandardCostItems(true); + m_Inventory.push_back(SoldItem(11909, 0)); // Top hat w frog + m_Inventory.push_back(SoldItem(7785, 0)); // Flash bulb + m_Inventory.push_back(SoldItem(12764, 0)); // Big fountain soda + m_Inventory.push_back(SoldItem(12241, 0)); // Hot cocoa (from fb) +} + +void VendorComponent::HandleMrReeCameras(){ + if (m_Parent->GetLOT() == 13569) { + SetHasStandardCostItems(true); + auto randomCamera = GeneralUtils::GenerateRandomNumber(0, 2); + + LOT camera = 0; + DluAssert(randomCamera >= 0 && randomCamera <= 2); + switch (randomCamera) { + case 0: + camera = 16253; // Grungagroid + break; + case 1: + camera = 16254; // Hipstabrick + break; + case 2: + camera = 16204; // Megabrixel snapshot + break; + } + m_Inventory.push_back(SoldItem(camera, 0)); + } } diff --git a/dGame/dComponents/VendorComponent.h b/dGame/dComponents/VendorComponent.h index cbff0cfdb..7924a9285 100644 --- a/dGame/dComponents/VendorComponent.h +++ b/dGame/dComponents/VendorComponent.h @@ -9,91 +9,56 @@ #include "RakNetTypes.h" #include "eReplicaComponentType.h" -/** - * A component for vendor NPCs. A vendor sells items to the player. - */ +struct SoldItem { + SoldItem(const LOT lot, const int32_t sortPriority) { + this->lot = lot; + this->sortPriority = sortPriority; + }; + LOT lot = 0; + int32_t sortPriority = 0; +}; + class VendorComponent : public Component { public: - static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR; - + inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR; VendorComponent(Entity* parent); - ~VendorComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void OnUse(Entity* originator) override; - - /** - * Gets the buy scaler - * @return the buy scaler - */ - float GetBuyScalar() const; - - /** - * Sets the buy scalar. - * @param value the new value. - */ - void SetBuyScalar(float value); - - /** - * Gets the buy scaler - * @return the buy scaler - */ - float GetSellScalar() const; - - /** - * Sets the sell scalar. - * @param value the new value. - */ - void SetSellScalar(float value); - - /** - * True if the NPC LOT is 13800, the only NPC with a crafting station. - */ - bool HasCraftingStation(); - - /** - * Gets the list if items the vendor sells. - * @return the list of items. - */ - std::map& GetInventory(); - - /** - * Refresh the inventory of this vendor. - */ void RefreshInventory(bool isCreation = false); - - /** - * Called on startup of vendor to setup the variables for the component. - */ void SetupConstants(); - bool SellsItem(const LOT item) const; -private: - /** - * The buy scalar. - */ - float m_BuyScalar; + float GetBuyScalar() const { return m_BuyScalar; } + float GetSellScalar() const { return m_SellScalar; } + void SetBuyScalar(const float value) { m_BuyScalar = value; } + void SetSellScalar(const float value) { m_SellScalar = value; } + const std::vector& GetInventory() { return m_Inventory; } - /** - * The sell scalar. - */ - float m_SellScalar; + void SetHasMultiCostItems(const bool hasMultiCostItems) { + if (m_HasMultiCostItems == hasMultiCostItems) return; + m_HasMultiCostItems = hasMultiCostItems; + m_DirtyVendor = true; + } - /** - * The refresh time of this vendors' inventory. - */ - float m_RefreshTimeSeconds; + void SetHasStandardCostItems(const bool hasStandardCostItems) { + if (m_HasStandardCostItems == hasStandardCostItems) return; + m_HasStandardCostItems = hasStandardCostItems; + m_DirtyVendor = true; + } - /** - * Loot matrix id of this vendor. - */ - uint32_t m_LootMatrixID; - /** - * The list of items the vendor sells. - */ - std::map m_Inventory; +private: + void SetupMaxCustomVendor(); + void HandleMrReeCameras(); + float m_BuyScalar = 0.0f; + float m_SellScalar = 0.0f; + float m_RefreshTimeSeconds = 0.0f; + uint32_t m_LootMatrixID = 0; + std::vector m_Inventory; + bool m_DirtyVendor = false; + bool m_HasStandardCostItems = false; + bool m_HasMultiCostItems = false; }; #endif // VENDORCOMPONENT_H diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 83005b6fb..b2af8ca79 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -5,7 +5,7 @@ #include "GameMessageHandler.h" #include "MissionComponent.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "dServer.h" #include "../thirdparty/raknet/Source/RakNetworkFactory.h" #include @@ -48,10 +48,11 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System if (!entity) { Game::logger->Log("GameMessageHandler", "Failed to find associated entity (%llu), aborting GM (%X)!", objectID, messageID); - return; } + if (messageID != eGameMessageType::READY_FOR_UPDATES) Game::logger->LogDebug("GameMessageHandler", "received game message ID: %i", messageID); + switch (messageID) { case eGameMessageType::UN_USE_BBB_MODEL: { @@ -73,11 +74,11 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System break; } - case eGameMessageType::EQUIP_ITEM: + case eGameMessageType::EQUIP_INVENTORY: GameMessages::HandleEquipItem(inStream, entity); break; - case eGameMessageType::UN_EQUIP_ITEM: + case eGameMessageType::UN_EQUIP_INVENTORY: GameMessages::HandleUnequipItem(inStream, entity); break; @@ -252,7 +253,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System }*/ break; } - case eGameMessageType::HANDLE_HOT_PROPERTY_DATA: { + case eGameMessageType::GET_HOT_PROPERTY_DATA: { GameMessages::HandleGetHotPropertyData(inStream, entity, sysAddr); break; } @@ -314,7 +315,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System if (success) { //Broadcast our startSkill: RakNet::BitStream bitStreamLocal; - PacketUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); + BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); bitStreamLocal.Write(entity->GetObjectID()); EchoStartSkill echoStartSkill; @@ -336,7 +337,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case eGameMessageType::SYNC_SKILL: { RakNet::BitStream bitStreamLocal; - PacketUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); + BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); bitStreamLocal.Write(entity->GetObjectID()); //bitStreamLocal.Write((unsigned short)eGameMessageType::ECHO_SYNC_SKILL); //bitStreamLocal.Write(inStream); @@ -547,7 +548,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System GameMessages::HandleBBBSaveRequest(inStream, entity, sysAddr); break; - case eGameMessageType::CONTROL_BEHAVIOR: + case eGameMessageType::CONTROL_BEHAVIORS: GameMessages::HandleControlBehaviors(inStream, entity, sysAddr); break; @@ -596,11 +597,11 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System GameMessages::HandleRequestDie(inStream, entity, sysAddr); break; - case eGameMessageType::VEHICLE_NOTIFY_SERVER_ADD_PASSIVE_BOOST_ACTION: + case eGameMessageType::NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION: GameMessages::HandleVehicleNotifyServerAddPassiveBoostAction(inStream, entity, sysAddr); break; - case eGameMessageType::VEHICLE_NOTIFY_SERVER_REMOVE_PASSIVE_BOOST_ACTION: + case eGameMessageType::NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION: GameMessages::HandleVehicleNotifyServerRemovePassiveBoostAction(inStream, entity, sysAddr); break; @@ -668,7 +669,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case eGameMessageType::DISMOUNT_COMPLETE: GameMessages::HandleDismountComplete(inStream, entity, sysAddr); break; - case eGameMessageType::DEACTIVATE_BUBBLE_BUFF: + case eGameMessageType::DECTIVATE_BUBBLE_BUFF: GameMessages::HandleDeactivateBubbleBuff(inStream, entity); break; case eGameMessageType::ACTIVATE_BUBBLE_BUFF: @@ -680,8 +681,20 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case eGameMessageType::REQUEST_ACTIVITY_EXIT: GameMessages::HandleRequestActivityExit(inStream, entity); break; + case eGameMessageType::ADD_DONATION_ITEM: + GameMessages::HandleAddDonationItem(inStream, entity, sysAddr); + break; + case eGameMessageType::REMOVE_DONATION_ITEM: + GameMessages::HandleRemoveDonationItem(inStream, entity, sysAddr); + break; + case eGameMessageType::CONFIRM_DONATION_ON_PLAYER: + GameMessages::HandleConfirmDonationOnPlayer(inStream, entity); + break; + case eGameMessageType::CANCEL_DONATION_ON_PLAYER: + GameMessages::HandleCancelDonationOnPlayer(inStream, entity); + break; default: - // Game::logger->Log("GameMessageHandler", "Unknown game message ID: %i", messageID); + Game::logger->LogDebug("GameMessageHandler", "Unknown game message ID: %i", messageID); break; } } diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 8d8085a9e..83f832b2b 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2,6 +2,7 @@ #include "User.h" #include "Entity.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "BitStream.h" #include "Game.h" #include "SlashCommandHandler.h" @@ -24,7 +25,7 @@ #include "dConfig.h" #include "TeamManager.h" #include "ChatPackets.h" -#include "RocketLaunchLupComponent.h" +#include "MultiZoneEntranceComponent.h" #include "eUnequippableActiveType.h" #include "eMovementPlatformState.h" #include "LeaderboardManager.h" @@ -76,6 +77,7 @@ #include "RacingControlComponent.h" #include "RailActivatorComponent.h" #include "LevelProgressionComponent.h" +#include "DonationVendorComponent.h" // Message includes: #include "dZoneManager.h" @@ -172,7 +174,7 @@ void GameMessages::SendPlayAnimation(Entity* entity, const std::u16string& anima bitStream.Write(eGameMessageType::PLAY_ANIMATION); bitStream.Write(animationIDLength); - PacketUtils::WriteWString(bitStream, animationName, animationIDLength); + bitStream.Write(LUWString(animationName, animationIDLength)); bitStream.Write(bExpectAnimToExist); @@ -325,13 +327,6 @@ void GameMessages::SendPlayNDAudioEmitter(Entity* entity, const SystemAddress& s bitStream.Write(static_cast(audioGUID[k])); } - //PacketUtils::WriteString(bitStream, audioGUID, audioGUID.size()); - - //bitStream.Write(uint32_t(audioGUID.size())); - //for (char character : audioGUID) { - // bitStream.Write(character); - //} - bitStream.Write(uint32_t(0)); bitStream.Write0(); bitStream.Write0(); @@ -974,7 +969,7 @@ void GameMessages::SendStop2DAmbientSound(Entity* entity, bool force, std::strin CMSGHEADER; bitStream.Write(entity->GetObjectID()); - bitStream.Write((uint16_t)eGameMessageType::PLAY2_DAMBIENT_SOUND); + bitStream.Write((uint16_t)eGameMessageType::STOP2_D_AMBIENT_SOUND); uint32_t audioGUIDSize = audioGUID.size(); @@ -997,7 +992,7 @@ void GameMessages::SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, CMSGHEADER; bitStream.Write(entity->GetObjectID()); - bitStream.Write((uint16_t)eGameMessageType::PLAY2_DAMBIENT_SOUND); + bitStream.Write((uint16_t)eGameMessageType::PLAY2_D_AMBIENT_SOUND); uint32_t audioGUIDSize = audioGUID.size(); @@ -1016,7 +1011,7 @@ void GameMessages::SendSetNetworkScriptVar(Entity* entity, const SystemAddress& CMSGHEADER; bitStream.Write(entity->GetObjectID()); - bitStream.Write((uint16_t)eGameMessageType::SET_NETWORK_SCRIPT_VAR); + bitStream.Write((uint16_t)eGameMessageType::SCRIPT_NETWORK_VAR_UPDATE); // FIXME: this is a bad place to need to do a conversion because we have no clue whether data is utf8 or plain ascii // an this has performance implications @@ -1286,21 +1281,22 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s VendorComponent* vendor = static_cast(entity->GetComponent(eReplicaComponentType::VENDOR)); if (!vendor) return; - std::map vendorItems = vendor->GetInventory(); + auto vendorItems = vendor->GetInventory(); bitStream.Write(entity->GetObjectID()); bitStream.Write(eGameMessageType::VENDOR_STATUS_UPDATE); bitStream.Write(bUpdateOnly); - bitStream.Write(static_cast(vendorItems.size())); + bitStream.Write(vendorItems.size()); - for (std::pair item : vendorItems) { - bitStream.Write(static_cast(item.first)); - bitStream.Write(static_cast(item.second)); + + for (const auto& item : vendorItems) { + bitStream.Write(item.lot); + bitStream.Write(item.sortPriority); } - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST - SEND_PACKET; + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; } void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr) { @@ -2115,7 +2111,7 @@ void GameMessages::SendUGCEquipPreCreateBasedOnEditMode(LWOOBJID objectId, const CMSGHEADER; bitStream.Write(objectId); - bitStream.Write(eGameMessageType::HANDLE_UGC_EQUIP_PRE_CREATE_BASED_ON_EDIT_MODE); + bitStream.Write(eGameMessageType::HANDLE_UGC_POST_CREATE_BASED_ON_EDIT_MODE); bitStream.Write(modelCount); bitStream.Write(model); @@ -2129,7 +2125,7 @@ void GameMessages::SendUGCEquipPostDeleteBasedOnEditMode(LWOOBJID objectId, cons CMSGHEADER; bitStream.Write(objectId); - bitStream.Write(eGameMessageType::HANDLE_UGC_EQUIP_POST_DELETE_BASED_ON_EDIT_MODE); + bitStream.Write(eGameMessageType::HANDLE_UGC_POST_DELETE_BASED_ON_EDIT_MODE); bitStream.Write(inventoryItem); @@ -2179,7 +2175,7 @@ void GameMessages::HandleUnUseModel(RakNet::BitStream* inStream, Entity* entity, if (unknown) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); bitStream.Write(LWOOBJID_EMPTY); //always zero so that a check on the client passes bitStream.Write(eBlueprintSaveResponseType::PlacementFailed); // Sending a non-zero error code here prevents the client from deleting its in progress build for some reason? bitStream.Write(0); @@ -2431,7 +2427,7 @@ void GameMessages::HandleBBBLoadItemRequest(RakNet::BitStream* inStream, Entity* void GameMessages::SendBlueprintLoadItemResponse(const SystemAddress& sysAddr, bool success, LWOOBJID oldItemId, LWOOBJID newItemId) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_LOAD_RESPONSE_ITEMID); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_LOAD_RESPONSE_ITEMID); bitStream.Write(static_cast(success)); bitStream.Write(oldItemId); bitStream.Write(newItemId); @@ -2458,7 +2454,7 @@ void GameMessages::SendUnSmash(Entity* entity, LWOOBJID builderID, float duratio CMSGHEADER; bitStream.Write(entity->GetObjectID()); - bitStream.Write(eGameMessageType::UNSMASH); + bitStream.Write(eGameMessageType::UN_SMASH); bitStream.Write(builderID != LWOOBJID_EMPTY); if (builderID != LWOOBJID_EMPTY) bitStream.Write(builderID); @@ -2679,7 +2675,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent //Tell the client their model is saved: (this causes us to actually pop out of our current state): CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); bitStream.Write(localId); bitStream.Write(eBlueprintSaveResponseType::EverythingWorked); bitStream.Write(1); @@ -2793,9 +2789,9 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti return; } - auto rocketLaunchLupComponent = entity->GetComponent(); - if (rocketLaunchLupComponent != nullptr) { - rocketLaunchLupComponent->OnSelectWorld(player, index); + auto multiZoneEntranceComponent = entity->GetComponent(); + if (multiZoneEntranceComponent != nullptr) { + multiZoneEntranceComponent->OnSelectWorld(player, index); } } @@ -3461,7 +3457,7 @@ void GameMessages::SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, const st CMSGHEADER; bitStream.Write(objectId); - bitStream.Write(eGameMessageType::NOTIFY_PET_TAMING_PUZZLE_SELECTED); + bitStream.Write(eGameMessageType::NOTIFY_TAMING_PUZZLE_SELECTED); bitStream.Write(static_cast(bricks.size())); for (const auto& brick : bricks) { @@ -6207,3 +6203,104 @@ void GameMessages::HandleRequestActivityExit(RakNet::BitStream* inStream, Entity if (!entity || !player) return; entity->RequestActivityExit(entity, player_id, canceled); } + +void GameMessages::HandleAddDonationItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { + uint32_t count = 1; + bool hasCount = false; + inStream->Read(hasCount); + if (hasCount) inStream->Read(count); + LWOOBJID itemId = LWOOBJID_EMPTY; + inStream->Read(itemId); + if (!itemId) return; + + auto* donationVendorComponent = entity->GetComponent(); + if (!donationVendorComponent) return; + if (donationVendorComponent->GetActivityID() == 0) { + Game::logger->Log("GameMessages", "WARNING: Trying to dontate to a vendor with no activity"); + return; + } + User* user = UserManager::Instance()->GetUser(sysAddr); + if (!user) return; + Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar()); + if (!player) return; + auto* characterComponent = player->GetComponent(); + if (!characterComponent) return; + auto* inventoryComponent = player->GetComponent(); + if (!inventoryComponent) return; + Item* item = inventoryComponent->FindItemById(itemId); + if (!item) return; + if (item->GetCount() < count) return; + characterComponent->SetCurrentInteracting(entity->GetObjectID()); + inventoryComponent->MoveItemToInventory(item, eInventoryType::DONATION, count, true, false, true); +} + +void GameMessages::HandleRemoveDonationItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { + bool confirmed = false; + inStream->Read(confirmed); + uint32_t count = 1; + bool hasCount = false; + inStream->Read(hasCount); + if (hasCount) inStream->Read(count); + LWOOBJID itemId = LWOOBJID_EMPTY; + inStream->Read(itemId); + if (!itemId) return; + + User* user = UserManager::Instance()->GetUser(sysAddr); + if (!user) return; + Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar()); + if (!player) return; + + auto* inventoryComponent = player->GetComponent(); + if (!inventoryComponent) return; + + Item* item = inventoryComponent->FindItemById(itemId); + if (!item) return; + if (item->GetCount() < count) return; + inventoryComponent->MoveItemToInventory(item, eInventoryType::BRICKS, count, true, false, true); +} + +void GameMessages::HandleConfirmDonationOnPlayer(RakNet::BitStream* inStream, Entity* entity) { + auto* inventoryComponent = entity->GetComponent(); + if (!inventoryComponent) return; + auto* missionComponent = entity->GetComponent(); + if (!missionComponent) return; + auto* characterComponent = entity->GetComponent(); + if (!characterComponent || !characterComponent->GetCurrentInteracting()) return; + auto* donationEntity = Game::entityManager->GetEntity(characterComponent->GetCurrentInteracting()); + if (!donationEntity) return; + auto* donationVendorComponent = donationEntity->GetComponent(); + if(!donationVendorComponent) return; + if (donationVendorComponent->GetActivityID() == 0) { + Game::logger->Log("GameMessages", "WARNING: Trying to dontate to a vendor with no activity"); + return; + } + auto* inventory = inventoryComponent->GetInventory(eInventoryType::DONATION); + if (!inventory) return; + auto items = inventory->GetItems(); + if (!items.empty()) { + uint32_t count = 0; + for (auto& [itemID, item] : items){ + count += item->GetCount(); + item->RemoveFromInventory(); + } + missionComponent->Progress(eMissionTaskType::DONATION, 0, LWOOBJID_EMPTY, "", count); + LeaderboardManager::SaveScore(entity->GetObjectID(), donationVendorComponent->GetActivityID(), count); + donationVendorComponent->SubmitDonation(count); + Game::entityManager->SerializeEntity(donationEntity); + } + characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY); +} + +void GameMessages::HandleCancelDonationOnPlayer(RakNet::BitStream* inStream, Entity* entity) { + auto* inventoryComponent = entity->GetComponent(); + if (!inventoryComponent) return; + auto* inventory = inventoryComponent->GetInventory(eInventoryType::DONATION); + if (!inventory) return; + auto items = inventory->GetItems(); + for (auto& [itemID, item] : items){ + inventoryComponent->MoveItemToInventory(item, eInventoryType::BRICKS, item->GetCount(), false, false, true); + } + auto* characterComponent = entity->GetComponent(); + if (!characterComponent) return; + characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY); +} diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index bd1224d3b..3a9963b47 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -649,6 +649,12 @@ namespace GameMessages { void HandleZoneSummaryDismissed(RakNet::BitStream* inStream, Entity* entity); void HandleRequestActivityExit(RakNet::BitStream* inStream, Entity* entity); + + // Donation vendor + void HandleAddDonationItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void HandleRemoveDonationItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void HandleConfirmDonationOnPlayer(RakNet::BitStream* inStream, Entity* entity); + void HandleCancelDonationOnPlayer(RakNet::BitStream* inStream, Entity* entity); }; #endif // GAMEMESSAGES_H diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 34641335a..085fc38b5 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -42,9 +42,10 @@ Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) { auto* missionsTable = CDClientManager::Instance().GetTable(); - info = missionsTable->GetPtrByMissionID(missionId); + auto* mis = missionsTable->GetPtrByMissionID(missionId); + info = *mis; - if (info == &CDMissionsTable::Default) { + if (mis == &CDMissionsTable::Default) { Game::logger->Log("Missions", "Failed to find mission (%i)!", missionId); return; @@ -137,7 +138,7 @@ void Mission::UpdateXml(tinyxml2::XMLElement* element) { element->DeleteChildren(); - element->SetAttribute("id", static_cast(info->id)); + element->SetAttribute("id", static_cast(info.id)); if (m_Completions > 0) { element->SetAttribute("cct", static_cast(m_Completions)); @@ -212,11 +213,11 @@ User* Mission::GetUser() const { } uint32_t Mission::GetMissionId() const { - return info->id; + return info.id; } const CDMissions& Mission::GetClientInfo() const { - return *info; + return info; } uint32_t Mission::GetCompletions() const { @@ -240,15 +241,15 @@ eMissionState Mission::GetMissionState() const { } bool Mission::IsAchievement() const { - return !info->isMission; + return !info.isMission; } bool Mission::IsMission() const { - return info->isMission; + return info.isMission; } bool Mission::IsRepeatable() const { - return info->repeatable; + return info.repeatable; } bool Mission::IsComplete() const { @@ -284,7 +285,7 @@ void Mission::MakeAvalible() { } void Mission::Accept() { - SetMissionTypeState(eMissionLockState::NEW, info->defined_type, info->defined_subtype); + SetMissionTypeState(eMissionLockState::NEW, info.defined_type, info.defined_subtype); SetMissionState(m_Completions > 0 ? eMissionState::COMPLETE_ACTIVE : eMissionState::ACTIVE); @@ -321,16 +322,16 @@ void Mission::Complete(const bool yieldRewards) { auto* characterComponent = entity->GetComponent(); if (characterComponent != nullptr) { - characterComponent->TrackMissionCompletion(!info->isMission); + characterComponent->TrackMissionCompletion(!info.isMission); } auto* missionComponent = entity->GetComponent(); - missionComponent->Progress(eMissionTaskType::META, info->id); + missionComponent->Progress(eMissionTaskType::META, info.id); - missionComponent->Progress(eMissionTaskType::RACING, info->id, (LWOOBJID)eRacingTaskParam::COMPLETE_ANY_RACING_TASK); + missionComponent->Progress(eMissionTaskType::RACING, info.id, (LWOOBJID)eRacingTaskParam::COMPLETE_ANY_RACING_TASK); - missionComponent->Progress(eMissionTaskType::RACING, info->id, (LWOOBJID)eRacingTaskParam::COMPLETE_TRACK_TASKS); + missionComponent->Progress(eMissionTaskType::RACING, info.id, (LWOOBJID)eRacingTaskParam::COMPLETE_TRACK_TASKS); auto* missionEmailTable = CDClientManager::Instance().GetTable(); @@ -441,24 +442,24 @@ void Mission::YieldRewards() { } int32_t coinsToSend = 0; - if (info->LegoScore > 0) { - eLootSourceType lootSource = info->isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; + if (info.LegoScore > 0) { + eLootSourceType lootSource = info.isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; if (levelComponent->GetLevel() >= Game::zoneManager->GetWorldConfig()->levelCap) { // Since the character is at the level cap we reward them with coins instead of UScore. - coinsToSend += info->LegoScore * Game::zoneManager->GetWorldConfig()->levelCapCurrencyConversion; + coinsToSend += info.LegoScore * Game::zoneManager->GetWorldConfig()->levelCapCurrencyConversion; } else { - characterComponent->SetUScore(characterComponent->GetUScore() + info->LegoScore); - GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), info->LegoScore, lootSource); + characterComponent->SetUScore(characterComponent->GetUScore() + info.LegoScore); + GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), info.LegoScore, lootSource); } } if (m_Completions > 0) { std::vector> items; - items.emplace_back(info->reward_item1_repeatable, info->reward_item1_repeat_count); - items.emplace_back(info->reward_item2_repeatable, info->reward_item2_repeat_count); - items.emplace_back(info->reward_item3_repeatable, info->reward_item3_repeat_count); - items.emplace_back(info->reward_item4_repeatable, info->reward_item4_repeat_count); + items.emplace_back(info.reward_item1_repeatable, info.reward_item1_repeat_count); + items.emplace_back(info.reward_item2_repeatable, info.reward_item2_repeat_count); + items.emplace_back(info.reward_item3_repeatable, info.reward_item3_repeat_count); + items.emplace_back(info.reward_item4_repeatable, info.reward_item4_repeat_count); for (const auto& pair : items) { // Some missions reward zero of an item and so they must be allowed through this clause, @@ -478,9 +479,9 @@ void Mission::YieldRewards() { inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT); } - if (info->reward_currency_repeatable > 0 || coinsToSend > 0) { - eLootSourceType lootSource = info->isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; - character->SetCoins(character->GetCoins() + info->reward_currency_repeatable + coinsToSend, lootSource); + if (info.reward_currency_repeatable > 0 || coinsToSend > 0) { + eLootSourceType lootSource = info.isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; + character->SetCoins(character->GetCoins() + info.reward_currency_repeatable + coinsToSend, lootSource); } return; @@ -488,10 +489,10 @@ void Mission::YieldRewards() { std::vector> items; - items.emplace_back(info->reward_item1, info->reward_item1_count); - items.emplace_back(info->reward_item2, info->reward_item2_count); - items.emplace_back(info->reward_item3, info->reward_item3_count); - items.emplace_back(info->reward_item4, info->reward_item4_count); + items.emplace_back(info.reward_item1, info.reward_item1_count); + items.emplace_back(info.reward_item2, info.reward_item2_count); + items.emplace_back(info.reward_item3, info.reward_item3_count); + items.emplace_back(info.reward_item4, info.reward_item4_count); for (const auto& pair : items) { // Some missions reward zero of an item and so they must be allowed through this clause, @@ -511,58 +512,58 @@ void Mission::YieldRewards() { inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT); } - if (info->reward_currency > 0 || coinsToSend > 0) { - eLootSourceType lootSource = info->isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; - character->SetCoins(character->GetCoins() + info->reward_currency + coinsToSend, lootSource); + if (info.reward_currency > 0 || coinsToSend > 0) { + eLootSourceType lootSource = info.isMission ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT; + character->SetCoins(character->GetCoins() + info.reward_currency + coinsToSend, lootSource); } - if (info->reward_maxinventory > 0) { + if (info.reward_maxinventory > 0) { auto* inventory = inventoryComponent->GetInventory(ITEMS); - inventory->SetSize(inventory->GetSize() + info->reward_maxinventory); + inventory->SetSize(inventory->GetSize() + info.reward_maxinventory); } - if (info->reward_bankinventory > 0) { + if (info.reward_bankinventory > 0) { auto* inventory = inventoryComponent->GetInventory(eInventoryType::VAULT_ITEMS); auto modelInventory = inventoryComponent->GetInventory(eInventoryType::VAULT_MODELS); - inventory->SetSize(inventory->GetSize() + info->reward_bankinventory); - modelInventory->SetSize(modelInventory->GetSize() + info->reward_bankinventory); + inventory->SetSize(inventory->GetSize() + info.reward_bankinventory); + modelInventory->SetSize(modelInventory->GetSize() + info.reward_bankinventory); } - if (info->reward_reputation > 0) { - missionComponent->Progress(eMissionTaskType::EARN_REPUTATION, 0, 0L, "", info->reward_reputation); + if (info.reward_reputation > 0) { + missionComponent->Progress(eMissionTaskType::EARN_REPUTATION, 0, 0L, "", info.reward_reputation); auto character = entity->GetComponent(); if (character) { - character->SetReputation(character->GetReputation() + info->reward_reputation); + character->SetReputation(character->GetReputation() + info.reward_reputation); GameMessages::SendUpdateReputation(entity->GetObjectID(), character->GetReputation(), entity->GetSystemAddress()); } } - if (info->reward_maxhealth > 0) { - destroyableComponent->SetMaxHealth(destroyableComponent->GetMaxHealth() + static_cast(info->reward_maxhealth), true); + if (info.reward_maxhealth > 0) { + destroyableComponent->SetMaxHealth(destroyableComponent->GetMaxHealth() + static_cast(info.reward_maxhealth), true); } - if (info->reward_maximagination > 0) { - destroyableComponent->SetMaxImagination(destroyableComponent->GetMaxImagination() + static_cast(info->reward_maximagination), true); + if (info.reward_maximagination > 0) { + destroyableComponent->SetMaxImagination(destroyableComponent->GetMaxImagination() + static_cast(info.reward_maximagination), true); } Game::entityManager->SerializeEntity(entity); - if (info->reward_emote > 0) { - character->UnlockEmote(info->reward_emote); + if (info.reward_emote > 0) { + character->UnlockEmote(info.reward_emote); } - if (info->reward_emote2 > 0) { - character->UnlockEmote(info->reward_emote2); + if (info.reward_emote2 > 0) { + character->UnlockEmote(info.reward_emote2); } - if (info->reward_emote3 > 0) { - character->UnlockEmote(info->reward_emote3); + if (info.reward_emote3 > 0) { + character->UnlockEmote(info.reward_emote3); } - if (info->reward_emote4 > 0) { - character->UnlockEmote(info->reward_emote4); + if (info.reward_emote4 > 0) { + character->UnlockEmote(info.reward_emote4); } } @@ -599,7 +600,7 @@ void Mission::SetMissionState(const eMissionState state, const bool sendingRewar return; } - GameMessages::SendNotifyMission(entity, entity->GetParentUser()->GetSystemAddress(), info->id, static_cast(state), sendingRewards); + GameMessages::SendNotifyMission(entity, entity->GetParentUser()->GetSystemAddress(), info.id, static_cast(state), sendingRewards); } void Mission::SetMissionTypeState(eMissionLockState state, const std::string& type, const std::string& subType) { diff --git a/dGame/dMission/Mission.h b/dGame/dMission/Mission.h index b04c3548d..f7c17003c 100644 --- a/dGame/dMission/Mission.h +++ b/dGame/dMission/Mission.h @@ -245,7 +245,7 @@ class Mission final /** * The database information that corresponds to this mission */ - const CDMissions* info; + CDMissions info; /** * The current state this mission is in diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 6bc12b725..997fd34e8 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -449,6 +449,9 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& AddProgress(count); break; } + case eMissionTaskType::DONATION: + AddProgress(count); + break; default: Game::logger->Log("MissionTask", "Invalid mission task type (%i)!", static_cast(type)); return; diff --git a/dGame/dUtilities/CMakeLists.txt b/dGame/dUtilities/CMakeLists.txt index 55ca57972..639f9cf4e 100644 --- a/dGame/dUtilities/CMakeLists.txt +++ b/dGame/dUtilities/CMakeLists.txt @@ -1,4 +1,5 @@ set(DGAME_DUTILITIES_SOURCES "BrickDatabase.cpp" + "CheatDetection.cpp" "GUID.cpp" "Loot.cpp" "Mail.cpp" diff --git a/dGame/dUtilities/CheatDetection.cpp b/dGame/dUtilities/CheatDetection.cpp new file mode 100644 index 000000000..11a682633 --- /dev/null +++ b/dGame/dUtilities/CheatDetection.cpp @@ -0,0 +1,138 @@ +#include "CheatDetection.h" +#include "Database.h" +#include "Entity.h" +#include "PossessableComponent.h" +#include "Player.h" +#include "Game.h" +#include "EntityManager.h" +#include "Character.h" +#include "User.h" +#include "UserManager.h" +#include "dConfig.h" + +Entity* GetPossessedEntity(const LWOOBJID& objId) { + auto* entity = Game::entityManager->GetEntity(objId); + if (!entity) return nullptr; + + auto* possessableComponent = entity->GetComponent(); + // If no possessable, then this entity is the most possessed entity. + if (!possessableComponent) return entity; + + // If not, get the entity that possesses the fetched entity. + return Game::entityManager->GetEntity(possessableComponent->GetPossessor()); +} + +void ReportCheat(User* user, const SystemAddress& sysAddr, const char* messageIfNotSender, va_list args) { + if (!user) { + Game::logger->Log("CheatDetection", "WARNING: User is null, using defaults."); + } + std::unique_ptr stmt(Database::CreatePreppedStmt( + "INSERT INTO player_cheat_detections (account_id, name, violation_msg, violation_system_address) VALUES (?, ?, ?, ?)") + ); + stmt->setInt(1, user ? user->GetAccountID() : 0); + stmt->setString(2, user ? user->GetUsername().c_str() : "User is null."); + + constexpr int32_t bufSize = 4096; + char buffer[bufSize]; + vsnprintf(buffer, bufSize, messageIfNotSender, args); + + stmt->setString(3, buffer); + stmt->setString(4, Game::config->GetValue("log_ip_addresses_for_anti_cheat") == "1" ? sysAddr.ToString() : "IP logging disabled."); + stmt->execute(); + Game::logger->Log("CheatDetection", "Anti-cheat message: %s", buffer); +} + +void LogAndSaveFailedAntiCheatCheck(const LWOOBJID& id, const SystemAddress& sysAddr, const CheckType checkType, const char* messageIfNotSender, va_list args) { + User* toReport = nullptr; + switch (checkType) { + case CheckType::Entity: { + auto* player = Player::GetPlayer(sysAddr); + auto* entity = GetPossessedEntity(id); + + // If player exists and entity exists in world, use both for logging info. + if (entity && player) { + Game::logger->Log("CheatDetection", "Player (%s) (%llu) at system address (%s) with sending player (%s) (%llu) does not match their own.", + player->GetCharacter()->GetName().c_str(), player->GetObjectID(), + sysAddr.ToString(), + entity->GetCharacter()->GetName().c_str(), entity->GetObjectID()); + toReport = player->GetParentUser(); + // In the case that the target entity id did not exist, just log the player info. + } else if (player) { + Game::logger->Log("CheatDetection", "Player (%s) (%llu) at system address (%s) with sending player (%llu) does not match their own.", + player->GetCharacter()->GetName().c_str(), player->GetObjectID(), + sysAddr.ToString(), id); + toReport = player->GetParentUser(); + // In the rare case that the player does not exist, just log the system address and who the target id was. + } else { + Game::logger->Log("CheatDetection", "Player at system address (%s) with sending player (%llu) does not match their own.", + sysAddr.ToString(), id); + } + break; + } + case CheckType::User: { + auto* user = UserManager::Instance()->GetUser(sysAddr); + + if (user) { + Game::logger->Log("CheatDetection", "User at system address (%s) (%s) (%llu) sent a packet as (%i) which is not an id they own.", + sysAddr.ToString(), user->GetLastUsedChar()->GetName().c_str(), user->GetLastUsedChar()->GetObjectID(), static_cast(id)); + // Can't know sending player. Just log system address for IP banning. + } else { + Game::logger->Log("CheatDetection", "No user found for system address (%s).", sysAddr.ToString()); + } + toReport = user; + break; + } + }; + ReportCheat(toReport, sysAddr, messageIfNotSender, args); +} + +void CheatDetection::ReportCheat(User* user, const SystemAddress& sysAddr, const char* messageIfNotSender, ...) { + va_list args; + va_start(args, messageIfNotSender); + ReportCheat(user, sysAddr, messageIfNotSender, args); + va_end(args); +} + +bool CheatDetection::VerifyLwoobjidIsSender(const LWOOBJID& id, const SystemAddress& sysAddr, const CheckType checkType, const char* messageIfNotSender, ...) { + // Get variables we'll need for the whole function + bool invalidPacket = false; + switch (checkType) { + case CheckType::Entity: { + // In this case, the sender may be an entity in the world. + auto* entity = GetPossessedEntity(id); + if (entity) { + invalidPacket = entity->IsPlayer() && entity->GetSystemAddress() != sysAddr; + } + break; + } + case CheckType::User: { + // In this case, the player is not an entity in the world, but may be a user still in world server if they are connected. + // Check here if the system address has a character with id matching the lwoobjid after unsetting the flag bits. + auto* sendingUser = UserManager::Instance()->GetUser(sysAddr); + if (!sendingUser) { + Game::logger->Log("CheatDetection", "No user found for system address (%s).", sysAddr.ToString()); + return false; + } + invalidPacket = true; + const uint32_t characterId = static_cast(id); + // Check to make sure the ID provided is one of the user's characters. + for (const auto& character : sendingUser->GetCharacters()) { + if (character && character->GetID() == characterId) { + invalidPacket = false; + break; + } + } + } + }; + + // This will be true if the player does not possess the entity they are trying to send a packet as. + // or if the user does not own the character they are trying to send a packet as. + if (invalidPacket) { + va_list args; + va_start(args, messageIfNotSender); + LogAndSaveFailedAntiCheatCheck(id, sysAddr, checkType, messageIfNotSender, args); + va_end(args); + } + + return !invalidPacket; +} diff --git a/dGame/dUtilities/CheatDetection.h b/dGame/dUtilities/CheatDetection.h new file mode 100644 index 000000000..ee0dce89b --- /dev/null +++ b/dGame/dUtilities/CheatDetection.h @@ -0,0 +1,30 @@ +#ifndef __CHEATDETECTION__H__ +#define __CHEATDETECTION__H__ + +#include "dCommonVars.h" + +struct SystemAddress; + +enum class CheckType : uint8_t { + User, + Entity, +}; + +namespace CheatDetection { + /** + * @brief Verify that the object ID provided in this function is in someway connected to the system address who sent it. + * + * @param id The object ID to check ownership of + * @param sysAddr The system address which sent the packet + * @param checkType The check type to perform + * @param messageIfNotSender The message to log if the sender is not the owner of the object ID + * @param ... format args + * @return true If the sender is the owner of the object ID + * @return false If the sender is not the owner of the object ID + */ + bool VerifyLwoobjidIsSender(const LWOOBJID& id, const SystemAddress& sysAddr, const CheckType checkType, const char* messageIfNotSender, ...); + void ReportCheat(User* user, const SystemAddress& sysAddr, const char* messageIfNotSender, ...); +}; + +#endif //!__CHEATDETECTION__H__ + diff --git a/dGame/dUtilities/GUID.cpp b/dGame/dUtilities/GUID.cpp index 57f76a81f..50ac8b03c 100644 --- a/dGame/dUtilities/GUID.cpp +++ b/dGame/dUtilities/GUID.cpp @@ -1,6 +1,11 @@ #include "GUID.h" +namespace { + const std::string EMPTY_GUID = "{00000000-0000-0000-0000-000000000000}"; +} + GUID::GUID(const std::string& guid) { + if(guid == EMPTY_GUID) return; sscanf(guid.c_str(), "{%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx}", &this->data1, &this->data2, &this->data3, @@ -8,20 +13,13 @@ GUID::GUID(const std::string& guid) { &this->data4[4], &this->data4[5], &this->data4[6], &this->data4[7]); } -uint32_t GUID::GetData1() const { - return data1; -} - -uint16_t GUID::GetData2() const { - return data2; -} - -uint16_t GUID::GetData3() const { - return data3; -} - -std::array GUID::GetData4() const { - return data4; +void GUID::Serialize(RakNet::BitStream* outBitStream) { + outBitStream->Write(GetData1()); + outBitStream->Write(GetData2()); + outBitStream->Write(GetData3()); + for (const auto& guidSubPart : GetData4()) { + outBitStream->Write(guidSubPart); + } } GUID::GUID() = default; diff --git a/dGame/dUtilities/GUID.h b/dGame/dUtilities/GUID.h index 2d958c100..38e57a6a1 100644 --- a/dGame/dUtilities/GUID.h +++ b/dGame/dUtilities/GUID.h @@ -7,10 +7,24 @@ class GUID { public: explicit GUID(); explicit GUID(const std::string& guid); - uint32_t GetData1() const; - uint16_t GetData2() const; - uint16_t GetData3() const; - std::array GetData4() const; + void Serialize(RakNet::BitStream* outBitStream); + + uint32_t GetData1() const { + return data1; + } + + uint16_t GetData2() const { + return data2; + } + + uint16_t GetData3() const { + return data3; + } + + std::array GetData4() const { + return data4; + } + private: uint32_t data1 = 0; uint16_t data2 = 0; diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index d33af6dc0..a828efa0f 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -13,6 +13,7 @@ #include "Entity.h" #include "Character.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "dLogger.h" #include "EntityManager.h" #include "InventoryComponent.h" @@ -283,7 +284,7 @@ void Mail::HandleDataRequest(RakNet::BitStream* packet, const SystemAddress& sys sql::ResultSet* res = stmt->executeQuery(); RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); bitStream.Write(int(MailMessageID::MailData)); bitStream.Write(int(0)); @@ -406,7 +407,7 @@ void Mail::HandleNotificationRequest(const SystemAddress& sysAddr, uint32_t obje void Mail::SendSendResponse(const SystemAddress& sysAddr, MailSendResponse response) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); bitStream.Write(int(MailMessageID::SendResponse)); bitStream.Write(int(response)); Game::server->Send(&bitStream, sysAddr, false); @@ -414,7 +415,7 @@ void Mail::SendSendResponse(const SystemAddress& sysAddr, MailSendResponse respo void Mail::SendNotification(const SystemAddress& sysAddr, int mailCount) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); uint64_t messageType = 2; uint64_t s1 = 0; uint64_t s2 = 0; @@ -433,7 +434,7 @@ void Mail::SendNotification(const SystemAddress& sysAddr, int mailCount) { void Mail::SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t mailID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); bitStream.Write(int(MailMessageID::AttachmentCollectConfirm)); bitStream.Write(int(0)); //unknown bitStream.Write(mailID); @@ -442,7 +443,7 @@ void Mail::SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t ma void Mail::SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); bitStream.Write(int(MailMessageID::MailDeleteConfirm)); bitStream.Write(int(0)); //unknown bitStream.Write(mailID); @@ -456,7 +457,7 @@ void Mail::SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOO void Mail::SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAIL); bitStream.Write(int(MailMessageID::MailReadConfirm)); bitStream.Write(int(0)); //unknown bitStream.Write(mailID); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 5ecd186cc..b4ebe0ed1 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -49,7 +49,7 @@ #include "dpWorld.h" #include "Item.h" #include "PropertyManagementComponent.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "Loot.h" #include "EntityInfo.h" #include "LUTriggers.h" @@ -761,7 +761,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (chatCommand == "shutdownuniverse" && entity->GetGMLevel() == eGameMasterLevel::OPERATOR) { //Tell the master server that we're going to be shutting down whole "universe": CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_UNIVERSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_UNIVERSE); Game::server->SendToMaster(&bitStream); ChatPackets::SendSystemMessage(sysAddr, u"Sent universe shutdown notification to master."); @@ -1092,7 +1092,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit //Notify chat about it CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); bitStream.Write(characterId); bitStream.Write(expire); @@ -2013,7 +2013,7 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std:: //Notify chat about it CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ANNOUNCEMENT); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ANNOUNCEMENT); bitStream.Write(title.size()); for (auto character : title) { diff --git a/dGame/dUtilities/VanityUtilities.cpp b/dGame/dUtilities/VanityUtilities.cpp index 86fa95034..eb182e043 100644 --- a/dGame/dUtilities/VanityUtilities.cpp +++ b/dGame/dUtilities/VanityUtilities.cpp @@ -80,10 +80,10 @@ void VanityUtilities::SpawnVanity() { // Spawn the NPC auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); - - npcEntity->SetVar>(u"chats", m_PartyPhrases); - - SetupNPCTalk(npcEntity); + if (!npc.m_Phrases.empty()) { + npcEntity->SetVar>(u"chats", m_PartyPhrases); + SetupNPCTalk(npcEntity); + } } return; @@ -114,21 +114,21 @@ void VanityUtilities::SpawnVanity() { // Spawn the NPC auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); + if (!npc.m_Phrases.empty()){ + npcEntity->SetVar>(u"chats", npc.m_Phrases); - npcEntity->SetVar>(u"chats", npc.m_Phrases); + auto* scriptComponent = npcEntity->GetComponent(); - auto* scriptComponent = npcEntity->GetComponent(); + if (scriptComponent && !npc.m_Script.empty()) { + scriptComponent->SetScript(npc.m_Script); + scriptComponent->SetSerialized(false); - if (scriptComponent && !npc.m_Script.empty()) { - scriptComponent->SetScript(npc.m_Script); - scriptComponent->SetSerialized(false); - - for (const auto& npc : npc.m_Flags) { - npcEntity->SetVar(GeneralUtils::ASCIIToUTF16(npc.first), npc.second); + for (const auto& npc : npc.m_Flags) { + npcEntity->SetVar(GeneralUtils::ASCIIToUTF16(npc.first), npc.second); + } } + SetupNPCTalk(npcEntity); } - - SetupNPCTalk(npcEntity); } if (zoneID == 1200) { @@ -160,6 +160,7 @@ Entity* VanityUtilities::SpawnNPC(LOT lot, const std::string& name, const NiPoin auto* entity = Game::entityManager->CreateEntity(info); entity->SetVar(u"npcName", name); + if (entity->GetVar(u"noGhosting")) entity->SetIsGhostingCandidate(false); auto* inventoryComponent = entity->GetComponent(); diff --git a/dMasterServer/InstanceManager.cpp b/dMasterServer/InstanceManager.cpp index 50f55b72b..9ef3077ad 100644 --- a/dMasterServer/InstanceManager.cpp +++ b/dMasterServer/InstanceManager.cpp @@ -8,7 +8,7 @@ #include "CDClientManager.h" #include "CDZoneTableTable.h" #include "MasterPackets.h" -#include "PacketUtils.h" +#include "BitStreamUtils.h" #include "BinaryPathFinder.h" #include "eConnectionType.h" #include "eMasterMessageType.h" @@ -202,7 +202,7 @@ void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstan CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_REQUEST); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_REQUEST); bitStream.Write(request.id); @@ -406,7 +406,7 @@ bool Instance::GetShutdownComplete() const { void Instance::Shutdown() { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN); Game::server->Send(&bitStream, this->m_SysAddr, false); diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index ce237eacf..942574710 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -42,6 +42,7 @@ #include "ObjectIDManager.h" #include "PacketUtils.h" #include "FdbToSqlite.h" +#include "BitStreamUtils.h" namespace Game { dLogger* logger = nullptr; @@ -113,6 +114,17 @@ int main(int argc, char** argv) { Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); + uint32_t clientNetVersion = 0; + if (!GeneralUtils::TryParse(Game::config->GetValue("client_net_version"), clientNetVersion)) { + Game::logger->Log("MasterServer", "Failed to parse (%s) as net version. Cannot start server as no clients could connect.",Game::config->GetValue("client_net_version").c_str()); + Game::logger->Log("MasterServer", "As of version 1.1.1, client_net_version is required to be defined in sharedconfig.ini as opposed to in CMakeVariables.txt as NET_VERSION."); + Game::logger->Log("MasterServer", "Rerun cmake to ensure all config values exist. If client_net_version already exists in sharedconfig.ini, please ensure it is a valid number."); + Game::logger->Log("MasterServer", "like 171022"); + return EXIT_FAILURE; + } + + Game::logger->Log("MasterServer", "Using net version %s", Game::config->GetValue("client_net_version").c_str()); + Game::logger->Log("MasterServer", "Starting Master server..."); Game::logger->Log("MasterServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("MasterServer", "Compiled on: %s", __TIMESTAMP__); @@ -621,7 +633,7 @@ void HandlePacket(Packet* packet) { activeSessions.erase(it.first); CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::NEW_SESSION_ALERT); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::NEW_SESSION_ALERT); bitStream.Write(sessionKey); bitStream.Write(username.size()); for (auto character : username) { @@ -646,9 +658,9 @@ void HandlePacket(Packet* packet) { for (auto key : activeSessions) { if (key.second == username) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SESSION_KEY_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SESSION_KEY_RESPONSE); bitStream.Write(key.first); - PacketUtils::WriteString(bitStream, key.second, 64); + bitStream.Write(LUString(key.second, 64)); Game::server->Send(&bitStream, packet->systemAddress, false); break; } @@ -892,7 +904,7 @@ void ShutdownSequence(int32_t signal) { { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN); Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::logger->Log("MasterServer", "Triggered master shutdown"); } diff --git a/dNavigation/dNavMesh.cpp b/dNavigation/dNavMesh.cpp index fdba4a2d4..14b59055f 100644 --- a/dNavigation/dNavMesh.cpp +++ b/dNavigation/dNavMesh.cpp @@ -10,6 +10,7 @@ #include "BinaryPathFinder.h" #include "dZoneManager.h" +#include "DluAssert.h" dNavMesh::dNavMesh(uint32_t zoneId) { m_ZoneId = zoneId; @@ -118,7 +119,7 @@ void dNavMesh::LoadNavmesh() { m_NavMesh = mesh; } -float dNavMesh::GetHeightAtPoint(const NiPoint3& location) { +float dNavMesh::GetHeightAtPoint(const NiPoint3& location, const float halfExtentsHeight) const { if (m_NavMesh == nullptr) { return location.y; } @@ -130,15 +131,27 @@ float dNavMesh::GetHeightAtPoint(const NiPoint3& location) { pos[2] = location.z; dtPolyRef nearestRef = 0; - float polyPickExt[3] = { 32.0f, 32.0f, 32.0f }; + float polyPickExt[3] = { 0.0f, halfExtentsHeight, 0.0f }; + float nearestPoint[3] = { 0.0f, 0.0f, 0.0f }; dtQueryFilter filter{}; - m_NavQuery->findNearestPoly(pos, polyPickExt, &filter, &nearestRef, 0); + auto hasPoly = m_NavQuery->findNearestPoly(pos, polyPickExt, &filter, &nearestRef, nearestPoint); m_NavQuery->getPolyHeight(nearestRef, pos, &toReturn); - +#ifdef _DEBUG + if (toReturn != 0.0f) { + DluAssert(toReturn == nearestPoint[1]); + } +#endif if (toReturn == 0.0f) { - toReturn = location.y; + // If we were unable to get the poly height, but the query returned a success, just use the height of the nearest point. + // This is what seems to happen anyways and it is better than returning zero. + if (hasPoly == DT_SUCCESS) { + toReturn = nearestPoint[1]; + } else { + toReturn = location.y; + } } + // If we failed to even find a poly, do not change the height since we have no idea what it should be. return toReturn; } diff --git a/dNavigation/dNavMesh.h b/dNavigation/dNavMesh.h index dc3db854e..600b8b868 100644 --- a/dNavigation/dNavMesh.h +++ b/dNavigation/dNavMesh.h @@ -15,7 +15,15 @@ class dNavMesh { dNavMesh(uint32_t zoneId); ~dNavMesh(); - float GetHeightAtPoint(const NiPoint3& location); + /** + * Get the height at a point + * + * @param location The location to check for height at. This is the center of the search area. + * @param halfExtentsHeight The half extents height of the search area. This is the distance from the center to the top and bottom of the search area. + * The larger the value of halfExtentsHeight is, the larger the performance cost of the query. + * @return float The height at the point. If the point is not on the navmesh, the height of the point is returned. + */ + float GetHeightAtPoint(const NiPoint3& location, const float halfExtentsHeight = 32.0f) const; std::vector GetPath(const NiPoint3& startPos, const NiPoint3& endPos, float speed = 10.0f); class dtNavMesh* GetdtNavMesh() { return m_NavMesh; } diff --git a/dNavigation/dTerrain/RawFile.cpp b/dNavigation/dTerrain/RawFile.cpp index d4496b2ff..dfad9ca4f 100644 --- a/dNavigation/dTerrain/RawFile.cpp +++ b/dNavigation/dTerrain/RawFile.cpp @@ -32,13 +32,15 @@ RawFile::RawFile(std::string fileName) { m_Chunks.push_back(chunk); } + m_FinalMesh = new RawMesh(); + this->GenerateFinalMeshFromChunks(); } RawFile::~RawFile() { - delete m_FinalMesh; + if (m_FinalMesh) delete m_FinalMesh; for (const auto* item : m_Chunks) { - delete item; + if (item) delete item; } } @@ -49,10 +51,14 @@ void RawFile::GenerateFinalMeshFromChunks() { for (const auto& vert : chunk->m_Mesh->m_Vertices) { auto tempVert = vert; - tempVert.SetX(tempVert.GetX() + (chunk->m_X / 4)); - tempVert.SetZ(tempVert.GetZ() + (chunk->m_Z / 4)); + // Scale X and Z by the chunk's position in the world + // Scale Y by the chunk's heightmap scale factor + tempVert.SetX(tempVert.GetX() + (chunk->m_X / chunk->m_HeightMap->m_ScaleFactor)); + tempVert.SetY(tempVert.GetY() / chunk->m_HeightMap->m_ScaleFactor); + tempVert.SetZ(tempVert.GetZ() + (chunk->m_Z / chunk->m_HeightMap->m_ScaleFactor)); - tempVert* chunk->m_HeightMap->m_ScaleFactor; + // Then scale it again for some reason + tempVert *= chunk->m_HeightMap->m_ScaleFactor; m_FinalMesh->m_Vertices.push_back(tempVert); } @@ -67,16 +73,12 @@ void RawFile::GenerateFinalMeshFromChunks() { void RawFile::WriteFinalMeshToOBJ(std::string path) { std::ofstream file(path); - std::string vertData; for (const auto& v : m_FinalMesh->m_Vertices) { - vertData += "v " + std::to_string(v.x) + " " + std::to_string(v.y) + " " + std::to_string(v.z) + "\n"; + file << "v " << v.x << ' ' << v.y << ' ' << v.z << '\n'; } for (int i = 0; i < m_FinalMesh->m_Triangles.size(); i += 3) { - vertData += "f " + std::to_string(*std::next(m_FinalMesh->m_Triangles.begin(), i) + 1) + " " + std::to_string(*std::next(m_FinalMesh->m_Triangles.begin(), i + 1) + 1) + " " + std::to_string(*std::next(m_FinalMesh->m_Triangles.begin(), i + 2) + 1) + "\n"; + file << "f " << *std::next(m_FinalMesh->m_Triangles.begin(), i) + 1 << ' ' << *std::next(m_FinalMesh->m_Triangles.begin(), i + 1) + 1 << ' ' << *std::next(m_FinalMesh->m_Triangles.begin(), i + 2) + 1 << '\n'; } - - file.write(vertData.c_str(), vertData.size()); - file.close(); } diff --git a/dNavigation/dTerrain/RawFile.h b/dNavigation/dTerrain/RawFile.h index 2a702c531..b1fb40241 100644 --- a/dNavigation/dTerrain/RawFile.h +++ b/dNavigation/dTerrain/RawFile.h @@ -24,5 +24,5 @@ class RawFile { uint32_t m_Height; std::vector m_Chunks; - RawMesh* m_FinalMesh; + RawMesh* m_FinalMesh = nullptr; }; diff --git a/dNet/AuthPackets.cpp b/dNet/AuthPackets.cpp index 978540c19..3fe9b35b4 100644 --- a/dNet/AuthPackets.cpp +++ b/dNet/AuthPackets.cpp @@ -1,5 +1,6 @@ #include "AuthPackets.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "dNetCommon.h" #include "dServer.h" @@ -39,8 +40,13 @@ void AuthPackets::HandleHandshake(dServer* server, Packet* packet) { void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, const std::string& nextServerIP, uint16_t nextServerPort, const ServerType serverType) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM); - bitStream.Write(NET_VERSION); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM); + uint32_t netVersion; + if (!GeneralUtils::TryParse(Game::config->GetValue("client_net_version"), netVersion)) { + Game::logger->Log("AuthPackets", "Failed to parse client_net_version. Cannot authenticate to %s:%i", nextServerIP.c_str(), nextServerPort); + return; + } + bitStream.Write(netVersion); bitStream.Write(uint32_t(0x93)); if (serverType == ServerType::Auth) bitStream.Write(uint32_t(1)); //Conn: auth @@ -192,20 +198,19 @@ void AuthPackets::HandleLoginRequest(dServer* server, Packet* packet) { void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username) { RakNet::BitStream packet; - PacketUtils::WriteHeader(packet, eConnectionType::CLIENT, eClientMessageType::LOGIN_RESPONSE); + BitStreamUtils::WriteHeader(packet, eConnectionType::CLIENT, eClientMessageType::LOGIN_RESPONSE); packet.Write(static_cast(responseCode)); - PacketUtils::WritePacketString("Talk_Like_A_Pirate", 33, &packet); - - // 7 unknown strings - perhaps other IP addresses? - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); + // Event Gating + packet.Write(LUString("Talk_Like_A_Pirate")); + packet.Write(LUString("")); + packet.Write(LUString("")); + packet.Write(LUString("")); + packet.Write(LUString("")); + packet.Write(LUString("")); + packet.Write(LUString("")); + packet.Write(LUString("")); packet.Write(static_cast(1)); // Version Major packet.Write(static_cast(10)); // Version Current @@ -215,34 +220,34 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd uint32_t sessionKey = GeneralUtils::GenerateRandomNumber(); std::string userHash = std::to_string(sessionKey); userHash = md5(userHash); - PacketUtils::WritePacketWString(userHash, 33, &packet); + packet.Write(LUWString(userHash)); // Write the Character and Chat IPs - PacketUtils::WritePacketString(wServerIP, 33, &packet); - PacketUtils::WritePacketString("", 33, &packet); + packet.Write(LUString(wServerIP)); + packet.Write(LUString("")); // Write the Character and Chat Ports packet.Write(static_cast(wServerPort)); packet.Write(static_cast(0)); - // Write another IP - PacketUtils::WritePacketString("", 33, &packet); + // CDN Key + packet.Write(LUString("")); - // Write a GUID or something... - PacketUtils::WritePacketString("00000000-0000-0000-0000-000000000000", 37, &packet); + // CDN Ticket + packet.Write(LUString("00000000-0000-0000-0000-000000000000", 37)); - packet.Write(static_cast(0)); // ??? + packet.Write(static_cast(0)); // Language // Write the localization - PacketUtils::WritePacketString("US", 3, &packet); + packet.Write(LUString("US", 3)); - packet.Write(static_cast(false)); // User first logged in? - packet.Write(static_cast(false)); // User is F2P? - packet.Write(static_cast(0)); // ??? + packet.Write(static_cast(false)); // Just upgraded from F2P + packet.Write(static_cast(false)); // User is F2P + packet.Write(static_cast(0)); // Time Remaining in F2P // Write custom error message packet.Write(static_cast(errorMsg.length())); - PacketUtils::WritePacketWString(errorMsg, static_cast(errorMsg.length()), &packet); + packet.Write(LUWString(errorMsg, static_cast(errorMsg.length()))); // Here write auth logs packet.Write(static_cast(20)); @@ -258,9 +263,9 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd //Inform the master server that we've created a session for this user: { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SET_SESSION_KEY); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SET_SESSION_KEY); bitStream.Write(sessionKey); - PacketUtils::WriteString(bitStream, username, 66); + bitStream.Write(LUString(username, 66)); server->SendToMaster(&bitStream); server->GetLogger()->Log("AuthPackets", "Set sessionKey: %i for user %s", sessionKey, username.c_str()); diff --git a/dNet/BitStreamUtils.h b/dNet/BitStreamUtils.h new file mode 100644 index 000000000..6daa1c176 --- /dev/null +++ b/dNet/BitStreamUtils.h @@ -0,0 +1,104 @@ +#ifndef __BITSTREAMUTILS__H__ +#define __BITSTREAMUTILS__H__ + +#include "GeneralUtils.h" +#include "MessageIdentifiers.h" +#include "BitStream.h" +#include + +enum class eConnectionType : uint16_t; + +struct LUString { + std::string string; + uint32_t size; + + LUString(uint32_t size) { + this->size = size; + }; + LUString(std::string string, uint32_t size = 33) { + this->string = string; + this->size = size; + }; + std::u16string GetAsU16String() const { + return GeneralUtils::ASCIIToUTF16(this->string); + }; +}; + +struct LUWString { + std::u16string string; + uint32_t size; + + LUWString(uint32_t size) { + this->size = size; + }; + LUWString(std::u16string string, uint32_t size = 33) { + this->string = string; + this->size = size; + }; + LUWString(std::string string, uint32_t size = 33) { + this->string = GeneralUtils::ASCIIToUTF16(string); + this->size = size; + }; + std::string GetAsString() const { + return GeneralUtils::UTF16ToWTF8(this->string); + }; +}; + +namespace BitStreamUtils { + template + void WriteHeader(RakNet::BitStream& bitStream, eConnectionType connectionType, T internalPacketID) { + bitStream.Write(MessageID(ID_USER_PACKET_ENUM)); + bitStream.Write(connectionType); + bitStream.Write(static_cast(internalPacketID)); + bitStream.Write(0); + } + +} + +namespace RakNet { +#ifndef __BITSTREAM_NATIVE_END +#error No definition for big endian reading of LUString +#endif + + template <> + inline bool RakNet::BitStream::Read(LUString& value) { + value.string.resize(value.size); + bool res = ReadBits(reinterpret_cast(value.string.data()), BYTES_TO_BITS(value.string.size()), true); + if (!res) return false; + value.string.erase(std::find(value.string.begin(), value.string.end(), '\0'), value.string.end()); + return res; + } + + template <> + inline bool RakNet::BitStream::Read(LUWString& value) { + value.string.resize(value.size); + bool res = ReadBits(reinterpret_cast(value.string.data()), BYTES_TO_BITS(value.string.size()) * sizeof(std::u16string::value_type), true); + if (!res) return false; + value.string.erase(std::find(value.string.begin(), value.string.end(), u'\0'), value.string.end()); + return res; + } + + template <> + inline void RakNet::BitStream::Write(std::string value) { + this->WriteBits(reinterpret_cast(value.data()), BYTES_TO_BITS(value.size())); + } + + template <> + inline void RakNet::BitStream::Write(std::u16string value) { + this->WriteBits(reinterpret_cast(value.data()), BYTES_TO_BITS(value.size()) * sizeof(std::u16string::value_type)); + } + + template <> + inline void RakNet::BitStream::Write(LUString value) { + value.string.resize(value.size); + this->Write(value.string); + } + + template <> + inline void RakNet::BitStream::Write(LUWString value) { + value.string.resize(value.size); + this->Write(value.string); + } +}; + +#endif //!__BITSTREAMUTILS__H__ diff --git a/dNet/ChatPackets.cpp b/dNet/ChatPackets.cpp index 416615234..20f8aafaf 100644 --- a/dNet/ChatPackets.cpp +++ b/dNet/ChatPackets.cpp @@ -8,19 +8,20 @@ #include "BitStream.h" #include "Game.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "dServer.h" #include "eConnectionType.h" #include "eChatMessageType.h" void ChatPackets::SendChatMessage(const SystemAddress& sysAddr, char chatChannel, const std::string& senderName, LWOOBJID playerObjectID, bool senderMythran, const std::u16string& message) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GENERAL_CHAT_MESSAGE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GENERAL_CHAT_MESSAGE); bitStream.Write(static_cast(0)); bitStream.Write(chatChannel); bitStream.Write(static_cast(message.size())); - PacketUtils::WriteWString(bitStream, senderName, 33); + bitStream.Write(LUWString(senderName)); bitStream.Write(playerObjectID); bitStream.Write(static_cast(0)); @@ -36,13 +37,13 @@ void ChatPackets::SendChatMessage(const SystemAddress& sysAddr, char chatChannel void ChatPackets::SendSystemMessage(const SystemAddress& sysAddr, const std::u16string& message, const bool broadcast) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GENERAL_CHAT_MESSAGE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GENERAL_CHAT_MESSAGE); bitStream.Write(static_cast(0)); bitStream.Write(static_cast(4)); bitStream.Write(static_cast(message.size())); - PacketUtils::WriteWString(bitStream, "", 33); + bitStream.Write(LUWString("", 33)); bitStream.Write(static_cast(0)); bitStream.Write(static_cast(0)); @@ -68,7 +69,7 @@ void ChatPackets::SendMessageFail(const SystemAddress& sysAddr) { //0x01 - "Upgrade to a full LEGO Universe Membership to chat with other players." CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SEND_CANNED_TEXT); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SEND_CANNED_TEXT); bitStream.Write(0); //response type, options above ^ //docs say there's a wstring here-- no idea what it's for, or if it's even needed so leaving it as is for now. SEND_PACKET; diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 8bebda931..e797ea217 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -33,6 +33,7 @@ #include "Database.h" #include "eGameMasterLevel.h" #include "eReplicaComponentType.h" +#include "CheatDetection.h" void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) { User* user = UserManager::Instance()->GetUser(sysAddr); @@ -65,8 +66,18 @@ void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* pack std::string playerName = user->GetLastUsedChar()->GetName(); bool isMythran = user->GetLastUsedChar()->GetGMLevel() > eGameMasterLevel::CIVILIAN; - - if (!user->GetLastChatMessageApproved() && !isMythran) return; + bool isOk = Game::chatFilter->IsSentenceOkay(GeneralUtils::UTF16ToWTF8(message), user->GetLastUsedChar()->GetGMLevel()).empty(); + Game::logger->LogDebug("ClientPackets", "Msg: %s was approved previously? %i", GeneralUtils::UTF16ToWTF8(message).c_str(), user->GetLastChatMessageApproved()); + if (!isOk) { + // Add a limit to the string converted by general utils because it is a user received string and may be a bad actor. + CheatDetection::ReportCheat( + user, + sysAddr, + "Player %s attempted to bypass chat filter with message: %s", + playerName.c_str(), + GeneralUtils::UTF16ToWTF8(message, 512).c_str()); + } + if (!isOk && !isMythran) return; std::string sMessage = GeneralUtils::UTF16ToWTF8(message); Game::logger->Log("Chat", "%s: %s", playerName.c_str(), sMessage.c_str()); diff --git a/dNet/MasterPackets.cpp b/dNet/MasterPackets.cpp index 4233a37da..03330cc9f 100644 --- a/dNet/MasterPackets.cpp +++ b/dNet/MasterPackets.cpp @@ -5,19 +5,20 @@ #include "dServer.h" #include "eConnectionType.h" #include "eMasterMessageType.h" +#include "BitStreamUtils.h" #include void MasterPackets::SendPersistentIDRequest(dServer* server, uint64_t requestID) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID); bitStream.Write(requestID); server->SendToMaster(&bitStream); } void MasterPackets::SendPersistentIDResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE); bitStream.Write(requestID); bitStream.Write(objID); @@ -27,7 +28,7 @@ void MasterPackets::SendPersistentIDResponse(dServer* server, const SystemAddres void MasterPackets::SendZoneTransferRequest(dServer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER); bitStream.Write(requestID); bitStream.Write(static_cast(mythranShift)); @@ -39,7 +40,7 @@ void MasterPackets::SendZoneTransferRequest(dServer* server, uint64_t requestID, void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint32_t cloneID, const std::string& password) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::CREATE_PRIVATE_ZONE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::CREATE_PRIVATE_ZONE); bitStream.Write(zoneID); bitStream.Write(cloneID); @@ -54,7 +55,7 @@ void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID, bool mythranShift, const std::string& password) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PRIVATE_ZONE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PRIVATE_ZONE); bitStream.Write(requestID); bitStream.Write(static_cast(mythranShift)); @@ -69,7 +70,7 @@ void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID, void MasterPackets::SendWorldReady(dServer* server, LWOMAPID zoneId, LWOINSTANCEID instanceId) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::WORLD_READY); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::WORLD_READY); bitStream.Write(zoneId); bitStream.Write(instanceId); @@ -79,7 +80,7 @@ void MasterPackets::SendWorldReady(dServer* server, LWOMAPID zoneId, LWOINSTANCE void MasterPackets::SendZoneTransferResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE); bitStream.Write(requestID); bitStream.Write(static_cast(mythranShift)); @@ -87,7 +88,7 @@ void MasterPackets::SendZoneTransferResponse(dServer* server, const SystemAddres bitStream.Write(zoneInstance); bitStream.Write(zoneClone); bitStream.Write(static_cast(serverPort)); - PacketUtils::WriteString(bitStream, serverIP, static_cast(serverIP.size() + 1)); + bitStream.Write(LUString(serverIP, static_cast(serverIP.size() + 1))); server->Send(&bitStream, sysAddr, false); } @@ -111,13 +112,13 @@ void MasterPackets::HandleServerInfo(Packet* packet) { void MasterPackets::SendServerInfo(dServer* server, Packet* packet) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SERVER_INFO); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SERVER_INFO); bitStream.Write(server->GetPort()); bitStream.Write(server->GetZoneID()); bitStream.Write(server->GetInstanceID()); bitStream.Write(server->GetServerType()); - PacketUtils::WriteString(bitStream, server->GetIP(), server->GetIP().size()); + bitStream.Write(LUString(server->GetIP(), server->GetIP().size())); server->SendToMaster(&bitStream); } diff --git a/dNet/PacketUtils.cpp b/dNet/PacketUtils.cpp index 77b314d60..c19298264 100644 --- a/dNet/PacketUtils.cpp +++ b/dNet/PacketUtils.cpp @@ -4,7 +4,7 @@ #include "dLogger.h" #include "Game.h" -uint16_t PacketUtils::ReadPacketU16(uint32_t startLoc, Packet* packet) { +uint16_t PacketUtils::ReadU16(uint32_t startLoc, Packet* packet) { if (startLoc + 2 > packet->length) return 0; std::vector t; @@ -12,7 +12,7 @@ uint16_t PacketUtils::ReadPacketU16(uint32_t startLoc, Packet* packet) { return *(uint16_t*)t.data(); } -uint32_t PacketUtils::ReadPacketU32(uint32_t startLoc, Packet* packet) { +uint32_t PacketUtils::ReadU32(uint32_t startLoc, Packet* packet) { if (startLoc + 4 > packet->length) return 0; std::vector t; @@ -22,7 +22,7 @@ uint32_t PacketUtils::ReadPacketU32(uint32_t startLoc, Packet* packet) { return *(uint32_t*)t.data(); } -uint64_t PacketUtils::ReadPacketU64(uint32_t startLoc, Packet* packet) { +uint64_t PacketUtils::ReadU64(uint32_t startLoc, Packet* packet) { if (startLoc + 8 > packet->length) return 0; std::vector t; @@ -30,7 +30,7 @@ uint64_t PacketUtils::ReadPacketU64(uint32_t startLoc, Packet* packet) { return *(uint64_t*)t.data(); } -int64_t PacketUtils::ReadPacketS64(uint32_t startLoc, Packet* packet) { +int64_t PacketUtils::ReadS64(uint32_t startLoc, Packet* packet) { if (startLoc + 8 > packet->length) return 0; std::vector t; @@ -59,81 +59,6 @@ std::string PacketUtils::ReadString(uint32_t startLoc, Packet* packet, bool wide return readString; } -void PacketUtils::WritePacketString(const std::string& string, uint32_t maxSize, RakNet::BitStream* bitStream) { - uint32_t size = static_cast(string.size()); - uint32_t remSize = static_cast(maxSize - size); - - if (size > maxSize) size = maxSize; - - for (uint32_t i = 0; i < size; ++i) { - bitStream->Write(static_cast(string[i])); - } - - for (uint32_t j = 0; j < remSize; ++j) { - bitStream->Write(static_cast(0)); - } -} - -void PacketUtils::WriteString(RakNet::BitStream& bitStream, const std::string& s, uint32_t maxSize) { - uint32_t size = s.size(); - uint32_t emptySize = maxSize - size; - - if (size > maxSize) size = maxSize; - - for (uint32_t i = 0; i < size; i++) { - bitStream.Write((char)s[i]); - } - - for (uint32_t i = 0; i < emptySize; i++) { - bitStream.Write((char)0); - } -} - -void PacketUtils::WriteWString(RakNet::BitStream& bitStream, const std::string& string, uint32_t maxSize) { - uint32_t size = static_cast(string.length()); - uint32_t remSize = static_cast(maxSize - size); - - if (size > maxSize) size = maxSize; - - for (uint32_t i = 0; i < size; ++i) { - bitStream.Write(static_cast(string[i])); - } - - for (uint32_t j = 0; j < remSize; ++j) { - bitStream.Write(static_cast(0)); - } -} - -void PacketUtils::WriteWString(RakNet::BitStream& bitStream, const std::u16string& string, uint32_t maxSize) { - uint32_t size = static_cast(string.length()); - uint32_t remSize = static_cast(maxSize - size); - - if (size > maxSize) size = maxSize; - - for (uint32_t i = 0; i < size; ++i) { - bitStream.Write(static_cast(string[i])); - } - - for (uint32_t j = 0; j < remSize; ++j) { - bitStream.Write(static_cast(0)); - } -} - -void PacketUtils::WritePacketWString(const std::string& string, uint32_t maxSize, RakNet::BitStream* bitStream) { - uint32_t size = static_cast(string.length()); - uint32_t remSize = static_cast(maxSize - size); - - if (size > maxSize) size = maxSize; - - for (uint32_t i = 0; i < size; ++i) { - bitStream->Write(static_cast(string[i])); - } - - for (uint32_t j = 0; j < remSize; ++j) { - bitStream->Write(static_cast(0)); - } -} - //! Saves a packet to the filesystem void PacketUtils::SavePacket(const std::string& filename, const char* data, size_t length) { //If we don't log to the console, don't save the bin files either. This takes up a lot of time. diff --git a/dNet/PacketUtils.h b/dNet/PacketUtils.h index d07759a00..2afd53c76 100644 --- a/dNet/PacketUtils.h +++ b/dNet/PacketUtils.h @@ -8,26 +8,11 @@ enum class eConnectionType : uint16_t; namespace PacketUtils { - template - void WriteHeader(RakNet::BitStream& bitStream, eConnectionType connectionType, T internalPacketID) { - bitStream.Write(MessageID(ID_USER_PACKET_ENUM)); - bitStream.Write(connectionType); - bitStream.Write(static_cast(internalPacketID)); - bitStream.Write(0); - } - - uint16_t ReadPacketU16(uint32_t startLoc, Packet* packet); - uint32_t ReadPacketU32(uint32_t startLoc, Packet* packet); - uint64_t ReadPacketU64(uint32_t startLoc, Packet* packet); - int64_t ReadPacketS64(uint32_t startLoc, Packet* packet); + uint16_t ReadU16(uint32_t startLoc, Packet* packet); + uint32_t ReadU32(uint32_t startLoc, Packet* packet); + uint64_t ReadU64(uint32_t startLoc, Packet* packet); + int64_t ReadS64(uint32_t startLoc, Packet* packet); std::string ReadString(uint32_t startLoc, Packet* packet, bool wide, uint32_t maxLen = 33); - - void WritePacketString(const std::string& string, uint32_t maxSize, RakNet::BitStream* bitStream); - void WriteString(RakNet::BitStream& bitStream, const std::string& s, uint32_t maxSize); - void WriteWString(RakNet::BitStream& bitStream, const std::string& string, uint32_t maxSize); - void WriteWString(RakNet::BitStream& bitStream, const std::u16string& string, uint32_t maxSize); - void WritePacketWString(const std::string& string, uint32_t maxSize, RakNet::BitStream* bitStream); - void SavePacket(const std::string& filename, const char* data, size_t length); }; diff --git a/dNet/WorldPackets.cpp b/dNet/WorldPackets.cpp index 35c985eb3..18c2c8a5a 100644 --- a/dNet/WorldPackets.cpp +++ b/dNet/WorldPackets.cpp @@ -14,10 +14,11 @@ #include "CharacterComponent.h" #include "ZCompression.h" #include "eConnectionType.h" +#include "BitStreamUtils.h" void WorldPackets::SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::LOAD_STATIC_ZONE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::LOAD_STATIC_ZONE); auto zone = Game::zoneManager->GetZone()->GetZoneID(); bitStream.Write(static_cast(zone.GetMapID())); @@ -41,7 +42,7 @@ void WorldPackets::SendCharacterList(const SystemAddress& sysAddr, User* user) { if (!user) return; RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_LIST_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_LIST_RESPONSE); std::vector characters = user->GetCharacters(); bitStream.Write(static_cast(characters.size())); @@ -51,13 +52,13 @@ void WorldPackets::SendCharacterList(const SystemAddress& sysAddr, User* user) { bitStream.Write(characters[i]->GetObjectID()); bitStream.Write(static_cast(0)); - PacketUtils::WriteWString(bitStream, characters[i]->GetName(), 33); - PacketUtils::WriteWString(bitStream, characters[i]->GetUnapprovedName(), 33); + bitStream.Write(LUWString(characters[i]->GetName())); + bitStream.Write(LUWString(characters[i]->GetUnapprovedName())); bitStream.Write(static_cast(characters[i]->GetNameRejected())); bitStream.Write(static_cast(false)); - PacketUtils::WriteString(bitStream, "", 10); + bitStream.Write(LUString("", 10)); bitStream.Write(characters[i]->GetShirtColor()); bitStream.Write(characters[i]->GetShirtStyle()); @@ -90,30 +91,30 @@ void WorldPackets::SendCharacterList(const SystemAddress& sysAddr, User* user) { void WorldPackets::SendCharacterCreationResponse(const SystemAddress& sysAddr, eCharacterCreationResponse response) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_CREATE_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_CREATE_RESPONSE); bitStream.Write(response); SEND_PACKET; } void WorldPackets::SendCharacterRenameResponse(const SystemAddress& sysAddr, eRenameResponse response) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_RENAME_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_RENAME_RESPONSE); bitStream.Write(response); SEND_PACKET; } void WorldPackets::SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::DELETE_CHARACTER_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::DELETE_CHARACTER_RESPONSE); bitStream.Write(static_cast(response)); SEND_PACKET; } void WorldPackets::SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TRANSFER_TO_WORLD); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TRANSFER_TO_WORLD); - PacketUtils::WriteString(bitStream, serverIP, 33); + bitStream.Write(LUString(serverIP)); bitStream.Write(static_cast(serverPort)); bitStream.Write(static_cast(mythranShift)); @@ -122,14 +123,14 @@ void WorldPackets::SendTransferToWorld(const SystemAddress& sysAddr, const std:: void WorldPackets::SendServerState(const SystemAddress& sysAddr) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SERVER_STATES); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SERVER_STATES); bitStream.Write(static_cast(1)); //If the server is receiving this request, it probably is ready anyway. SEND_PACKET; } void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* entity, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CREATE_CHARACTER); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CREATE_CHARACTER); RakNet::BitStream data; data.Write(7); //LDF key count @@ -198,7 +199,7 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* ent void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::vector> unacceptedItems) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHAT_MODERATION_STRING); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHAT_MODERATION_STRING); bitStream.Write(unacceptedItems.empty()); // Is sentence ok? bitStream.Write(0x16); // Source ID, unknown @@ -206,7 +207,7 @@ void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool bitStream.Write(static_cast(requestID)); // request ID bitStream.Write(static_cast(0)); // chat mode - PacketUtils::WritePacketWString(receiver, 42, &bitStream); // receiver name + bitStream.Write(LUWString(receiver, 42)); // receiver name for (auto it : unacceptedItems) { bitStream.Write(it.first); // start index @@ -222,7 +223,7 @@ void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool void WorldPackets::SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAKE_GM_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::MAKE_GM_RESPONSE); bitStream.Write(success); bitStream.Write(static_cast(highestLevel)); diff --git a/dNet/ZoneInstanceManager.cpp b/dNet/ZoneInstanceManager.cpp index b57bb6347..f92855797 100644 --- a/dNet/ZoneInstanceManager.cpp +++ b/dNet/ZoneInstanceManager.cpp @@ -28,10 +28,10 @@ void ZoneInstanceManager::RequestZoneTransfer(dServer* server, uint32_t zoneID, void ZoneInstanceManager::HandleRequestZoneTransferResponse(uint64_t requestID, Packet* packet) { bool mythranShift = static_cast(packet->data[16]); - uint32_t zoneID = PacketUtils::ReadPacketU32(17, packet); - uint32_t zoneInstance = PacketUtils::ReadPacketU32(21, packet); - uint32_t zoneClone = PacketUtils::ReadPacketU32(25, packet); - uint16_t serverPort = PacketUtils::ReadPacketU16(29, packet); + uint32_t zoneID = PacketUtils::ReadU32(17, packet); + uint32_t zoneInstance = PacketUtils::ReadU32(21, packet); + uint32_t zoneClone = PacketUtils::ReadU32(25, packet); + uint16_t serverPort = PacketUtils::ReadU16(29, packet); std::string serverIP = PacketUtils::ReadString(31, packet, false); for (uint32_t i = 0; i < this->requests.size(); ++i) { diff --git a/dNet/dServer.cpp b/dNet/dServer.cpp index 610f06a5d..75cd40917 100644 --- a/dNet/dServer.cpp +++ b/dNet/dServer.cpp @@ -11,6 +11,7 @@ #include "eMasterMessageType.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "MasterPackets.h" #include "ZoneInstanceManager.h" @@ -123,7 +124,7 @@ Packet* dServer::ReceiveFromMaster() { if (static_cast(packet->data[1]) == eConnectionType::MASTER) { switch (static_cast(packet->data[3])) { case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: { - uint64_t requestID = PacketUtils::ReadPacketU64(8, packet); + uint64_t requestID = PacketUtils::ReadU64(8, packet); ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet); break; } @@ -168,7 +169,7 @@ void dServer::SendToMaster(RakNet::BitStream* bitStream) { void dServer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) { RakNet::BitStream bitStream; - PacketUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY); bitStream.Write(disconNotifyID); mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, false); diff --git a/dScripts/02_server/Map/AM/AmShieldGenerator.cpp b/dScripts/02_server/Map/AM/AmShieldGenerator.cpp index e39233ebc..7c785c41e 100644 --- a/dScripts/02_server/Map/AM/AmShieldGenerator.cpp +++ b/dScripts/02_server/Map/AM/AmShieldGenerator.cpp @@ -136,7 +136,7 @@ void AmShieldGenerator::EnemyEnteredShield(Entity* self, Entity* intruder) { // TODO: Figure out how todo knockback, I'll stun them for now - if (NiPoint3::DistanceSquared(self->GetPosition(), movementAIComponent->GetCurrentPosition()) < 20 * 20) { + if (NiPoint3::DistanceSquared(self->GetPosition(), intruder->GetPosition()) < 20 * 20) { baseCombatAIComponent->Stun(2.0f); movementAIComponent->SetDestination(baseCombatAIComponent->GetStartPosition()); } diff --git a/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp b/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp index 506f55806..0c09a5dae 100644 --- a/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp +++ b/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp @@ -194,7 +194,7 @@ void AmShieldGeneratorQuickbuild::EnemyEnteredShield(Entity* self, Entity* intru // TODO: Figure out how todo knockback, I'll stun them for now - if (NiPoint3::DistanceSquared(self->GetPosition(), movementAIComponent->GetCurrentPosition()) < 20 * 20) { + if (NiPoint3::DistanceSquared(self->GetPosition(), intruder->GetPosition()) < 20 * 20) { baseCombatAIComponent->Stun(2.0f); movementAIComponent->SetDestination(baseCombatAIComponent->GetStartPosition()); } diff --git a/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp b/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp index 641845a94..2d526a257 100644 --- a/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp +++ b/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp @@ -52,12 +52,6 @@ void EnemySpiderSpawner::OnTimerDone(Entity* self, std::string timerName) { if (newEntity) { Game::entityManager->ConstructEntity(newEntity); newEntity->GetGroups().push_back("BabySpider"); - - /* - auto* movementAi = newEntity->GetComponent(); - - movementAi->SetDestination(newEntity->GetPosition()); - */ } self->ScheduleKillAfterUpdate(); diff --git a/dScripts/BaseSurvivalServer.cpp b/dScripts/BaseSurvivalServer.cpp index 0e8d04314..ffa86968b 100644 --- a/dScripts/BaseSurvivalServer.cpp +++ b/dScripts/BaseSurvivalServer.cpp @@ -472,7 +472,7 @@ std::vector BaseSurvivalServer::GetRandomMobSet(SpawnerNetworkCollecti if (mobSets.sets.find(spawnerNetworkCollection.mobSetName) != mobSets.sets.end()) { auto mobSet = mobSets.sets.at(spawnerNetworkCollection.mobSetName); if (setNumber < mobSet.size()) { - return mobSet.at(setNumber).at(rand() % mobSet.at(setNumber).size()); + return mobSet.at(setNumber).at(GeneralUtils::GenerateRandomNumber(0, mobSet.at(setNumber).size() - 1)); } } @@ -487,7 +487,7 @@ SpawnerNetwork BaseSurvivalServer::GetRandomSpawner(SpawnerNetworkCollection& sp } if (!validSpawners.empty()) { - auto spawner = validSpawners.at(rand() % validSpawners.size()); + auto spawner = validSpawners.at(GeneralUtils::GenerateRandomNumber(0, validSpawners.size() - 1)); spawner.isActive = true; return spawner; } diff --git a/dScripts/ScriptComponent.cpp b/dScripts/ScriptComponent.cpp index 272de5ab4..2079d67a3 100644 --- a/dScripts/ScriptComponent.cpp +++ b/dScripts/ScriptComponent.cpp @@ -17,7 +17,7 @@ ScriptComponent::~ScriptComponent() { } -void ScriptComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { +void ScriptComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { const auto& networkSettings = m_Parent->GetNetworkSettings(); auto hasNetworkSettings = !networkSettings.empty(); diff --git a/dScripts/ScriptComponent.h b/dScripts/ScriptComponent.h index 77dff5bfb..98925eb44 100644 --- a/dScripts/ScriptComponent.h +++ b/dScripts/ScriptComponent.h @@ -24,7 +24,7 @@ class ScriptComponent : public Component { ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false); ~ScriptComponent() override; - void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; /** * Returns the script that's attached to this entity diff --git a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp index 08942cee9..ccb900f60 100644 --- a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp +++ b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp @@ -291,7 +291,7 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) { enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI); - movementAI->SetSpeed(toSpawn.initialSpeed); + movementAI->SetMaxSpeed(toSpawn.initialSpeed); movementAI->SetCurrentSpeed(toSpawn.initialSpeed); movementAI->SetHaltDistance(0.0f); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index f7e3caeea..0803bbf71 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -29,6 +29,7 @@ #include "AuthPackets.h" #include "PacketUtils.h" +#include "BitStreamUtils.h" #include "WorldPackets.h" #include "UserManager.h" #include "CDClientManager.h" @@ -72,6 +73,7 @@ #include "eGameMessageType.h" #include "ZCompression.h" #include "EntityManager.h" +#include "CheatDetection.h" namespace Game { dLogger* logger = nullptr; @@ -261,48 +263,49 @@ int main(int argc, char** argv) { Game::zoneManager->Initialize(LWOZONEID(zoneID, instanceID, cloneID)); g_CloneID = cloneID; - // pre calculate the FDB checksum - if (Game::config->GetValue("check_fdb") == "1") { - std::ifstream fileStream; + } else { + Game::entityManager->Initialize(); + } - static const std::vector aliases = { - "CDServers.fdb", - "cdserver.fdb", - "CDClient.fdb", - "cdclient.fdb", - }; + // pre calculate the FDB checksum + if (Game::config->GetValue("check_fdb") == "1") { + std::ifstream fileStream; - for (const auto& file : aliases) { - fileStream.open(Game::assetManager->GetResPath() / file, std::ios::binary | std::ios::in); - if (fileStream.is_open()) { - break; - } + static const std::vector aliases = { + "CDServers.fdb", + "cdserver.fdb", + "CDClient.fdb", + "cdclient.fdb", + }; + + for (const auto& file : aliases) { + fileStream.open(Game::assetManager->GetResPath() / file, std::ios::binary | std::ios::in); + if (fileStream.is_open()) { + break; } + } - const int32_t bufferSize = 1024; - MD5* md5 = new MD5(); + const int32_t bufferSize = 1024; + MD5* md5 = new MD5(); - char fileStreamBuffer[1024] = {}; + char fileStreamBuffer[1024] = {}; - while (!fileStream.eof()) { - memset(fileStreamBuffer, 0, bufferSize); - fileStream.read(fileStreamBuffer, bufferSize); - md5->update(fileStreamBuffer, fileStream.gcount()); - } + while (!fileStream.eof()) { + memset(fileStreamBuffer, 0, bufferSize); + fileStream.read(fileStreamBuffer, bufferSize); + md5->update(fileStreamBuffer, fileStream.gcount()); + } - fileStream.close(); + fileStream.close(); - const char* nullTerminateBuffer = "\0"; - md5->update(nullTerminateBuffer, 1); // null terminate the data - md5->finalize(); - databaseChecksum = md5->hexdigest(); + const char* nullTerminateBuffer = "\0"; + md5->update(nullTerminateBuffer, 1); // null terminate the data + md5->finalize(); + databaseChecksum = md5->hexdigest(); - delete md5; + delete md5; - Game::logger->Log("WorldServer", "FDB Checksum calculated as: %s", databaseChecksum.c_str()); - } - } else { - Game::entityManager->Initialize(); + Game::logger->Log("WorldServer", "FDB Checksum calculated as: %s", databaseChecksum.c_str()); } uint32_t currentFrameDelta = highFrameDelta; @@ -706,7 +709,7 @@ void HandlePacket(Packet* packet) { { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); bitStream.Write(user->GetLoggedInChar()); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } @@ -718,7 +721,7 @@ void HandlePacket(Packet* packet) { } CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_REMOVED); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_REMOVED); bitStream.Write((LWOMAPID)Game::server->GetZoneID()); bitStream.Write((LWOINSTANCEID)instanceID); Game::server->SendToMaster(&bitStream); @@ -734,14 +737,14 @@ void HandlePacket(Packet* packet) { if (static_cast(packet->data[1]) == eConnectionType::MASTER) { switch (static_cast(packet->data[3])) { case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: { - uint64_t requestID = PacketUtils::ReadPacketU64(8, packet); - uint32_t objectID = PacketUtils::ReadPacketU32(16, packet); + uint64_t requestID = PacketUtils::ReadU64(8, packet); + uint32_t objectID = PacketUtils::ReadU32(16, packet); ObjectIDManager::Instance()->HandleRequestPersistentIDResponse(requestID, objectID); break; } case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: { - uint64_t requestID = PacketUtils::ReadPacketU64(8, packet); + uint64_t requestID = PacketUtils::ReadU64(8, packet); ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet); break; } @@ -803,7 +806,7 @@ void HandlePacket(Packet* packet) { //Notify master: { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_ADDED); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_ADDED); bitStream.Write((LWOMAPID)Game::server->GetZoneID()); bitStream.Write((LWOINSTANCEID)instanceID); Game::server->SendToMaster(&bitStream); @@ -813,13 +816,13 @@ void HandlePacket(Packet* packet) { break; } case eMasterMessageType::AFFIRM_TRANSFER_REQUEST: { - const uint64_t requestID = PacketUtils::ReadPacketU64(8, packet); + const uint64_t requestID = PacketUtils::ReadU64(8, packet); Game::logger->Log("MasterServer", "Got affirmation request of transfer %llu", requestID); CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE); bitStream.Write(requestID); Game::server->SendToMaster(&bitStream); @@ -905,8 +908,8 @@ void HandlePacket(Packet* packet) { //Request the session info from Master: CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_SESSION_KEY); - PacketUtils::WriteString(bitStream, username, 64); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_SESSION_KEY); + bitStream.Write(LUString(username, 64)); Game::server->SendToMaster(&bitStream); //Insert info into our pending list @@ -954,7 +957,15 @@ void HandlePacket(Packet* packet) { RakNet::BitStream dataStream; bitStream.Read(dataStream, bitStream.GetNumberOfUnreadBits()); - GameMessageHandler::HandleMessage(&dataStream, packet->systemAddress, objectID, messageID); + auto isSender = CheatDetection::VerifyLwoobjidIsSender( + objectID, + packet->systemAddress, + CheckType::Entity, + "Sending GM with a sending player that does not match their own. GM ID: %i", + static_cast(messageID) + ); + + if (isSender) GameMessageHandler::HandleMessage(&dataStream, packet->systemAddress, objectID, messageID); break; } @@ -969,6 +980,17 @@ void HandlePacket(Packet* packet) { LWOOBJID playerID = 0; inStream.Read(playerID); + + bool valid = CheatDetection::VerifyLwoobjidIsSender( + playerID, + packet->systemAddress, + CheckType::User, + "Sending login request with a sending player that does not match their own. Player ID: %llu", + playerID + ); + + if (!valid) return; + GeneralUtils::ClearBit(playerID, eObjectBits::CHARACTER); GeneralUtils::ClearBit(playerID, eObjectBits::PERSISTENT); @@ -979,7 +1001,7 @@ void HandlePacket(Packet* packet) { // 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, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); bitStream.Write(lastCharacter); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); } @@ -1128,7 +1150,7 @@ void HandlePacket(Packet* packet) { GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT); CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::BLUEPRINT_SAVE_RESPONSE); bitStream.Write(LWOOBJID_EMPTY); //always zero so that a check on the client passes bitStream.Write(eBlueprintSaveResponseType::EverythingWorked); bitStream.Write(1); @@ -1169,7 +1191,7 @@ void HandlePacket(Packet* packet) { //RakNet::RakString playerName(player->GetCharacter()->GetName().c_str()); CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION); bitStream.Write(player->GetObjectID()); bitStream.Write(playerName.size()); for (size_t i = 0; i < playerName.size(); i++) { @@ -1201,6 +1223,7 @@ void HandlePacket(Packet* packet) { case eWorldMessageType::MAIL: { RakNet::BitStream bitStream(packet->data, packet->length, false); + // FIXME: Change this to the macro to skip the header... LWOOBJID space; bitStream.Read(space); Mail::HandleMailStuff(&bitStream, packet->systemAddress, UserManager::Instance()->GetUser(packet->systemAddress)->GetLastUsedChar()->GetEntity()); @@ -1220,7 +1243,7 @@ void HandlePacket(Packet* packet) { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, packet->data[14]); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, packet->data[14]); //We need to insert the player's objectID so the chat server can find who originated this request: LWOOBJID objectID = 0; @@ -1346,6 +1369,6 @@ void FinalizeShutdown() { void SendShutdownMessageToMaster() { CBITSTREAM; - PacketUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_RESPONSE); + BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_RESPONSE); Game::server->SendToMaster(&bitStream); } diff --git a/dZoneManager/CMakeLists.txt b/dZoneManager/CMakeLists.txt index 1dd3841b7..bbb22ba7d 100644 --- a/dZoneManager/CMakeLists.txt +++ b/dZoneManager/CMakeLists.txt @@ -3,4 +3,5 @@ set(DZONEMANAGER_SOURCES "dZoneManager.cpp" "Spawner.cpp" "Zone.cpp") -add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES}) +add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES}) +target_link_libraries(dZoneManager dPhysics) diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 7343bb59d..07b3d72c2 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -13,6 +13,7 @@ #include "CDZoneTableTable.h" #include "Spawner.h" #include "dZoneManager.h" +#include "dpWorld.h" #include "eTriggerCommandType.h" #include "eTriggerEventType.h" @@ -54,22 +55,22 @@ void Zone::LoadZoneIntoMemory() { std::istream file(&buffer); if (file) { - BinaryIO::BinaryRead(file, m_ZoneFileFormatVersion); + BinaryIO::BinaryRead(file, m_FileFormatVersion); uint32_t mapRevision = 0; - if (m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::Alpha) BinaryIO::BinaryRead(file, mapRevision); + if (m_FileFormatVersion >= Zone::FileFormatVersion::Alpha) BinaryIO::BinaryRead(file, mapRevision); BinaryIO::BinaryRead(file, m_WorldID); if ((uint16_t)m_WorldID != m_ZoneID.GetMapID()) Game::logger->Log("Zone", "WorldID: %i doesn't match MapID %i! Is this intended?", m_WorldID, m_ZoneID.GetMapID()); AddRevision(LWOSCENEID_INVALID, mapRevision); - if (m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::Beta) { + if (m_FileFormatVersion >= Zone::FileFormatVersion::Beta) { BinaryIO::BinaryRead(file, m_Spawnpoint); BinaryIO::BinaryRead(file, m_SpawnpointRotation); } - if (m_ZoneFileFormatVersion <= Zone::ZoneFileFormatVersion::LateAlpha) { + if (m_FileFormatVersion <= Zone::FileFormatVersion::LateAlpha) { uint8_t sceneCount; BinaryIO::BinaryRead(file, sceneCount); m_SceneCount = sceneCount; @@ -93,14 +94,14 @@ void Zone::LoadZoneIntoMemory() { BinaryIO::BinaryRead(file, stringLength); m_ZoneDesc = BinaryIO::ReadString(file, stringLength); - if (m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::PreAlpha) { + if (m_FileFormatVersion >= Zone::FileFormatVersion::PreAlpha) { BinaryIO::BinaryRead(file, m_NumberOfSceneTransitionsLoaded); for (uint32_t i = 0; i < m_NumberOfSceneTransitionsLoaded; ++i) { LoadSceneTransition(file); } } - if (m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::EarlyAlpha) { + if (m_FileFormatVersion >= Zone::FileFormatVersion::EarlyAlpha) { BinaryIO::BinaryRead(file, m_PathDataLength); BinaryIO::BinaryRead(file, m_PathChunkVersion); // always should be 1 @@ -244,16 +245,29 @@ void Zone::LoadScene(std::istream& file) { scene.triggers.insert({ trigger->id, trigger }); } - BinaryIO::BinaryRead(file, scene.id); - BinaryIO::BinaryRead(file, scene.sceneType); - lwoSceneID.SetSceneID(scene.id); + if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion < Zone::FileFormatVersion::PrePreAlpha) { + BinaryIO::BinaryRead(file, scene.id); + lwoSceneID.SetSceneID(scene.id); + } + if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha) { + BinaryIO::BinaryRead(file, scene.sceneType); + lwoSceneID.SetLayerID(scene.sceneType); + + uint8_t sceneNameLength; + BinaryIO::BinaryRead(file, sceneNameLength); + scene.name = BinaryIO::ReadString(file, sceneNameLength); + } - uint8_t sceneNameLength; - BinaryIO::BinaryRead(file, sceneNameLength); - scene.name = BinaryIO::ReadString(file, sceneNameLength); - file.ignore(3); + if (m_FileFormatVersion == Zone::FileFormatVersion::LatePreAlpha){ + BinaryIO::BinaryRead(file, scene.unknown1); + BinaryIO::BinaryRead(file, scene.unknown2); + } - lwoSceneID.SetLayerID(scene.sceneType); + if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha) { + BinaryIO::BinaryRead(file, scene.color_r); + BinaryIO::BinaryRead(file, scene.color_b); + BinaryIO::BinaryRead(file, scene.color_g); + } m_Scenes.insert(std::make_pair(lwoSceneID, scene)); m_NumberOfScenesLoaded++; @@ -345,15 +359,15 @@ const Path* Zone::GetPath(std::string name) const { void Zone::LoadSceneTransition(std::istream& file) { SceneTransition sceneTrans; - if (m_ZoneFileFormatVersion < Zone::ZoneFileFormatVersion::Auramar) { + if (m_FileFormatVersion < Zone::FileFormatVersion::Auramar) { uint8_t length; BinaryIO::BinaryRead(file, length); sceneTrans.name = BinaryIO::ReadString(file, length); - file.ignore(4); + BinaryIO::BinaryRead(file, sceneTrans.width); } //BR�THER MAY I HAVE SOME L��PS? - uint8_t loops = (m_ZoneFileFormatVersion < Zone::ZoneFileFormatVersion::EarlyAlpha || m_ZoneFileFormatVersion >= Zone::ZoneFileFormatVersion::Launch) ? 2 : 5; + uint8_t loops = (m_FileFormatVersion <= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion >= Zone::FileFormatVersion::Launch) ? 2 : 5; for (uint8_t i = 0; i < loops; ++i) { sceneTrans.points.push_back(LoadSceneTransitionInfo(file)); @@ -401,7 +415,7 @@ void Zone::LoadPath(std::istream& file) { } else if (path.pathType == PathType::Property) { BinaryIO::BinaryRead(file, path.property.pathType); BinaryIO::BinaryRead(file, path.property.price); - BinaryIO::BinaryRead(file, path.property.rentalTimeUnit); + BinaryIO::BinaryRead(file, path.property.rentalTime); BinaryIO::BinaryRead(file, path.property.associatedZone); if (path.pathVersion >= 5) { @@ -426,14 +440,12 @@ void Zone::LoadPath(std::istream& file) { if (path.pathVersion >= 7) { BinaryIO::BinaryRead(file, path.property.cloneLimit); BinaryIO::BinaryRead(file, path.property.repMultiplier); - BinaryIO::BinaryRead(file, path.property.rentalTimeUnit); + BinaryIO::BinaryRead(file, path.property.rentalPeriod); } if (path.pathVersion >= 8) { BinaryIO::BinaryRead(file, path.property.achievementRequired); - BinaryIO::BinaryRead(file, path.property.playerZoneCoords.x); - BinaryIO::BinaryRead(file, path.property.playerZoneCoords.y); - BinaryIO::BinaryRead(file, path.property.playerZoneCoords.z); + BinaryIO::BinaryRead(file, path.property.playerZoneCoords); BinaryIO::BinaryRead(file, path.property.maxBuildHeight); } } else if (path.pathType == PathType::Camera) { @@ -543,11 +555,15 @@ void Zone::LoadPath(std::istream& file) { if (ldfConfig) waypoint.config.push_back(ldfConfig); } } - + // We verify the waypoint heights against the navmesh because in many movement paths, + // the waypoint is located near 0 height, + if (path.pathType == PathType::Movement) { + if (dpWorld::Instance().IsLoaded()) { + // 2000 should be large enough for every world. + waypoint.position.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(waypoint.position, 2000.0f); + } + } path.pathWaypoints.push_back(waypoint); } - - - m_Paths.push_back(path); } diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index 9c5322a19..af9f6b554 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -18,6 +18,11 @@ struct SceneRef { uint32_t id; uint32_t sceneType; //0 = general, 1 = audio? std::string name; + NiPoint3 unknown1; + float unknown2; + uint8_t color_r; + uint8_t color_g; + uint8_t color_b; Level* level; std::map triggers; }; @@ -30,6 +35,7 @@ struct SceneTransitionInfo { struct SceneTransition { std::string name; std::vector points; + float width; }; struct MovingPlatformPathWaypoint { @@ -100,7 +106,7 @@ enum class PropertyType : int32_t { Headspace = 3 }; -enum class PropertyRentalTimeUnit : int32_t { +enum class PropertyRentalPeriod : uint32_t { Forever = 0, Seconds = 1, Minutes = 2, @@ -111,7 +117,7 @@ enum class PropertyRentalTimeUnit : int32_t { Years = 7 }; -enum class PropertyAchievmentRequired : int32_t { +enum class PropertyAchievmentRequired : uint32_t { None = 0, Builder = 1, Craftsman = 2, @@ -133,13 +139,14 @@ struct MovingPlatformPath { struct PropertyPath { PropertyPathType pathType; int32_t price; - PropertyRentalTimeUnit rentalTimeUnit; + uint32_t rentalTime; uint64_t associatedZone; std::string displayName; std::string displayDesc; PropertyType type; - int32_t cloneLimit; + uint32_t cloneLimit; float repMultiplier; + PropertyRentalPeriod rentalPeriod; PropertyAchievmentRequired achievementRequired; NiPoint3 playerZoneCoords; float maxBuildHeight; @@ -176,15 +183,17 @@ struct Path { class Zone { public: - enum class ZoneFileFormatVersion : uint32_t { //Times are guessed. - PreAlpha = 0x20, - EarlyAlpha = 0x23, - Alpha = 0x24, - LateAlpha = 0x25, - Beta = 0x26, - Launch = 0x27, - Auramar = 0x28, - Latest = 0x29 + enum class FileFormatVersion : uint32_t { //Times are guessed. + PrePreAlpha = 30, + PreAlpha = 32, + LatePreAlpha = 33, + EarlyAlpha = 35, + Alpha = 36, + LateAlpha = 37, + Beta = 38, + Launch = 39, + Auramar = 40, + Latest = 41 }; public: @@ -220,7 +229,7 @@ class Zone { uint32_t m_NumberOfScenesLoaded; uint32_t m_NumberOfObjectsLoaded; uint32_t m_NumberOfSceneTransitionsLoaded; - ZoneFileFormatVersion m_ZoneFileFormatVersion; + FileFormatVersion m_FileFormatVersion; uint32_t m_CheckSum; uint32_t m_WorldID; //should be equal to the MapID NiPoint3 m_Spawnpoint; diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 51f6e640f..7b352a570 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -277,7 +277,7 @@ void dZoneManager::LoadWorldConfig() { m_WorldConfig->characterMaxSlope = worldConfig.getFloatField("character_max_slope"); m_WorldConfig->defaultRespawnTime = worldConfig.getFloatField("defaultrespawntime"); m_WorldConfig->missionTooltipTimeout = worldConfig.getFloatField("mission_tooltip_timeout"); - m_WorldConfig->vendorBuyMultiplier = worldConfig.getFloatField("vendor_buy_multiplier"); + m_WorldConfig->vendorBuyMultiplier = worldConfig.getFloatField("vendor_buy_multiplier", 0.1); m_WorldConfig->petFollowRadius = worldConfig.getFloatField("pet_follow_radius"); m_WorldConfig->characterEyeHeight = worldConfig.getFloatField("character_eye_height"); m_WorldConfig->flightVerticalVelocity = worldConfig.getFloatField("flight_vertical_velocity"); diff --git a/docker-compose.yml b/docker-compose.yml index 4b997e532..d8c3c40ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: - DATABASE_USER=${MARIADB_USER:-darkflame} - DATABASE_PASSWORD=${MARIADB_PASSWORD:-darkflame} - EXTERNAL_IP=${EXTERNAL_IP:-darkflame} + - BUILD_VERSION=${BUILD_VERSION:?171022} volumes: - ${CLIENT_PATH:?missing_client_path}:/client - shared_configs:/docker/ diff --git a/docker/Dockerfile b/docker/Dockerfile index c5638a205..39153110c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -32,13 +32,12 @@ COPY .clang-* CMake* LICENSE /build/ ARG BUILD_THREADS=1 ARG BUILD_VERSION=171022 -RUN echo "Build server" && \ - mkdir -p cmake_build && \ - cd cmake_build && \ - sed -i -e "s/NET_VERSION=.*/NET_VERSION=${BUILD_VERSION}/g" ../CMakeVariables.txt && \ - sed -i -e "s/__maria_db_connector_compile_jobs__=.*/__maria_db_connector_compile_jobs__=${BUILD_THREADS}/g" ../CMakeVariables.txt && \ - cmake .. -DCMAKE_BUILD_RPATH_USE_ORIGIN=TRUE && \ - make -j $BUILD_THREADS +RUN echo "Build server" +RUN sed -i -e "s/__maria_db_connector_compile_jobs__=.*/__maria_db_connector_compile_jobs__=${BUILD_THREADS}/g" CMakeVariables.txt +RUN mkdir -p cmake_build +RUN cd cmake_build && \ + cmake .. -DCMAKE_BUILD_RPATH_USE_ORIGIN=TRUE && \ + make -j$BUILD_THREADS FROM gcc:12 as runtime diff --git a/docker/setup.sh b/docker/setup.sh index ade67d2e4..1944bbba9 100755 --- a/docker/setup.sh +++ b/docker/setup.sh @@ -17,9 +17,8 @@ function update_database_ini_values_for() { update_ini $INI_FILE mysql_database $DATABASE update_ini $INI_FILE mysql_username $DATABASE_USER update_ini $INI_FILE mysql_password $DATABASE_PASSWORD - if [[ "$INI_FILE" != "worldconfig.ini" ]]; then - update_ini $INI_FILE external_ip $EXTERNAL_IP - fi + update_ini $INI_FILE client_net_version $BUILD_VERSION + update_ini $INI_FILE external_ip $EXTERNAL_IP } function update_ini_values() { diff --git a/docs/Commands.md b/docs/Commands.md index c997c3c4f..85edfd3b4 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -105,7 +105,7 @@ These commands are primarily for development and testing. The usage of many of t |unlock-emote|`/unlock-emote `|Unlocks for your character the emote of the given id.|8| |Set Level|`/setlevel (username)`|Sets the using entities level to the requested level. Takes an optional parameter of an in-game players username to set the level of.|8| |crash|`/crash`|Crashes the server.|9| -|rollloot|`/rollloot `|Rolls loot matrix.|9| +|rollloot|`/rollloot `|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9| ## Detailed `/inspect` Usage diff --git a/migrations/dlu/10_Security_updates.sql b/migrations/dlu/10_Security_updates.sql new file mode 100644 index 000000000..4cbf51a0c --- /dev/null +++ b/migrations/dlu/10_Security_updates.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS player_cheat_detections ( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + account_id INT REFERENCES accounts(id), + name TEXT REFERENCES charinfo(name), + violation_msg TEXT NOT NULL, + violation_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), + violation_system_address TEXT NOT NULL +); diff --git a/migrations/dlu/11_fix_cheat_detection_table.sql b/migrations/dlu/11_fix_cheat_detection_table.sql new file mode 100644 index 000000000..214648344 --- /dev/null +++ b/migrations/dlu/11_fix_cheat_detection_table.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `player_cheat_detections`; +CREATE TABLE IF NOT EXISTS player_cheat_detections ( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + account_id INT REFERENCES accounts(id), + name TEXT NOT NULL, + violation_msg TEXT NOT NULL, + violation_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), + violation_system_address TEXT NOT NULL +); diff --git a/resources/sharedconfig.ini b/resources/sharedconfig.ini index d2c43d11e..ad587b184 100644 --- a/resources/sharedconfig.ini +++ b/resources/sharedconfig.ini @@ -36,3 +36,10 @@ maximum_outgoing_bandwidth=80000 # from 512 <= maximum_mtu_size <= 1492 so make sure to keep this # value within that range. maximum_mtu_size=1228 + +# The client network version to allow to connect to this server. +# Client's that do not match this value will be kicked from the server. +# If you are using a Darkflame Universe client, set this value to 171023. +# This cannot just be any arbitrary number. This has to match the same value that is in your client. +# If you do not know what this value is, default it to 171022. +client_net_version=171022 diff --git a/resources/worldconfig.ini b/resources/worldconfig.ini index b05614b45..c0a0a10aa 100644 --- a/resources/worldconfig.ini +++ b/resources/worldconfig.ini @@ -61,3 +61,6 @@ hardcore_lose_uscore_on_death_percent=10 # Allow civilian players the ability to turn the nameplate above their head off. Must be exactly 1 to be enabled for civilians. allow_nameplate_off=0 + +# Turn logging of IP addresses for anti-cheat reporting on (1) or off(0) +log_ip_addresses_for_anti_cheat=1 diff --git a/tests/dCommonTests/CMakeLists.txt b/tests/dCommonTests/CMakeLists.txt index a345863d8..006102fa4 100644 --- a/tests/dCommonTests/CMakeLists.txt +++ b/tests/dCommonTests/CMakeLists.txt @@ -5,6 +5,8 @@ set(DCOMMONTEST_SOURCES "TestLDFFormat.cpp" "TestNiPoint3.cpp" "TestEncoding.cpp" + "TestLUString.cpp" + "TestLUWString.cpp" "dCommonDependencies.cpp" ) diff --git a/tests/dCommonTests/TestLUString.cpp b/tests/dCommonTests/TestLUString.cpp new file mode 100644 index 000000000..3abec9854 --- /dev/null +++ b/tests/dCommonTests/TestLUString.cpp @@ -0,0 +1,121 @@ +#include + +#include "dCommonVars.h" + +TEST(LUString33Test, SerializeWriteTestOld) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 33; i++) testString += "a"; + for (const auto& c : testString) bitStream.Write(c); + std::string result; + char c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeWriteTestOldPartial) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 15; i++) testString += "a"; + for (const auto& c : testString) bitStream.Write(c); + for (int i = 0; i < 18; i++) bitStream.Write(0); + std::string result; + char c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeWriteTestNew) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 33; i++) testString += "a"; + bitStream.Write(LUString(testString, 33)); + std::string result; + char c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeWriteTestNewPartial) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 15; i++) testString += "a"; + bitStream.Write(LUString(testString, 33)); + std::string result; + char c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeReadTestOld) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 33; i++) testString += "a"; + for (const auto& c : testString) bitStream.Write(c); + std::string result; + char c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeReadTestOldPartial) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 15; i++) testString += "a"; + for (const auto& c : testString) bitStream.Write(c); + for (int i = 0; i < 18; i++) bitStream.Write(0); + std::string result; + char c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUString33Test, SerializeReadTestNew) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 33; i++) testString += "a"; + bitStream.Write(LUString(testString, 33)); + LUString result(33); + ASSERT_EQ(result.size, 33); + ASSERT_TRUE(bitStream.Read(result)); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result.string, testString); +} + +TEST(LUString33Test, SerializeReadTestNewPartial) { + CBITSTREAM; + std::string testString; + for (int i = 0; i < 15; i++) testString += "a"; + bitStream.Write(LUString(testString, 33)); + LUString result(33); + ASSERT_EQ(result.size, 33); + ASSERT_TRUE(bitStream.Read(result)); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result.string, testString); +} diff --git a/tests/dCommonTests/TestLUWString.cpp b/tests/dCommonTests/TestLUWString.cpp new file mode 100644 index 000000000..a16dd9119 --- /dev/null +++ b/tests/dCommonTests/TestLUWString.cpp @@ -0,0 +1,121 @@ +#include + +#include "dCommonVars.h" + +TEST(LUWString33Test, SerializeWriteTestOld) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 33; i++) testString += u'ü'; + for (const auto& c : testString) bitStream.Write(c); + std::u16string result; + char16_t c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeWriteTestOldPartial) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 15; i++) testString += u'ü'; + for (const auto& c : testString) bitStream.Write(c); + for (int i = 0; i < 18; i++) bitStream.Write(0); + std::u16string result; + char16_t c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeWriteTestNew) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 33; i++) testString += u'ü'; + bitStream.Write(LUWString(testString, 33)); + std::u16string result; + char16_t c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeWriteTestNewPartial) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 15; i++) testString += u'ü'; + bitStream.Write(LUWString(testString, 33)); + std::u16string result; + char16_t c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeReadTestOld) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 33; i++) testString += u'ü'; + for (const auto& c : testString) bitStream.Write(c); + std::u16string result; + char16_t c; + while (bitStream.Read(c)) result += c; + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeReadTestOldPartial) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 15; i++) testString += u'ü'; + for (const auto& c : testString) bitStream.Write(c); + for (int i = 0; i < 18; i++) bitStream.Write(0); + std::u16string result; + char16_t c; + int nulls = 18; + while (bitStream.Read(c)){ + if (c == 0) { + nulls--; + continue; + } + result += c; + } + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(nulls, 0); + ASSERT_EQ(result, testString); +} + +TEST(LUWString33Test, SerializeReadTestNew) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 33; i++) testString += u'ü'; + bitStream.Write(LUWString(testString, 33)); + LUWString result(33); + ASSERT_EQ(result.size, 33); + ASSERT_TRUE(bitStream.Read(result)); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result.string, testString); +} + +TEST(LUWString33Test, SerializeReadTestNewPartial) { + CBITSTREAM; + std::u16string testString; + for (int i = 0; i < 15; i++) testString += u'ü'; + bitStream.Write(LUWString(testString, 33)); + LUWString result(33); + ASSERT_EQ(result.size, 33); + ASSERT_TRUE(bitStream.Read(result)); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(result.string, testString); +} diff --git a/tests/dCommonTests/TestNiPoint3.cpp b/tests/dCommonTests/TestNiPoint3.cpp index 33cd51d2a..fbc98eb09 100644 --- a/tests/dCommonTests/TestNiPoint3.cpp +++ b/tests/dCommonTests/TestNiPoint3.cpp @@ -12,3 +12,12 @@ TEST(dCommonTests, NiPoint3Test) { // Check what unitize does to a vector of length 0 ASSERT_EQ(NiPoint3::ZERO.Unitize(), NiPoint3::ZERO); } + +TEST(dCommonTests, NiPoint3OperatorTest) { + NiPoint3 a(1, 2, 3); + NiPoint3 b(4, 5, 6); + a += b; + EXPECT_FLOAT_EQ(a.x, 5); + EXPECT_FLOAT_EQ(a.y, 7); + EXPECT_FLOAT_EQ(a.z, 9); +} diff --git a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp index db9c033a2..85507b4ee 100644 --- a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp +++ b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp @@ -41,7 +41,7 @@ class DestroyableTest : public GameDependenciesTest { * Test Construction of a DestroyableComponent */ TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) { - destroyableComponent->Serialize(&bitStream, true, flags); + destroyableComponent->Serialize(&bitStream, true); // Assert that the full number of bits are present ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 748); { @@ -171,7 +171,7 @@ TEST_F(DestroyableTest, DestroyableComponentSerializeTest) { destroyableComponent->SetMaxHealth(1233.0f); // Now we test a serialization for correctness. - destroyableComponent->Serialize(&bitStream, false, flags); + destroyableComponent->Serialize(&bitStream, false); ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 422); { // Now read in the full serialized BitStream diff --git a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt index 54c43777d..e1c4884cc 100644 --- a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt +++ b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt @@ -1,5 +1,6 @@ SET(DGAMEMESSAGES_TESTS - "GameMessageTests.cpp") + "GameMessageTests.cpp" + "LegacyGameMessageTests.cpp") # Get the folder name and prepend it to the files above get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME) diff --git a/tests/dGameTests/dGameMessagesTests/LegacyGameMessageTests.cpp b/tests/dGameTests/dGameMessagesTests/LegacyGameMessageTests.cpp new file mode 100644 index 000000000..0226b0adb --- /dev/null +++ b/tests/dGameTests/dGameMessagesTests/LegacyGameMessageTests.cpp @@ -0,0 +1,298 @@ +#include +#include "eGameMessageType.h" + +TEST(LegacyGameMessageTests, AssertLegacyGmValues) { + EXPECT_EQ(eGameMessageType::TELEPORT, (eGameMessageType)19); + EXPECT_EQ(eGameMessageType::SET_PLAYER_CONTROL_SCHEME, (eGameMessageType)26); + EXPECT_EQ(eGameMessageType::DROP_CLIENT_LOOT, (eGameMessageType)30); + EXPECT_EQ(eGameMessageType::DIE, (eGameMessageType)37); + EXPECT_EQ(eGameMessageType::REQUEST_DIE, (eGameMessageType)38); + EXPECT_EQ(eGameMessageType::PLAY_EMOTE, (eGameMessageType)41); + EXPECT_EQ(eGameMessageType::PLAY_ANIMATION, (eGameMessageType)43); + EXPECT_EQ(eGameMessageType::CONTROL_BEHAVIORS, (eGameMessageType)48); + EXPECT_EQ(eGameMessageType::SET_NAME, (eGameMessageType)72); + EXPECT_EQ(eGameMessageType::ECHO_START_SKILL, (eGameMessageType)118); + EXPECT_EQ(eGameMessageType::START_SKILL, (eGameMessageType)119); + EXPECT_EQ(eGameMessageType::VERIFY_ACK, (eGameMessageType)121); + EXPECT_EQ(eGameMessageType::ADD_SKILL, (eGameMessageType)127); + EXPECT_EQ(eGameMessageType::REMOVE_SKILL, (eGameMessageType)128); + EXPECT_EQ(eGameMessageType::SET_CURRENCY, (eGameMessageType)133); + EXPECT_EQ(eGameMessageType::PICKUP_CURRENCY, (eGameMessageType)137); + EXPECT_EQ(eGameMessageType::PICKUP_ITEM, (eGameMessageType)139); + EXPECT_EQ(eGameMessageType::TEAM_PICKUP_ITEM, (eGameMessageType)140); + EXPECT_EQ(eGameMessageType::PLAY_FX_EFFECT, (eGameMessageType)154); + EXPECT_EQ(eGameMessageType::STOP_FX_EFFECT, (eGameMessageType)155); + EXPECT_EQ(eGameMessageType::REQUEST_RESURRECT, (eGameMessageType)159); + EXPECT_EQ(eGameMessageType::RESURRECT, (eGameMessageType)160); + EXPECT_EQ(eGameMessageType::PUSH_EQUIPPED_ITEMS_STATE, (eGameMessageType)191); + EXPECT_EQ(eGameMessageType::POP_EQUIPPED_ITEMS_STATE, (eGameMessageType)192); + EXPECT_EQ(eGameMessageType::SET_GM_LEVEL, (eGameMessageType)193); + EXPECT_EQ(eGameMessageType::SET_STUNNED, (eGameMessageType)198); + EXPECT_EQ(eGameMessageType::SET_STUN_IMMUNITY, (eGameMessageType)200); + EXPECT_EQ(eGameMessageType::KNOCKBACK, (eGameMessageType)202); + EXPECT_EQ(eGameMessageType::REBUILD_CANCEL, (eGameMessageType)209); + EXPECT_EQ(eGameMessageType::ENABLE_REBUILD, (eGameMessageType)213); + EXPECT_EQ(eGameMessageType::MOVE_ITEM_IN_INVENTORY, (eGameMessageType)224); + EXPECT_EQ(eGameMessageType::ADD_ITEM_TO_INVENTORY_CLIENT_SYNC, (eGameMessageType)227); + EXPECT_EQ(eGameMessageType::REMOVE_ITEM_FROM_INVENTORY, (eGameMessageType)230); + EXPECT_EQ(eGameMessageType::EQUIP_INVENTORY, (eGameMessageType)231); + EXPECT_EQ(eGameMessageType::UN_EQUIP_INVENTORY, (eGameMessageType)233); + EXPECT_EQ(eGameMessageType::OFFER_MISSION, (eGameMessageType)248); + EXPECT_EQ(eGameMessageType::RESPOND_TO_MISSION, (eGameMessageType)249); + EXPECT_EQ(eGameMessageType::NOTIFY_MISSION, (eGameMessageType)254); + EXPECT_EQ(eGameMessageType::NOTIFY_MISSION_TASK, (eGameMessageType)255); + EXPECT_EQ(eGameMessageType::REBUILD_NOTIFY_STATE, (eGameMessageType)336); + EXPECT_EQ(eGameMessageType::TERMINATE_INTERACTION, (eGameMessageType)357); + EXPECT_EQ(eGameMessageType::SERVER_TERMINATE_INTERACTION, (eGameMessageType)358); + EXPECT_EQ(eGameMessageType::REQUEST_USE, (eGameMessageType)364); + EXPECT_EQ(eGameMessageType::VENDOR_OPEN_WINDOW, (eGameMessageType)369); + EXPECT_EQ(eGameMessageType::BUY_FROM_VENDOR, (eGameMessageType)373); + EXPECT_EQ(eGameMessageType::SELL_TO_VENDOR, (eGameMessageType)374); + EXPECT_EQ(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG, (eGameMessageType)383); + EXPECT_EQ(eGameMessageType::SET_INVENTORY_SIZE, (eGameMessageType)389); + EXPECT_EQ(eGameMessageType::ACKNOWLEDGE_POSSESSION, (eGameMessageType)391); + EXPECT_EQ(eGameMessageType::SET_SHOOTING_GALLERY_PARAMS, (eGameMessageType)400); + EXPECT_EQ(eGameMessageType::REQUEST_ACTIVITY_START_STOP, (eGameMessageType)402); + EXPECT_EQ(eGameMessageType::REQUEST_ACTIVITY_ENTER, (eGameMessageType)403); + EXPECT_EQ(eGameMessageType::REQUEST_ACTIVITY_EXIT, (eGameMessageType)404); + EXPECT_EQ(eGameMessageType::ACTIVITY_ENTER, (eGameMessageType)405); + EXPECT_EQ(eGameMessageType::ACTIVITY_EXIT, (eGameMessageType)406); + EXPECT_EQ(eGameMessageType::ACTIVITY_START, (eGameMessageType)407); + EXPECT_EQ(eGameMessageType::ACTIVITY_STOP, (eGameMessageType)408); + EXPECT_EQ(eGameMessageType::SHOOTING_GALLERY_CLIENT_AIM_UPDATE, (eGameMessageType)409); + EXPECT_EQ(eGameMessageType::SHOOTING_GALLERY_FIRE, (eGameMessageType)411); + EXPECT_EQ(eGameMessageType::REQUEST_VENDOR_STATUS_UPDATE, (eGameMessageType)416); + EXPECT_EQ(eGameMessageType::VENDOR_STATUS_UPDATE, (eGameMessageType)417); + EXPECT_EQ(eGameMessageType::NOTIFY_CLIENT_SHOOTING_GALLERY_SCORE, (eGameMessageType)425); + EXPECT_EQ(eGameMessageType::CONSUME_CLIENT_ITEM, (eGameMessageType)427); + EXPECT_EQ(eGameMessageType::CLIENT_ITEM_CONSUMED, (eGameMessageType)428); + EXPECT_EQ(eGameMessageType::UPDATE_SHOOTING_GALLERY_ROTATION, (eGameMessageType)448); + EXPECT_EQ(eGameMessageType::SET_FLAG, (eGameMessageType)471); + EXPECT_EQ(eGameMessageType::NOTIFY_CLIENT_FLAG_CHANGE, (eGameMessageType)472); + EXPECT_EQ(eGameMessageType::VENDOR_TRANSACTION_RESULT, (eGameMessageType)476); + EXPECT_EQ(eGameMessageType::HAS_BEEN_COLLECTED, (eGameMessageType)486); + EXPECT_EQ(eGameMessageType::DISPLAY_CHAT_BUBBLE, (eGameMessageType)495); + EXPECT_EQ(eGameMessageType::SPAWN_PET, (eGameMessageType)498); + EXPECT_EQ(eGameMessageType::DESPAWN_PET, (eGameMessageType)499); + EXPECT_EQ(eGameMessageType::PLAYER_LOADED, (eGameMessageType)505); + EXPECT_EQ(eGameMessageType::PLAYER_READY, (eGameMessageType)509); + EXPECT_EQ(eGameMessageType::REQUEST_LINKED_MISSION, (eGameMessageType)515); + EXPECT_EQ(eGameMessageType::INVALID_ZONE_TRANSFER_LIST, (eGameMessageType)519); + EXPECT_EQ(eGameMessageType::MISSION_DIALOGUE_OK, (eGameMessageType)520); + EXPECT_EQ(eGameMessageType::DISPLAY_MESSAGE_BOX, (eGameMessageType)529); + EXPECT_EQ(eGameMessageType::MESSAGE_BOX_RESPOND, (eGameMessageType)530); + EXPECT_EQ(eGameMessageType::CHOICE_BOX_RESPOND, (eGameMessageType)531); + EXPECT_EQ(eGameMessageType::SMASH, (eGameMessageType)537); + EXPECT_EQ(eGameMessageType::UN_SMASH, (eGameMessageType)538); + EXPECT_EQ(eGameMessageType::PLACE_MODEL_RESPONSE, (eGameMessageType)547); + EXPECT_EQ(eGameMessageType::SET_SHOOTING_GALLERY_RETICULE_EFFECT, (eGameMessageType)546); + EXPECT_EQ(eGameMessageType::SET_JET_PACK_MODE, (eGameMessageType)561); + EXPECT_EQ(eGameMessageType::REGISTER_PET_ID, (eGameMessageType)565); + EXPECT_EQ(eGameMessageType::REGISTER_PET_DBID, (eGameMessageType)566); + EXPECT_EQ(eGameMessageType::SHOW_ACTIVITY_COUNTDOWN, (eGameMessageType)568); + EXPECT_EQ(eGameMessageType::START_ACTIVITY_TIME, (eGameMessageType)576); + EXPECT_EQ(eGameMessageType::ACTIVITY_PAUSE, (eGameMessageType)602); + EXPECT_EQ(eGameMessageType::USE_NON_EQUIPMENT_ITEM, (eGameMessageType)603); + EXPECT_EQ(eGameMessageType::USE_ITEM_RESULT, (eGameMessageType)607); + EXPECT_EQ(eGameMessageType::COMMAND_PET, (eGameMessageType)640); + EXPECT_EQ(eGameMessageType::PET_RESPONSE, (eGameMessageType)641); + EXPECT_EQ(eGameMessageType::REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA, (eGameMessageType)648); + EXPECT_EQ(eGameMessageType::SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA, (eGameMessageType)649); + EXPECT_EQ(eGameMessageType::NOTIFY_OBJECT, (eGameMessageType)656); + EXPECT_EQ(eGameMessageType::CLIENT_NOTIFY_PET, (eGameMessageType)659); + EXPECT_EQ(eGameMessageType::NOTIFY_PET, (eGameMessageType)660); + EXPECT_EQ(eGameMessageType::NOTIFY_PET_TAMING_MINIGAME, (eGameMessageType)661); + EXPECT_EQ(eGameMessageType::START_SERVER_PET_MINIGAME_TIMER, (eGameMessageType)662); + EXPECT_EQ(eGameMessageType::CLIENT_EXIT_TAMING_MINIGAME, (eGameMessageType)663); + EXPECT_EQ(eGameMessageType::PET_NAME_CHANGED, (eGameMessageType)686); + EXPECT_EQ(eGameMessageType::PET_TAMING_MINIGAME_RESULT, (eGameMessageType)667); + EXPECT_EQ(eGameMessageType::PET_TAMING_TRY_BUILD_RESULT, (eGameMessageType)668); + EXPECT_EQ(eGameMessageType::NOTIFY_TAMING_BUILD_SUCCESS, (eGameMessageType)673); + EXPECT_EQ(eGameMessageType::NOTIFY_TAMING_MODEL_LOADED_ON_SERVER, (eGameMessageType)674); + EXPECT_EQ(eGameMessageType::ACTIVATE_BUBBLE_BUFF, (eGameMessageType)678); + EXPECT_EQ(eGameMessageType::DECTIVATE_BUBBLE_BUFF, (eGameMessageType)679); + EXPECT_EQ(eGameMessageType::ADD_PET_TO_PLAYER, (eGameMessageType)681); + EXPECT_EQ(eGameMessageType::REQUEST_SET_PET_NAME, (eGameMessageType)683); + EXPECT_EQ(eGameMessageType::SET_PET_NAME, (eGameMessageType)684); + EXPECT_EQ(eGameMessageType::NOTIFY_TAMING_PUZZLE_SELECTED, (eGameMessageType)675); + EXPECT_EQ(eGameMessageType::SHOW_PET_ACTION_BUTTON, (eGameMessageType)692); + EXPECT_EQ(eGameMessageType::SET_EMOTE_LOCK_STATE, (eGameMessageType)693); + EXPECT_EQ(eGameMessageType::USE_ITEM_REQUIREMENTS_RESPONSE, (eGameMessageType)703); + EXPECT_EQ(eGameMessageType::PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT, (eGameMessageType)713); + EXPECT_EQ(eGameMessageType::DOWNLOAD_PROPERTY_DATA, (eGameMessageType)716); + EXPECT_EQ(eGameMessageType::QUERY_PROPERTY_DATA, (eGameMessageType)717); + EXPECT_EQ(eGameMessageType::PROPERTY_EDITOR_BEGIN, (eGameMessageType)724); + EXPECT_EQ(eGameMessageType::PROPERTY_EDITOR_END, (eGameMessageType)725); + EXPECT_EQ(eGameMessageType::IS_MINIFIG_IN_A_BUBBLE, (eGameMessageType)729); + EXPECT_EQ(eGameMessageType::START_PATHING, (eGameMessageType)733); + EXPECT_EQ(eGameMessageType::ACTIVATE_BUBBLE_BUFF_FROM_SERVER, (eGameMessageType)734); + EXPECT_EQ(eGameMessageType::DEACTIVATE_BUBBLE_BUFF_FROM_SERVER, (eGameMessageType)735); + EXPECT_EQ(eGameMessageType::NOTIFY_CLIENT_ZONE_OBJECT, (eGameMessageType)737); + EXPECT_EQ(eGameMessageType::UPDATE_REPUTATION, (eGameMessageType)746); + EXPECT_EQ(eGameMessageType::PROPERTY_RENTAL_RESPONSE, (eGameMessageType)750); + EXPECT_EQ(eGameMessageType::REQUEST_PLATFORM_RESYNC, (eGameMessageType)760); + EXPECT_EQ(eGameMessageType::PLATFORM_RESYNC, (eGameMessageType)761); + EXPECT_EQ(eGameMessageType::PLAY_CINEMATIC, (eGameMessageType)762); + EXPECT_EQ(eGameMessageType::END_CINEMATIC, (eGameMessageType)763); + EXPECT_EQ(eGameMessageType::CINEMATIC_UPDATE, (eGameMessageType)764); + EXPECT_EQ(eGameMessageType::TOGGLE_GHOST_REFERENCE_OVERRIDE, (eGameMessageType)767); + EXPECT_EQ(eGameMessageType::SET_GHOST_REFERENCE_POSITION, (eGameMessageType)768); + EXPECT_EQ(eGameMessageType::FIRE_EVENT_SERVER_SIDE, (eGameMessageType)770); + EXPECT_EQ(eGameMessageType::SCRIPT_NETWORK_VAR_UPDATE, (eGameMessageType)781); + EXPECT_EQ(eGameMessageType::UPDATE_MODEL_FROM_CLIENT, (eGameMessageType)793); + EXPECT_EQ(eGameMessageType::DELETE_MODEL_FROM_CLIENT, (eGameMessageType)794); + EXPECT_EQ(eGameMessageType::PLAY_ND_AUDIO_EMITTER, (eGameMessageType)821); + EXPECT_EQ(eGameMessageType::PLAY2_D_AMBIENT_SOUND, (eGameMessageType)831); + EXPECT_EQ(eGameMessageType::ENTER_PROPERTY1, (eGameMessageType)840); + EXPECT_EQ(eGameMessageType::ENTER_PROPERTY2, (eGameMessageType)841); + EXPECT_EQ(eGameMessageType::PROPERTY_ENTRANCE_SYNC, (eGameMessageType)842); + EXPECT_EQ(eGameMessageType::PROPERTY_SELECT_QUERY, (eGameMessageType)845); + EXPECT_EQ(eGameMessageType::PARSE_CHAT_MESSAGE, (eGameMessageType)850); + EXPECT_EQ(eGameMessageType::BROADCAST_TEXT_TO_CHATBOX, (eGameMessageType)858); + EXPECT_EQ(eGameMessageType::OPEN_PROPERTY_MANAGEMENT, (eGameMessageType)860); + EXPECT_EQ(eGameMessageType::OPEN_PROPERTY_VENDOR, (eGameMessageType)861); + EXPECT_EQ(eGameMessageType::UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK, (eGameMessageType)863); + EXPECT_EQ(eGameMessageType::CLIENT_TRADE_REQUEST, (eGameMessageType)868); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_REQUEST, (eGameMessageType)869); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_INVITE, (eGameMessageType)870); + EXPECT_EQ(eGameMessageType::CLIENT_TRADE_REPLY, (eGameMessageType)871); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_REPLY, (eGameMessageType)872); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_INITIAL_REPLY, (eGameMessageType)873); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_FINAL_REPLY, (eGameMessageType)874); + EXPECT_EQ(eGameMessageType::CLIENT_TRADE_UPDATE, (eGameMessageType)875); + EXPECT_EQ(eGameMessageType::SERVER_SIDE_TRADE_UPDATE, (eGameMessageType)876); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_UPDATE, (eGameMessageType)877); + EXPECT_EQ(eGameMessageType::CLIENT_TRADE_CANCEL, (eGameMessageType)878); + EXPECT_EQ(eGameMessageType::CLIENT_SIDE_TRADE_CANCEL, (eGameMessageType)879); + EXPECT_EQ(eGameMessageType::CLIENT_TRADE_ACCEPT, (eGameMessageType)880); + EXPECT_EQ(eGameMessageType::SERVER_SIDE_TRADE_ACCEPT, (eGameMessageType)881); + EXPECT_EQ(eGameMessageType::SERVER_SIDE_TRADE_CANCEL, (eGameMessageType)882); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_CANCEL, (eGameMessageType)883); + EXPECT_EQ(eGameMessageType::SERVER_TRADE_ACCEPT, (eGameMessageType)884); + EXPECT_EQ(eGameMessageType::READY_FOR_UPDATES, (eGameMessageType)888); + EXPECT_EQ(eGameMessageType::ORIENT_TO_OBJECT, (eGameMessageType)905); + EXPECT_EQ(eGameMessageType::ORIENT_TO_POSITION, (eGameMessageType)906); + EXPECT_EQ(eGameMessageType::ORIENT_TO_ANGLE, (eGameMessageType)907); + EXPECT_EQ(eGameMessageType::BOUNCER_ACTIVE_STATUS, (eGameMessageType)942); + EXPECT_EQ(eGameMessageType::UN_USE_BBB_MODEL, (eGameMessageType)999); + EXPECT_EQ(eGameMessageType::BBB_LOAD_ITEM_REQUEST, (eGameMessageType)1000); + EXPECT_EQ(eGameMessageType::BBB_SAVE_REQUEST, (eGameMessageType)1001); + EXPECT_EQ(eGameMessageType::BBB_SAVE_RESPONSE, (eGameMessageType)1005); + EXPECT_EQ(eGameMessageType::NOTIFY_CLIENT_OBJECT, (eGameMessageType)1042); + EXPECT_EQ(eGameMessageType::DISPLAY_ZONE_SUMMARY, (eGameMessageType)1043); + EXPECT_EQ(eGameMessageType::ZONE_SUMMARY_DISMISSED, (eGameMessageType)1044); + EXPECT_EQ(eGameMessageType::ACTIVITY_STATE_CHANGE_REQUEST, (eGameMessageType)1053); + EXPECT_EQ(eGameMessageType::MODIFY_PLAYER_ZONE_STATISTIC, (eGameMessageType)1046); + EXPECT_EQ(eGameMessageType::START_BUILDING_WITH_ITEM, (eGameMessageType)1057); + EXPECT_EQ(eGameMessageType::START_ARRANGING_WITH_ITEM, (eGameMessageType)1061); + EXPECT_EQ(eGameMessageType::FINISH_ARRANGING_WITH_ITEM, (eGameMessageType)1062); + EXPECT_EQ(eGameMessageType::DONE_ARRANGING_WITH_ITEM, (eGameMessageType)1063); + EXPECT_EQ(eGameMessageType::SET_BUILD_MODE, (eGameMessageType)1068); + EXPECT_EQ(eGameMessageType::BUILD_MODE_SET, (eGameMessageType)1069); + EXPECT_EQ(eGameMessageType::SET_BUILD_MODE_CONFIRMED, (eGameMessageType)1073); + EXPECT_EQ(eGameMessageType::NOTIFY_CLIENT_FAILED_PRECONDITION, (eGameMessageType)1081); + EXPECT_EQ(eGameMessageType::MOVE_ITEM_BETWEEN_INVENTORY_TYPES, (eGameMessageType)1093); + EXPECT_EQ(eGameMessageType::MODULAR_BUILD_BEGIN, (eGameMessageType)1094); + EXPECT_EQ(eGameMessageType::MODULAR_BUILD_END, (eGameMessageType)1095); + EXPECT_EQ(eGameMessageType::MODULAR_BUILD_MOVE_AND_EQUIP, (eGameMessageType)1096); + EXPECT_EQ(eGameMessageType::MODULAR_BUILD_FINISH, (eGameMessageType)1097); + EXPECT_EQ(eGameMessageType::REPORT_BUG, (eGameMessageType)1198); + EXPECT_EQ(eGameMessageType::MISSION_DIALOGUE_CANCELLED, (eGameMessageType)1129); + EXPECT_EQ(eGameMessageType::ECHO_SYNC_SKILL, (eGameMessageType)1144); + EXPECT_EQ(eGameMessageType::SYNC_SKILL, (eGameMessageType)1145); + EXPECT_EQ(eGameMessageType::REQUEST_SERVER_PROJECTILE_IMPACT, (eGameMessageType)1148); + EXPECT_EQ(eGameMessageType::DO_CLIENT_PROJECTILE_IMPACT, (eGameMessageType)1151); + EXPECT_EQ(eGameMessageType::MODULAR_BUILD_CONVERT_MODEL, (eGameMessageType)1155); + EXPECT_EQ(eGameMessageType::SET_PLAYER_ALLOWED_RESPAWN, (eGameMessageType)1165); + EXPECT_EQ(eGameMessageType::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT, (eGameMessageType)1184); + EXPECT_EQ(eGameMessageType::UI_MESSAGE_SERVER_TO_ALL_CLIENTS, (eGameMessageType)1185); + EXPECT_EQ(eGameMessageType::PET_TAMING_TRY_BUILD, (eGameMessageType)1197); + EXPECT_EQ(eGameMessageType::REQUEST_SMASH_PLAYER, (eGameMessageType)1202); + EXPECT_EQ(eGameMessageType::FIRE_EVENT_CLIENT_SIDE, (eGameMessageType)1213); + EXPECT_EQ(eGameMessageType::TOGGLE_GM_INVIS, (eGameMessageType)1218); + EXPECT_EQ(eGameMessageType::CHANGE_OBJECT_WORLD_STATE, (eGameMessageType)1223); + EXPECT_EQ(eGameMessageType::VEHICLE_LOCK_INPUT, (eGameMessageType)1230); + EXPECT_EQ(eGameMessageType::VEHICLE_UNLOCK_INPUT, (eGameMessageType)1231); + EXPECT_EQ(eGameMessageType::RACING_RESET_PLAYER_TO_LAST_RESET, (eGameMessageType)1252); + EXPECT_EQ(eGameMessageType::RACING_SERVER_SET_PLAYER_LAP_AND_PLANE, (eGameMessageType)1253); + EXPECT_EQ(eGameMessageType::RACING_SET_PLAYER_RESET_INFO, (eGameMessageType)1254); + EXPECT_EQ(eGameMessageType::RACING_PLAYER_INFO_RESET_FINISHED, (eGameMessageType)1255); + EXPECT_EQ(eGameMessageType::LOCK_NODE_ROTATION, (eGameMessageType)1260); + EXPECT_EQ(eGameMessageType::VEHICLE_SET_WHEEL_LOCK_STATE, (eGameMessageType)1273); + EXPECT_EQ(eGameMessageType::NOTIFY_VEHICLE_OF_RACING_OBJECT, (eGameMessageType)1276); + EXPECT_EQ(eGameMessageType::SET_NAME_BILLBOARD_STATE, (eGameMessageType)1284); + EXPECT_EQ(eGameMessageType::PLAYER_REACHED_RESPAWN_CHECKPOINT, (eGameMessageType)1296); + EXPECT_EQ(eGameMessageType::HANDLE_UGC_POST_DELETE_BASED_ON_EDIT_MODE, (eGameMessageType)1300); + EXPECT_EQ(eGameMessageType::HANDLE_UGC_POST_CREATE_BASED_ON_EDIT_MODE, (eGameMessageType)1301); + EXPECT_EQ(eGameMessageType::PROPERTY_CONTENTS_FROM_CLIENT, (eGameMessageType)1305); + EXPECT_EQ(eGameMessageType::GET_MODELS_ON_PROPERTY, (eGameMessageType)1306); + EXPECT_EQ(eGameMessageType::MATCH_REQUEST, (eGameMessageType)1308); + EXPECT_EQ(eGameMessageType::MATCH_RESPONSE, (eGameMessageType)1309); + EXPECT_EQ(eGameMessageType::MATCH_UPDATE, (eGameMessageType)1310); + EXPECT_EQ(eGameMessageType::MODULE_ASSEMBLY_DB_DATA_FOR_CLIENT, (eGameMessageType)1131); + EXPECT_EQ(eGameMessageType::MODULE_ASSEMBLY_QUERY_DATA, (eGameMessageType)1132); + EXPECT_EQ(eGameMessageType::SHOW_BILLBOARD_INTERACT_ICON, (eGameMessageType)1337); + EXPECT_EQ(eGameMessageType::CHANGE_IDLE_FLAGS, (eGameMessageType)1338); + EXPECT_EQ(eGameMessageType::VEHICLE_ADD_PASSIVE_BOOST_ACTION, (eGameMessageType)1340); + EXPECT_EQ(eGameMessageType::VEHICLE_REMOVE_PASSIVE_BOOST_ACTION, (eGameMessageType)1341); + EXPECT_EQ(eGameMessageType::NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION, (eGameMessageType)1342); + EXPECT_EQ(eGameMessageType::NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION, (eGameMessageType)1343); + EXPECT_EQ(eGameMessageType::VEHICLE_ADD_SLOWDOWN_ACTION, (eGameMessageType)1344); + EXPECT_EQ(eGameMessageType::VEHICLE_REMOVE_SLOWDOWN_ACTION, (eGameMessageType)1345); + EXPECT_EQ(eGameMessageType::NOTIFY_SERVER_VEHICLE_ADD_SLOWDOWN_ACTION, (eGameMessageType)1346); + EXPECT_EQ(eGameMessageType::NOTIFY_SERVER_VEHICLE_REMOVE_SLOWDOWN_ACTION, (eGameMessageType)1347); + EXPECT_EQ(eGameMessageType::BUYBACK_FROM_VENDOR, (eGameMessageType)1350); + EXPECT_EQ(eGameMessageType::SET_PROPERTY_ACCESS, (eGameMessageType)1366); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_PLACED, (eGameMessageType)1369); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_ROTATED, (eGameMessageType)1370); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_REMOVED_WHILE_EQUIPPED, (eGameMessageType)1371); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_EQUIPPED, (eGameMessageType)1372); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_PICKED_UP, (eGameMessageType)1373); + EXPECT_EQ(eGameMessageType::ZONE_PROPERTY_MODEL_REMOVED, (eGameMessageType)1374); + EXPECT_EQ(eGameMessageType::NOTIFY_RACING_CLIENT, (eGameMessageType)1390); + EXPECT_EQ(eGameMessageType::RACING_PLAYER_HACK_CAR, (eGameMessageType)1391); + EXPECT_EQ(eGameMessageType::RACING_PLAYER_LOADED, (eGameMessageType)1392); + EXPECT_EQ(eGameMessageType::RACING_CLIENT_READY, (eGameMessageType)1393); + EXPECT_EQ(eGameMessageType::UPDATE_CHAT_MODE, (eGameMessageType)1395); + EXPECT_EQ(eGameMessageType::VEHICLE_NOTIFY_FINISHED_RACE, (eGameMessageType)1396); + EXPECT_EQ(eGameMessageType::SET_CONSUMABLE_ITEM, (eGameMessageType)1409); + EXPECT_EQ(eGameMessageType::SET_STATUS_IMMUNITY, (eGameMessageType)1435); + EXPECT_EQ(eGameMessageType::SET_PET_NAME_MODERATED, (eGameMessageType)1448); + EXPECT_EQ(eGameMessageType::MODIFY_LEGO_SCORE, (eGameMessageType)1459); + EXPECT_EQ(eGameMessageType::RESTORE_TO_POST_LOAD_STATS, (eGameMessageType)1468); + EXPECT_EQ(eGameMessageType::SET_RAIL_MOVEMENT, (eGameMessageType)1471); + EXPECT_EQ(eGameMessageType::START_RAIL_MOVEMENT, (eGameMessageType)1472); + EXPECT_EQ(eGameMessageType::CANCEL_RAIL_MOVEMENT, (eGameMessageType)1474); + EXPECT_EQ(eGameMessageType::CLIENT_RAIL_MOVEMENT_READY, (eGameMessageType)1476); + EXPECT_EQ(eGameMessageType::PLAYER_RAIL_ARRIVED_NOTIFICATION, (eGameMessageType)1477); + EXPECT_EQ(eGameMessageType::UPDATE_PLAYER_STATISTIC, (eGameMessageType)1481); + EXPECT_EQ(eGameMessageType::MODULAR_ASSEMBLY_NIF_COMPLETED, (eGameMessageType)1498); + EXPECT_EQ(eGameMessageType::NOTIFY_NOT_ENOUGH_INV_SPACE, (eGameMessageType)1516); + EXPECT_EQ(eGameMessageType::TEAM_SET_LEADER, (eGameMessageType)1557); + EXPECT_EQ(eGameMessageType::TEAM_INVITE_CONFIRM, (eGameMessageType)1558); + EXPECT_EQ(eGameMessageType::TEAM_GET_STATUS_RESPONSE, (eGameMessageType)1559); + EXPECT_EQ(eGameMessageType::TEAM_ADD_PLAYER, (eGameMessageType)1562); + EXPECT_EQ(eGameMessageType::TEAM_REMOVE_PLAYER, (eGameMessageType)1563); + EXPECT_EQ(eGameMessageType::START_CELEBRATION_EFFECT, (eGameMessageType)1618); + EXPECT_EQ(eGameMessageType::ADD_BUFF, (eGameMessageType)1647); + EXPECT_EQ(eGameMessageType::SERVER_DONE_LOADING_ALL_OBJECTS, (eGameMessageType)1642); + EXPECT_EQ(eGameMessageType::PLACE_PROPERTY_MODEL, (eGameMessageType)1170); + EXPECT_EQ(eGameMessageType::VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER, (eGameMessageType)1606); + EXPECT_EQ(eGameMessageType::ADD_RUN_SPEED_MODIFIER, (eGameMessageType)1505); + EXPECT_EQ(eGameMessageType::GET_HOT_PROPERTY_DATA, (eGameMessageType)1511); + EXPECT_EQ(eGameMessageType::SEND_HOT_PROPERTY_DATA, (eGameMessageType)1510); + EXPECT_EQ(eGameMessageType::REMOVE_RUN_SPEED_MODIFIER, (eGameMessageType)1506); + EXPECT_EQ(eGameMessageType::UPDATE_PROPERTY_PERFORMANCE_COST, (eGameMessageType)1547); + EXPECT_EQ(eGameMessageType::PROPERTY_ENTRANCE_BEGIN, (eGameMessageType)1553); + EXPECT_EQ(eGameMessageType::SET_RESURRECT_RESTORE_VALUES, (eGameMessageType)1591); + EXPECT_EQ(eGameMessageType::VEHICLE_STOP_BOOST, (eGameMessageType)1617); + EXPECT_EQ(eGameMessageType::REMOVE_BUFF, (eGameMessageType)1648); + EXPECT_EQ(eGameMessageType::REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES, (eGameMessageType)1666); + EXPECT_EQ(eGameMessageType::RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES, (eGameMessageType)1667); + EXPECT_EQ(eGameMessageType::PLAYER_SET_CAMERA_CYCLING_MODE, (eGameMessageType)1676); + EXPECT_EQ(eGameMessageType::SET_MOUNT_INVENTORY_ID, (eGameMessageType)1727); + EXPECT_EQ(eGameMessageType::NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE, (eGameMessageType)1734); + EXPECT_EQ(eGameMessageType::NOTIFY_LEVEL_REWARDS, (eGameMessageType)1735); + EXPECT_EQ(eGameMessageType::DISMOUNT_COMPLETE, (eGameMessageType)1756); + EXPECT_EQ(eGameMessageType::MARK_INVENTORY_ITEM_AS_ACTIVE, (eGameMessageType)1767); +}