mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-11 15:23:43 +00:00
refactor: effects, audio, animation and UI text game messages as structs
Converts PlayAnimation, PlayNDAudioEmitter, PlayEmbeddedEffectOnAllClientsNearObject,
PlayFXEffect, StopFXEffect, BroadcastTextToChatbox, Play2DAmbientSound,
Stop2DAmbientSound, UIMessageServerToSingleClient, UIMessageServerToAllClients,
StartCelebrationEffect, DisplayMessageBox, DisplayChatBubble, ChangeIdleFlags,
SetNameBillboardState, ShowBillboardInteractIcon, PlayCinematic, EndCinematic,
SlashCommandTextFeedback, PlayEmote and SetEmoteLockState (21 old Send
functions, 23 with overloads) and the received MessageBoxRespond,
ChoiceBoxRespond, CinematicUpdate and PlayEmote to NetGameMsgs in
EffectsMessages.{h,cpp}. The high traffic messages get a constructor for their
required fields. UI messages own their AMF arguments. Every caller is switched,
the received messages are registered in GameMessageHandler's map, and the old
functions and switch cases are deleted. Handlers are copied verbatim.
No wire change and no change in recipients: functions that always broadcast
whatever address they were given are sent with Send(UNASSIGNED_SYSTEM_ADDRESS),
functions that only did SEND_PACKET use SendToClient. Quirks are kept and
documented on the structs (PlayAnimation's UTF-8 sized name, the always written
null terminator in BroadcastTextToChatbox, StartCelebrationEffect always
writing celebrationID, SetNameBillboardState having no payload).
Verified byte for byte against a frozen verbatim copy of the old functions over
an input grid, to one client and broadcast; received messages compared with the
old handlers' read sequences and every truncated payload rejected; hand
computed golden bytes; round trips; a deliberate width mutation made the tests
fail. The byte-equality helper gains a Broadcast mode for functions that
ignored their address.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "GameMessages.h"
|
||||
#include "EffectsMessages.h"
|
||||
#include "DashboardNotify.h"
|
||||
#include "PlayerReports.h"
|
||||
#include "EconomyLedger.h"
|
||||
@@ -162,43 +163,6 @@ void GameMessages::SendTeleport(const LWOOBJID& objectID, const NiPoint3& pos, c
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendPlayerReady(Entity* entity, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -283,28 +247,6 @@ void GameMessages::SendPlayerSetCameraCyclingMode(const LWOOBJID& objectID, cons
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendStartPathing(Entity* entity) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -491,153 +433,6 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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);
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendSetCurrency(Entity* entity, int64_t currency, int lootType, const LWOOBJID& sourceID, const LOT& sourceLOT, int sourceTradeID, bool overrideCurrent, eLootSourceType sourceType) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -792,19 +587,6 @@ void GameMessages::SendSetInventorySize(Entity* entity, int invType, int size) {
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendSetJetPackMode(Entity* entity, bool use, bool bypassChecks, bool doHover, int effectID, float airspeed, float maxAirspeed, float verticalVelocity, int warningEffectID) {
|
||||
/* historical jamesster jetpack values
|
||||
if (bIsJamessterPhysics) {
|
||||
@@ -880,47 +662,6 @@ void GameMessages::SendResurrect(Entity* entity) {
|
||||
SEND_PACKET_BROADCAST;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendSetNetworkScriptVar(Entity* entity, const SystemAddress& sysAddr, std::string data) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -1424,33 +1165,6 @@ void GameMessages::HandleActivityStateChangeRequest(RakNet::BitStream& inStream,
|
||||
entity->OnActivityStateChangeRequest(objectID, value1, value2, stringValue);
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendSetRailMovement(const LWOOBJID& objectID, bool pathGoForward, std::u16string pathName,
|
||||
uint32_t pathStart, const SystemAddress& sysAddr, int32_t railActivatorComponentID,
|
||||
LWOOBJID railActivatorObjectID) {
|
||||
@@ -1696,114 +1410,6 @@ void GameMessages::HandleSetConsumableItem(RakNet::BitStream& inStream, Entity*
|
||||
inventory->SetConsumable(lot);
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::HandleCinematicUpdate(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
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);
|
||||
}
|
||||
|
||||
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT);
|
||||
for (Entity* scriptEntity : scriptedActs) {
|
||||
scriptEntity->OnCinematicUpdate(scriptEntity, entity, event, pathName, pathTime, overallTime, waypoint);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr,
|
||||
LWOOBJID originator, bool bCantAttack, bool bCantEquip,
|
||||
bool bCantInteract, bool bCantJump, bool bCantMove, bool bCantTurn,
|
||||
@@ -2296,20 +1902,6 @@ void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -2325,106 +1917,6 @@ void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeI
|
||||
SEND_PACKET_BROADCAST;
|
||||
}
|
||||
|
||||
void GameMessages::HandleMessageBoxResponse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
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);
|
||||
}
|
||||
|
||||
LOG("Button: %d; LOT: %u identifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(identifier).c_str(), GeneralUtils::UTF16ToWTF8(userData).c_str());
|
||||
|
||||
auto* user = UserManager::Instance()->GetUser(sysAddr);
|
||||
|
||||
if (user == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* userEntity = user->GetLastUsedChar()->GetEntity();
|
||||
|
||||
if (userEntity == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
entity->OnMessageBoxResponse(userEntity, iButton, identifier, userData);
|
||||
|
||||
auto* scriptedActivityComponent = entity->GetComponent<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent != nullptr) {
|
||||
scriptedActivityComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier));
|
||||
}
|
||||
|
||||
auto* racingControlComponent = entity->GetComponent<RacingControlComponent>();
|
||||
|
||||
if (racingControlComponent != nullptr) {
|
||||
racingControlComponent->HandleMessageBoxResponse(userEntity, iButton, GeneralUtils::UTF16ToWTF8(identifier));
|
||||
}
|
||||
|
||||
for (auto* shootingGallery : Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SHOOTING_GALLERY)) {
|
||||
shootingGallery->OnMessageBoxResponse(userEntity, iButton, identifier, userData);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
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);
|
||||
}
|
||||
|
||||
LOG("Button: %d; LOT: %u buttonIdentifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(buttonIdentifier).c_str(), GeneralUtils::UTF16ToWTF8(identifier).c_str());
|
||||
|
||||
auto* user = UserManager::Instance()->GetUser(sysAddr);
|
||||
|
||||
if (user == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* userEntity = user->GetLastUsedChar()->GetEntity();
|
||||
|
||||
if (userEntity == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
entity->OnChoiceBoxResponse(userEntity, iButton, buttonIdentifier, identifier);
|
||||
}
|
||||
|
||||
void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap, bool isZoneStart, LWOOBJID sender) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -2458,68 +1950,6 @@ void GameMessages::SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeS
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) {
|
||||
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;
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
// Mounts
|
||||
|
||||
void GameMessages::SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr) {
|
||||
@@ -3143,59 +2573,6 @@ void GameMessages::HandleQuickBuildCancel(RakNet::BitStream& inStream, Entity* e
|
||||
quickBuildComponent->CancelQuickBuild(Game::entityManager->GetEntity(userID), eQuickBuildFailReason::CANCELED_EARLY);
|
||||
}
|
||||
|
||||
void GameMessages::HandlePlayEmote(RakNet::BitStream& inStream, Entity* entity) {
|
||||
int32_t emoteID;
|
||||
LWOOBJID targetID;
|
||||
|
||||
inStream.Read(emoteID);
|
||||
inStream.Read(targetID);
|
||||
|
||||
LOG_DEBUG("Emote (%i) (%llu)", emoteID, targetID);
|
||||
|
||||
//TODO: If targetID != 0, and we have one of the "perform emote" missions, complete them.
|
||||
|
||||
if (emoteID == 0) return;
|
||||
std::string sAnimationName = "deaded"; //Default name in case we fail to get the emote
|
||||
|
||||
CDEmoteTableTable* emotes = CDClientManager::GetTable<CDEmoteTableTable>();
|
||||
if (emotes) {
|
||||
CDEmoteTable* emote = emotes->GetEmote(emoteID);
|
||||
if (emote) sAnimationName = emote->animationName;
|
||||
}
|
||||
|
||||
GameMessages::EmotePlayed msg;
|
||||
msg.target = entity->GetObjectID();
|
||||
msg.emoteID = emoteID;
|
||||
msg.targetID = targetID; // The emote’s target entity or 0 if none
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS); // Broadcast to all clients
|
||||
|
||||
MissionComponent* missionComponent = entity->GetComponent<MissionComponent>();
|
||||
if (!missionComponent) return;
|
||||
|
||||
if (targetID != LWOOBJID_EMPTY) {
|
||||
auto* targetEntity = Game::entityManager->GetEntity(targetID);
|
||||
|
||||
LOG_DEBUG("Emote target found (%d)", targetEntity != nullptr);
|
||||
|
||||
if (targetEntity != nullptr) {
|
||||
targetEntity->OnEmoteReceived(emoteID, entity);
|
||||
missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, targetID);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("Target ID is empty, using backup");
|
||||
const auto scriptedEntities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT);
|
||||
|
||||
const auto& referencePoint = entity->GetPosition();
|
||||
|
||||
for (auto* scripted : scriptedEntities) {
|
||||
if (Vector3::DistanceSquared(scripted->GetPosition(), referencePoint) > 5.0f * 5.0f) continue;
|
||||
|
||||
scripted->OnEmoteReceived(emoteID, entity);
|
||||
missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, scripted->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream& inStream, Entity* entity) {
|
||||
auto* levelComp = entity->GetComponent<LevelProgressionComponent>();
|
||||
if (!levelComp) return;
|
||||
@@ -3218,7 +2595,7 @@ void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream&
|
||||
}
|
||||
|
||||
//Play the level up effect:
|
||||
GameMessages::SendPlayFXEffect(entity, 7074, u"create", "7074", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
|
||||
GameMessages::PlayFXEffect(entity->GetObjectID(), 7074, u"create", "7074").Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
//Send a notification in chat:
|
||||
std::stringstream wss;
|
||||
@@ -3232,7 +2609,11 @@ void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream&
|
||||
std::u16string attrs = GeneralUtils::UTF8ToUTF16(wss.str());
|
||||
std::u16string wsText = u"UI_LEVEL_PROGRESSION_LEVELUP_MESSAGE";
|
||||
|
||||
GameMessages::SendBroadcastTextToChatbox(entity, UNASSIGNED_SYSTEM_ADDRESS, attrs, wsText);
|
||||
GameMessages::BroadcastTextToChatbox chatboxText;
|
||||
chatboxText.target = entity->GetObjectID();
|
||||
chatboxText.attrs = attrs;
|
||||
chatboxText.wsText = wsText;
|
||||
chatboxText.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
void GameMessages::HandlePickupCurrency(RakNet::BitStream& inStream, Entity* entity) {
|
||||
@@ -3809,35 +3190,6 @@ void GameMessages::HandleZoneSummaryDismissed(RakNet::BitStream& inStream, Entit
|
||||
entity->TriggerEvent(eTriggerEventType::ZONE_SUMMARY_DISMISSED, target);
|
||||
};
|
||||
|
||||
void GameMessages::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
|
||||
}
|
||||
|
||||
void GameMessages::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
|
||||
}
|
||||
|
||||
void GameMessages::HandleAddDonationItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
uint32_t count = 1;
|
||||
bool hasCount = false;
|
||||
@@ -3937,18 +3289,6 @@ void GameMessages::HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Ent
|
||||
characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
void GameMessages::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;
|
||||
}
|
||||
|
||||
void GameMessages::HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
std::string action;
|
||||
std::u16string groupName;
|
||||
|
||||
Reference in New Issue
Block a user