#ifndef EFFECTSMESSAGESLEGACY_H #define EFFECTSMESSAGESLEGACY_H // FROZEN ORACLE - DO NOT EDIT. // Verbatim copies of the hand written GameMessages functions that EffectsMessages.h replaced // (dGame/dGameMessages/GameMessages.cpp, branched from origin/main 129199e4). Only the namespace changed. // The Read* functions are the read sequences of the replaced GameMessages::Handle* functions. #include "LegacyPacketMacros.h" #include "Amf3.h" #include "AmfSerialize.h" #include "BitStreamUtils.h" #include "dCommonVars.h" #include "dServer.h" #include "eAnimationFlags.h" #include "eCinematicEvent.h" #include "eEndBehavior.h" #include "Entity.h" #include "Game.h" #include "GeneralUtils.h" #include "Logger.h" #include "MessageType/Client.h" #include "MessageType/Game.h" #include "ServiceType.h" #include #include namespace LegacyGameMessages { // Declared in GameMessages.h in the original; the Entity* overload forwards to it. inline void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize); inline void SendPlayAnimation(Entity* entity, const std::u16string& animationName, float fPriority, float fScale) { if (!entity) { LOG("Trying to play animation, but entity var is nullptr!"); return; } //Stolen from the old DLU codebase as the new one's autogenerated code doesn't work properly for animationIDs longer than 6 characters. CBITSTREAM; CMSGHEADER; std::string sAnimationID = GeneralUtils::UTF16ToWTF8(animationName); uint32_t animationIDLength = sAnimationID.size(); bool bExpectAnimToExist = true; bool bPlayImmediate = false; bool bTriggerOnCompleteMsg = false; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::PLAY_ANIMATION); bitStream.Write(animationIDLength); bitStream.Write(LUWString(animationName, animationIDLength)); bitStream.Write(bExpectAnimToExist); bitStream.Write(bPlayImmediate); bitStream.Write(bTriggerOnCompleteMsg); bitStream.Write(fPriority != 0.0f); if (fPriority != 0.0f) bitStream.Write(fPriority); bitStream.Write(fScale != 1.0f); if (fScale != 1.0f) bitStream.Write(fScale); SEND_PACKET_BROADCAST; } inline void SendPlayNDAudioEmitter(Entity* entity, const SystemAddress& sysAddr, std::string audioGUID) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::PLAY_ND_AUDIO_EMITTER); bitStream.Write0(); // callback message data {lwoobjid} bitStream.Write0(); // audio emitterid {uint32_t} uint32_t length = audioGUID.size(); bitStream.Write(length); for (uint32_t k = 0; k < length; k++) { bitStream.Write(audioGUID[k]); } bitStream.Write(0); // size of NDAudioMetaEventName (then print the string like the guid) bitStream.Write0(); // result {bool} bitStream.Write0(); // m_TargetObjectIDForNDAudioCallbackMessages {lwoobjid} SEND_PACKET_BROADCAST; } inline void SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT); bitStream.Write(effectName.length()); for (uint32_t k = 0; k < effectName.length(); k++) { bitStream.Write(effectName[k]); } bitStream.Write(fromObjectID); bitStream.Write(radius); SEND_PACKET_BROADCAST; } inline void SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { SendPlayFXEffect(entity->GetObjectID(), effectID, effectType, name, secondary, priority, scale, serialize); } inline void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity); bitStream.Write(MessageType::Game::PLAY_FX_EFFECT); bitStream.Write(effectID != -1); if (effectID != -1) bitStream.Write(effectID); bitStream.Write(effectType.size()); for (const auto& k : effectType) { bitStream.Write(k); } bitStream.Write(scale != 1.0f); if (scale != 1.0f) bitStream.Write(scale); bitStream.Write(name.size()); for (const auto& k : name) { bitStream.Write(k); } bitStream.Write(priority != 1.0); if (priority != 1.0) bitStream.Write(priority); bitStream.Write(secondary != LWOOBJID_EMPTY); if (secondary != LWOOBJID_EMPTY) bitStream.Write(secondary); bitStream.Write(serialize); SEND_PACKET_BROADCAST; } inline void SendStopFXEffect(Entity* entity, bool killImmediate, std::string name) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::STOP_FX_EFFECT); bitStream.Write(killImmediate); bitStream.Write(name.size()); bitStream.Write(name.c_str(), name.size()); SEND_PACKET_BROADCAST; } inline void SendBroadcastTextToChatbox(Entity* entity, const SystemAddress& sysAddr, const std::u16string& attrs, const std::u16string& wsText) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX); bitStream.Write(attrs.size()); for (uint32_t i = 0; i < attrs.size(); ++i) { bitStream.Write(attrs[i]); } bitStream.Write(0x00); // Null Terminator uint32_t wsTextLength = wsText.size(); bitStream.Write(wsTextLength); for (uint32_t k = 0; k < wsTextLength; k++) { bitStream.Write(wsText[k]); } SEND_PACKET_BROADCAST; } inline void SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, bool result) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::PLAY2_D_AMBIENT_SOUND); uint32_t audioGUIDSize = audioGUID.size(); bitStream.Write(audioGUIDSize); for (uint32_t k = 0; k < audioGUIDSize; k++) { bitStream.Write(audioGUID[k]); } bitStream.Write(result); SystemAddress sysAddr = entity->GetSystemAddress(); SEND_PACKET; } inline void SendStop2DAmbientSound(Entity* entity, bool force, std::string audioGUID, bool result) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::STOP2_D_AMBIENT_SOUND); uint32_t audioGUIDSize = audioGUID.size(); bitStream.Write(force); bitStream.Write(audioGUIDSize); for (uint32_t k = 0; k < audioGUIDSize; k++) { bitStream.Write(audioGUID[k]); } bitStream.Write(result); SystemAddress sysAddr = entity->GetSystemAddress(); SEND_PACKET; } inline void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT); bitStream.Write(args); uint32_t strMessageNameLength = message.size(); bitStream.Write(strMessageNameLength); for (uint32_t k = 0; k < strMessageNameLength; k++) { bitStream.Write(message[k]); } SEND_PACKET; } inline void SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; LWOOBJID empty = 0; bitStream.Write(empty); bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); // This is intentional to allow the server to send a ui message to a client via their system address. bitStream.Write(args); uint32_t strMessageNameLength = message.size(); bitStream.Write(strMessageNameLength); for (uint32_t k = 0; k < strMessageNameLength; k++) { bitStream.Write(message[k]); } SEND_PACKET; } inline void SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args) { CBITSTREAM; CMSGHEADER; LWOOBJID empty = 0; bitStream.Write(empty); bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); bitStream.Write(args); uint32_t strMessageNameLength = message.size(); bitStream.Write(strMessageNameLength); for (uint32_t k = 0; k < strMessageNameLength; k++) { bitStream.Write(message[k]); } SEND_PACKET_BROADCAST; } inline void SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::START_CELEBRATION_EFFECT); bitStream.Write(0); //animation bitStream.Write0(); //No custom bg obj bitStream.Write0(); //custom path bitStream.Write0(); //leadin bitStream.Write0(); //leadout bitStream.Write1(); bitStream.Write(celebrationID); bitStream.Write(0.0f); //duration bitStream.Write(0); //icon bitStream.Write(0); //text bitStream.Write(0); //mixer bitStream.Write(0); //cue bitStream.Write(0); //pathnodename bitStream.Write(0); //soundguid bitStream.Write(0); //subtext SEND_PACKET; } inline void SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::DISPLAY_MESSAGE_BOX); bitStream.Write(bShow); bitStream.Write(callbackClient); bitStream.Write(identifier.size()); for (const auto character : identifier) { bitStream.Write(character); } bitStream.Write(imageID); bitStream.Write(text.size()); for (const auto character : text) { bitStream.Write(character); } bitStream.Write(userData.size()); for (const auto character : userData) { bitStream.Write(character); } if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } inline void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr) { // MessageType::Game::DISPLAY_CHAT_BUBBLE CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::DISPLAY_CHAT_BUBBLE); bitStream.Write(text.size()); for (const auto character : text) { bitStream.Write(character); } if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } inline void SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags flagsOn, eAnimationFlags flagsOff, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::CHANGE_IDLE_FLAGS); bitStream.Write(flagsOff != eAnimationFlags::IDLE_NONE); if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff); bitStream.Write(flagsOn != eAnimationFlags::IDLE_NONE); if (flagsOn != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOn); SEND_PACKET_BROADCAST; } inline void SendSetNamebillboardState(const SystemAddress& sysAddr, LWOOBJID objectId) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::SET_NAME_BILLBOARD_STATE); // Technically these bits would be written, however the client does not // contain a deserialize method to actually deserialize, so we are leaving it out. // As such this GM only turns the billboard off. // bitStream.Write(overrideDefault); // bitStream.Write(state); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST else SEND_PACKET } inline void SendShowBillboardInteractIcon(const SystemAddress& sysAddr, LWOOBJID objectId) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::SHOW_BILLBOARD_INTERACT_ICON); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST else SEND_PACKET } inline void SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, bool allowGhostUpdates, bool bCloseMultiInteract, bool bSendServerNotify, bool bUseControlledObjectForAudioListener, eEndBehavior endBehavior, bool hidePlayerDuringCine, float leadIn, bool leavePlayerLockedWhenFinished, bool lockPlayer, bool result, bool skipIfSamePath, float startTimeAdvance) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::PLAY_CINEMATIC); bitStream.Write(allowGhostUpdates); bitStream.Write(bCloseMultiInteract); bitStream.Write(bSendServerNotify); bitStream.Write(bUseControlledObjectForAudioListener); bitStream.Write(endBehavior != eEndBehavior::RETURN); if (endBehavior != eEndBehavior::RETURN) bitStream.Write(endBehavior); bitStream.Write(hidePlayerDuringCine); bitStream.Write(leadIn != -1); if (leadIn != -1) bitStream.Write(leadIn); bitStream.Write(leavePlayerLockedWhenFinished); bitStream.Write(lockPlayer); bitStream.Write(pathName.size()); for (char16_t c : pathName) { bitStream.Write(c); } bitStream.Write(result); bitStream.Write(skipIfSamePath); bitStream.Write(startTimeAdvance); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } inline void SendEndCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, float leadOut, bool leavePlayerLocked) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::END_CINEMATIC); bitStream.Write(leadOut != -1); if (leadOut != -1) bitStream.Write(leadOut); bitStream.Write(leavePlayerLocked); bitStream.Write(pathName.size()); for (uint32_t i = 0; i < pathName.size(); i++) { bitStream.Write(pathName[i]); } if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } inline void SendSlashCommandFeedbackText(Entity* entity, std::u16string text) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::SLASH_COMMAND_TEXT_FEEDBACK); bitStream.Write(text.size()); bitStream.Write(text); auto sysAddr = entity->GetSystemAddress(); SEND_PACKET; } inline void SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(MessageType::Game::PLAY_EMOTE); bitStream.Write(emoteID); bitStream.Write(target); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; SEND_PACKET; } inline void SendSetEmoteLockState(Entity* entity, bool bLock, int emoteID) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::SET_EMOTE_LOCK_STATE); bitStream.Write(bLock); bitStream.Write(emoteID); SystemAddress sysAddr = entity->GetSystemAddress(); SEND_PACKET; } struct LegacyMessageBoxResponse { bool ok{}; int32_t iButton{}; std::u16string identifier; std::u16string userData; }; inline LegacyMessageBoxResponse ReadMessageBoxResponse(RakNet::BitStream& inStream) { int32_t iButton; uint32_t identifierLength; std::u16string identifier; uint32_t userDataLength; std::u16string userData; inStream.Read(iButton); inStream.Read(identifierLength); if (identifierLength > MAX_MESSAGE_LENGTH) return {}; for (size_t i = 0; i < identifierLength; i++) { char16_t character; inStream.Read(character); identifier.push_back(character); } inStream.Read(userDataLength); if (userDataLength > MAX_MESSAGE_LENGTH) return {}; for (size_t i = 0; i < userDataLength; i++) { char16_t character; inStream.Read(character); userData.push_back(character); } return { true, iButton, identifier, userData }; } struct LegacyChoiceBoxRespond { bool ok{}; int32_t iButton{}; std::u16string buttonIdentifier; std::u16string identifier; }; inline LegacyChoiceBoxRespond ReadChoiceBoxRespond(RakNet::BitStream& inStream) { int32_t iButton; uint32_t buttonIdentifierLength; std::u16string buttonIdentifier; uint32_t identifierLength; std::u16string identifier; inStream.Read(buttonIdentifierLength); if (buttonIdentifierLength > MAX_MESSAGE_LENGTH) return {}; for (size_t i = 0; i < buttonIdentifierLength; i++) { char16_t character; inStream.Read(character); buttonIdentifier.push_back(character); } inStream.Read(iButton); inStream.Read(identifierLength); if (identifierLength > MAX_MESSAGE_LENGTH) return {}; for (size_t i = 0; i < identifierLength; i++) { char16_t character; inStream.Read(character); identifier.push_back(character); } return { true, iButton, buttonIdentifier, identifier }; } struct LegacyCinematicUpdate { eCinematicEvent event; float_t overallTime; std::u16string pathName; float_t pathTime; int32_t waypoint; }; inline LegacyCinematicUpdate ReadCinematicUpdate(RakNet::BitStream& inStream) { eCinematicEvent event; if (!inStream.ReadBit()) { event = eCinematicEvent::STARTED; } else { inStream.Read(event); } float_t overallTime; if (!inStream.ReadBit()) { overallTime = -1.0f; } else { inStream.Read(overallTime); } uint32_t pathNameLength; inStream.Read(pathNameLength); std::u16string pathName; for (size_t i = 0; i < pathNameLength; i++) { char16_t character; inStream.Read(character); pathName.push_back(character); } float_t pathTime; if (!inStream.ReadBit()) { pathTime = -1.0f; } else { inStream.Read(pathTime); } int32_t waypoint; if (!inStream.ReadBit()) { waypoint = -1; } else { inStream.Read(waypoint); } return { event, overallTime, pathName, pathTime, waypoint }; } struct LegacyPlayEmote { int32_t emoteID; LWOOBJID targetID; }; inline LegacyPlayEmote ReadPlayEmote(RakNet::BitStream& inStream) { int32_t emoteID; LWOOBJID targetID; inStream.Read(emoteID); inStream.Read(targetID); return { emoteID, targetID }; } } #endif // EFFECTSMESSAGESLEGACY_H