mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
Nothing in the server writes or reads a packet by hand any more, so the helpers for doing so go: - CBITSTREAM, CMSGHEADER, CINSTREAM, CINSTREAM_SKIP_HEADER, SEND_PACKET, SEND_PACKET_BROADCAST and HEADER_SIZE leave dCommonVars.h; - the free BitStreamUtils::WriteHeader (LUBitStream::WriteHeader writes the same bytes) and the unused PacketUtils::SavePacket are deleted. The last raw reads are replaced: WorldServer builds its input stream directly, the master packet logs read the header with LUBitStream::ReadHeader instead of peeking at packet->data[1] and [3], and MessageInspector reads a sent game message's header with the new NetGameMsg::ReadPacketHeader (the counterpart of WritePacket) instead of memcmp/memcpy. packet->data[0] is still compared with RakNet's own connection IDs. The frozen oracles keep using the macros verbatim through the test-only tests/dGameTests/LegacyPacketMacros.h; the HeaderSkip tests, which only tested CINSTREAM_SKIP_HEADER, are removed. docs/PacketArchitecture.md: "where we are" now describes the final state and what still touches raw bytes (RakNet IDs, replica headers, behavior bit streams), and a new section collects the known wire discrepancies found during the conversion, with client addresses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
609 lines
18 KiB
C++
609 lines
18 KiB
C++
#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 <cmath>
|
|
#include <string>
|
|
|
|
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<char>(audioGUID[k]);
|
|
}
|
|
|
|
bitStream.Write<uint32_t>(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<uint32_t>(effectName.length());
|
|
for (uint32_t k = 0; k < effectName.length(); k++) {
|
|
bitStream.Write<uint16_t>(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<uint32_t>(effectType.size());
|
|
for (const auto& k : effectType) {
|
|
bitStream.Write<uint16_t>(k);
|
|
}
|
|
|
|
bitStream.Write(scale != 1.0f);
|
|
if (scale != 1.0f) bitStream.Write(scale);
|
|
|
|
bitStream.Write<uint32_t>(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<uint32_t>(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<uint32_t>(attrs.size());
|
|
for (uint32_t i = 0; i < attrs.size(); ++i) {
|
|
bitStream.Write<uint16_t>(attrs[i]);
|
|
}
|
|
bitStream.Write<uint16_t>(0x00); // Null Terminator
|
|
|
|
uint32_t wsTextLength = wsText.size();
|
|
bitStream.Write(wsTextLength);
|
|
for (uint32_t k = 0; k < wsTextLength; k++) {
|
|
bitStream.Write<uint16_t>(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<char>(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<char>(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<AMFBaseValue&>(args);
|
|
uint32_t strMessageNameLength = message.size();
|
|
bitStream.Write(strMessageNameLength);
|
|
|
|
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
|
bitStream.Write<char>(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<AMFBaseValue&>(args);
|
|
uint32_t strMessageNameLength = message.size();
|
|
bitStream.Write(strMessageNameLength);
|
|
|
|
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
|
bitStream.Write<char>(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<AMFBaseValue&>(args);
|
|
uint32_t strMessageNameLength = message.size();
|
|
bitStream.Write(strMessageNameLength);
|
|
|
|
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
|
bitStream.Write<char>(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<uint32_t>(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<float>(0.0f); //duration
|
|
bitStream.Write<uint32_t>(0); //icon
|
|
bitStream.Write<uint32_t>(0); //text
|
|
bitStream.Write<uint32_t>(0); //mixer
|
|
bitStream.Write<uint32_t>(0); //cue
|
|
bitStream.Write<uint32_t>(0); //pathnodename
|
|
bitStream.Write<uint32_t>(0); //soundguid
|
|
bitStream.Write<uint32_t>(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<uint32_t>(identifier.size());
|
|
for (const auto character : identifier) {
|
|
bitStream.Write(character);
|
|
}
|
|
|
|
bitStream.Write(imageID);
|
|
|
|
bitStream.Write<uint32_t>(text.size());
|
|
for (const auto character : text) {
|
|
bitStream.Write(character);
|
|
}
|
|
|
|
bitStream.Write<uint32_t>(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<uint32_t>(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<bool>(flagsOff != eAnimationFlags::IDLE_NONE);
|
|
if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff);
|
|
bitStream.Write<bool>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<eCinematicEvent>(event);
|
|
}
|
|
|
|
float_t overallTime;
|
|
if (!inStream.ReadBit()) {
|
|
overallTime = -1.0f;
|
|
} else {
|
|
inStream.Read<float_t>(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<float_t>(pathTime);
|
|
}
|
|
|
|
int32_t waypoint;
|
|
if (!inStream.ReadBit()) {
|
|
waypoint = -1;
|
|
} else {
|
|
inStream.Read<int32_t>(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
|