/* * Darkflame Universe * Copyright 2018 */ #include "GameMessageHandler.h" #include "WorldMigration.h" #include "MissionComponent.h" #include "BitStreamUtils.h" #include "dServer.h" #include "RakNetworkFactory.h" #include #include "User.h" #include "UserManager.h" #include "BitStream.h" #include "RakPeer.h" #include "DestroyableComponent.h" #include "InventoryComponent.h" #include "Character.h" #include "ControllablePhysicsComponent.h" #include "dZoneManager.h" #include "CppScripts.h" #include "CDClientDatabase.h" #include "CDClientManager.h" #include "CDSkillBehaviorTable.h" #include "SkillComponent.h" #include "RacingControlComponent.h" #include "ActivityMessages.h" #include "BuildingMessages.h" #include "RacingMessages.h" #include "MissionMessages.h" #include "CombatMessages.h" #include "SkillMessages.h" #include "TradeMessages.h" #include "VendorMessages.h" #include "EffectsMessages.h" #include "InventoryMessages.h" #include "PetMessages.h" #include "PropertyMessages.h" #include "MovementMessages.h" #include "ObjectMessages.h" #include "PlayerMessages.h" #include "QuickBuildMessages.h" #include "ZoneMessages.h" #include "eMissionTaskType.h" #include "eReplicaComponentType.h" #include "ServiceType.h" #include "MessageType/Game.h" #include "ePlayerFlag.h" #include "dConfig.h" #include "GhostComponent.h" #include "eGameMasterLevel.h" #include "StringifiedEnum.h" #include "MessageInspector.h" namespace { using enum MessageType::Game; using namespace GameMessages; using MessageCreator = std::function()>; std::map g_MessageHandlers = { { REQUEST_USE, []() { return std::make_unique(); }}, { REQUEST_SERVER_OBJECT_INFO, []() { return std::make_unique(); } }, { SHOOTING_GALLERY_FIRE, []() { return std::make_unique(); } }, { PICKUP_ITEM, []() { return std::make_unique(); } }, { REQUEST_ACTIVITY_EXIT, []() { return std::make_unique(); } }, // Racing { MODULE_ASSEMBLY_QUERY_DATA, []() { return std::make_unique(); } }, { VEHICLE_SET_WHEEL_LOCK_STATE, []() { return std::make_unique(); } }, { MODULAR_ASSEMBLY_NIF_COMPLETED, []() { return std::make_unique(); } }, { RACING_CLIENT_READY, []() { return std::make_unique(); } }, { NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION, []() { return std::make_unique(); } }, { NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION, []() { return std::make_unique(); } }, { RACING_PLAYER_INFO_RESET_FINISHED, []() { return std::make_unique(); } }, { VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER, []() { return std::make_unique(); } }, // Missions, flags, collectibles { RESPOND_TO_MISSION, []() { return std::make_unique(); } }, { MISSION_DIALOGUE_OK, []() { return std::make_unique(); } }, { REQUEST_LINKED_MISSION, []() { return std::make_unique(); } }, { SET_FLAG, []() { return std::make_unique(); } }, { HAS_BEEN_COLLECTED, []() { return std::make_unique(); } }, // Effects, emotes, cinematics, UI { PLAY_EMOTE, []() { return std::make_unique(); } }, { MESSAGE_BOX_RESPOND, []() { return std::make_unique(); } }, { CHOICE_BOX_RESPOND, []() { return std::make_unique(); } }, { CINEMATIC_UPDATE, []() { return std::make_unique(); } }, // Inventory and items { EQUIP_INVENTORY, []() { return std::make_unique(); } }, { UN_EQUIP_INVENTORY, []() { return std::make_unique(); } }, { REMOVE_ITEM_FROM_INVENTORY, []() { return std::make_unique(); } }, { MOVE_ITEM_IN_INVENTORY, []() { return std::make_unique(); } }, { MOVE_ITEM_BETWEEN_INVENTORY_TYPES, []() { return std::make_unique(); } }, { REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES, []() { return std::make_unique(); } }, { PUSH_EQUIPPED_ITEMS_STATE, []() { return std::make_unique(); } }, { POP_EQUIPPED_ITEMS_STATE, []() { return std::make_unique(); } }, { CLIENT_ITEM_CONSUMED, []() { return std::make_unique(); } }, { USE_NON_EQUIPMENT_ITEM, []() { return std::make_unique(); } }, { SET_CONSUMABLE_ITEM, []() { return std::make_unique(); } }, { UPDATE_INVENTORY_GROUP, []() { return std::make_unique(); } }, { UPDATE_INVENTORY_GROUP_CONTENTS, []() { return std::make_unique(); } }, // Pets { PET_TAMING_TRY_BUILD, []() { return std::make_unique(); } }, { NOTIFY_TAMING_BUILD_SUCCESS, []() { return std::make_unique(); } }, { REQUEST_SET_PET_NAME, []() { return std::make_unique(); } }, { START_SERVER_PET_MINIGAME_TIMER, []() { return std::make_unique(); } }, { CLIENT_EXIT_TAMING_MINIGAME, []() { return std::make_unique(); } }, { COMMAND_PET, []() { return std::make_unique(); } }, { DESPAWN_PET, []() { return std::make_unique(); } }, // Property { SET_PROPERTY_ACCESS, []() { return std::make_unique(); } }, { UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK, []() { return std::make_unique(); } }, { QUERY_PROPERTY_DATA, []() { return std::make_unique(); } }, { PROPERTY_EDITOR_BEGIN, []() { return std::make_unique(); } }, { PROPERTY_EDITOR_END, []() { return std::make_unique(); } }, { PROPERTY_CONTENTS_FROM_CLIENT, []() { return std::make_unique(); } }, { ZONE_PROPERTY_MODEL_EQUIPPED, []() { return std::make_unique(); } }, { ZONE_PROPERTY_MODEL_ROTATED, []() { return std::make_unique(); } }, { PLACE_PROPERTY_MODEL, []() { return std::make_unique(); } }, { UPDATE_MODEL_FROM_CLIENT, []() { return std::make_unique(); } }, { DELETE_MODEL_FROM_CLIENT, []() { return std::make_unique(); } }, { CONTROL_BEHAVIORS, []() { return std::make_unique(); } }, { PROPERTY_ENTRANCE_SYNC, []() { return std::make_unique(); } }, { ENTER_PROPERTY1, []() { return std::make_unique(); } }, { UPDATE_PROPERTY_PERFORMANCE_COST, []() { return std::make_unique(); } }, { REPORT_OFFENSIVE_MODEL, []() { return std::make_unique(); } }, { REPORT_OFFENSIVE_PROPERTY, []() { return std::make_unique(); } }, { GET_HOT_PROPERTY_DATA, []() { return std::make_unique(); } }, // Building { START_BUILDING_WITH_ITEM, []() { return std::make_unique(); } }, { DONE_ARRANGING_WITH_ITEM, []() { return std::make_unique(); } }, { MODULAR_BUILD_FINISH, []() { return std::make_unique(); } }, { MODULAR_BUILD_MOVE_AND_EQUIP, []() { return std::make_unique(); } }, { MODULAR_BUILD_CONVERT_MODEL, []() { return std::make_unique(); } }, { SET_BUILD_MODE, []() { return std::make_unique(); } }, { BUILD_MODE_SET, []() { return std::make_unique(); } }, { UN_USE_BBB_MODEL, []() { return std::make_unique(); } }, { BBB_LOAD_ITEM_REQUEST, []() { return std::make_unique(); } }, { BBB_SAVE_REQUEST, []() { return std::make_unique(); } }, // Vendors and donation vendors { REQUEST_VENDOR_STATUS_UPDATE, []() { return std::make_unique(); } }, { BUY_FROM_VENDOR, []() { return std::make_unique(); } }, { SELL_TO_VENDOR, []() { return std::make_unique(); } }, { BUYBACK_FROM_VENDOR, []() { return std::make_unique(); } }, { ADD_DONATION_ITEM, []() { return std::make_unique(); } }, { REMOVE_DONATION_ITEM, []() { return std::make_unique(); } }, { CONFIRM_DONATION_ON_PLAYER, []() { return std::make_unique(); } }, { CANCEL_DONATION_ON_PLAYER, []() { return std::make_unique(); } }, // Trading { CLIENT_TRADE_REQUEST, []() { return std::make_unique(); } }, { CLIENT_TRADE_CANCEL, []() { return std::make_unique(); } }, { CLIENT_TRADE_ACCEPT, []() { return std::make_unique(); } }, { CLIENT_TRADE_UPDATE, []() { return std::make_unique(); } }, // Skills { SELECT_SKILL, []() { return std::make_unique(); } }, { START_SKILL, []() { return std::make_unique(); } }, { SYNC_SKILL, []() { return std::make_unique(); } }, { REQUEST_SERVER_PROJECTILE_IMPACT, []() { return std::make_unique(); } }, // Combat { REQUEST_DIE, []() { return std::make_unique(); } }, { REQUEST_SMASH_PLAYER, []() { return std::make_unique(); } }, { REQUEST_RESURRECT, []() { return std::make_unique(); } }, { RESURRECT, []() { return std::make_unique(); } }, { ACTIVATE_BUBBLE_BUFF, []() { return std::make_unique(); } }, { DECTIVATE_BUBBLE_BUFF, []() { return std::make_unique(); } }, // Zone lifecycle { PLAYER_LOADED, []() { return std::make_unique(); } }, { READY_FOR_UPDATES, []() { return std::make_unique(); } }, { NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE, []() { return std::make_unique(); } }, { ZONE_SUMMARY_DISMISSED, []() { return std::make_unique(); } }, { MISSION_DIALOGUE_CANCELLED, []() { return std::make_unique(); } }, // Objects and scripts { FIRE_EVENT_SERVER_SIDE, []() { return std::make_unique(); } }, // Player state, chat commands, reports { PARSE_CHAT_MESSAGE, []() { return std::make_unique(); } }, { PICKUP_CURRENCY, []() { return std::make_unique(); } }, { MODIFY_PLAYER_ZONE_STATISTIC, []() { return std::make_unique(); } }, { UPDATE_PLAYER_STATISTIC, []() { return std::make_unique(); } }, { REPORT_BUG, []() { return std::make_unique(); } }, { VERIFY_ACK, []() { return std::make_unique(); } }, // Quickbuilds { REBUILD_CANCEL, []() { return std::make_unique(); } }, // Activities, matches, leaderboards, shooting galleries { MATCH_REQUEST, []() { return std::make_unique(); } }, { REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA, []() { return std::make_unique(); } }, { SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA, []() { return std::make_unique(); } }, { ACTIVITY_STATE_CHANGE_REQUEST, []() { return std::make_unique(); } }, { UPDATE_SHOOTING_GALLERY_ROTATION, []() { return std::make_unique(); } }, // Movement: platforms, rails, mounts, ghosting { REQUEST_PLATFORM_RESYNC, []() { return std::make_unique(); } }, { CLIENT_RAIL_MOVEMENT_READY, []() { return std::make_unique(); } }, { CANCEL_RAIL_MOVEMENT, []() { return std::make_unique(); } }, { PLAYER_RAIL_ARRIVED_NOTIFICATION, []() { return std::make_unique(); } }, { DISMOUNT_COMPLETE, []() { return std::make_unique(); } }, { ACKNOWLEDGE_POSSESSION, []() { return std::make_unique(); } }, { TOGGLE_GHOST_REFERENCE_OVERRIDE, []() { return std::make_unique(); } }, { SET_GHOST_REFERENCE_POSITION, []() { return std::make_unique(); } }, }; }; void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) { // The dashboard's message inspector (sees every message a client sends; nothing to do unless a capture runs) if (MessageInspector::IsCapturing()) MessageInspector::RecordReceived(sysAddr, objectID, messageID, inStream); // Get the entity Entity* entity = Game::entityManager->GetEntity(objectID); User* usr = UserManager::Instance()->GetUser(sysAddr); if (!usr) { LOG("Failed to find a logged in user for (%llu), aborting GM: %4i, %s!", objectID, messageID, StringifiedEnum::ToString(messageID).data()); return; } if (!entity) { LOG("Failed to find associated entity (%llu), aborting GM: %4i, %s!", objectID, messageID, StringifiedEnum::ToString(messageID).data()); return; } if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data()); auto handler = g_MessageHandlers.find(messageID); if (handler != g_MessageHandlers.end()) { auto msg = handler->second(); // Verify that the system address user is able to use this message. if (msg->requiredGmLevel > eGameMasterLevel::CIVILIAN) { auto* usingEntity = Game::entityManager->GetEntity(usr->GetLoggedInChar()); if (!usingEntity || usingEntity->GetGMLevel() < msg->requiredGmLevel) { if (usingEntity) LOG("User %s (%llu) does not have the required GM level to execute this command.", usingEntity->GetCharacter()->GetName().c_str(), usingEntity->GetObjectID()); else LOG("ObjectID %llu tried to use a gm required message.", usr->GetLoggedInChar()); return; } } if (!msg->Deserialize(inStream)) { LOG("Dropping malformed GM %4i, %s from (%llu) targeting (%llu)", messageID, StringifiedEnum::ToString(messageID).data(), usr->GetLoggedInChar(), objectID); return; } msg->Handle(*entity, sysAddr); return; } LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data()); }