mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
refactor: pet game messages as structs
Converts the pet taming minigame, naming, command and bouncer messages to
NetGameMsgs in PetMessages.{h,cpp}: NotifyPetTamingMinigame,
NotifyTamingModelLoadedOnServer, NotifyPetTamingPuzzleSelected,
PetTamingTryBuildResult, PetResponse, AddPetToPlayer, RegisterPetID,
RegisterPetDBID, ShowPetActionButton, BouncerActiveStatus, SetPetName,
SetPetNameModerated and PetNameChanged (sent), and PetTamingTryBuild,
NotifyTamingBuildSuccess, RequestSetPetName, StartServerPetMinigameTimer,
ClientExitTamingMinigame, CommandPet and DespawnPet (received, registered
in GameMessageHandler's map; each Handle hands the message to the
player's taming or active PetComponent exactly as the old handler did).
PetComponent, BouncerComponent and the hydrant/catapult scripts build
the structs; the old Send*/Handle* functions and switch cases are gone.
The never-called SendClientExitTamingMinigame is folded into the
ClientExitTamingMinigame struct. MarkInventoryItemAsActive stays with
the inventory messages.
No wire change and no change in recipients. 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 with every truncated payload rejected, hand
computed golden bytes, round trips, and a mutation check. Layouts
confirmed against the 1.10.64 client's Serialize/Deserialize in Ghidra.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "BouncerComponent.h"
|
||||
#include "PetMessages.h"
|
||||
|
||||
#include "EntityManager.h"
|
||||
#include "dZoneManager.h"
|
||||
@@ -57,7 +58,10 @@ void BouncerComponent::SetPetEnabled(bool value) {
|
||||
void BouncerComponent::SetPetBouncerEnabled(bool value) {
|
||||
m_PetBouncerEnabled = value;
|
||||
|
||||
GameMessages::SendBouncerActiveStatus(m_Parent->GetObjectID(), value, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.bActive = value;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "PetComponent.h"
|
||||
#include "DashboardNotify.h"
|
||||
#include "GameMessages.h"
|
||||
#include "PetMessages.h"
|
||||
#include "BrickDatabase.h"
|
||||
#include "CDClientDatabase.h"
|
||||
#include "CDTamingBuildPuzzleTable.h"
|
||||
@@ -205,31 +206,38 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
|
||||
auto rotation = QuatUtils::LookAt(position, petPosition);
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
originator->GetObjectID(),
|
||||
m_Parent->GetObjectID(),
|
||||
LWOOBJID_EMPTY,
|
||||
true,
|
||||
ePetTamingNotifyType::BEGIN,
|
||||
petPosition,
|
||||
position,
|
||||
rotation,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = originator->GetObjectID();
|
||||
msg.PetID = m_Parent->GetObjectID();
|
||||
msg.PlayerTamingID = LWOOBJID_EMPTY;
|
||||
msg.bForceTeleport = true;
|
||||
msg.notifyType = ePetTamingNotifyType::BEGIN;
|
||||
msg.petsDestPos = petPosition;
|
||||
msg.telePos = position;
|
||||
msg.teleRot = rotation;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
m_Parent->GetObjectID(),
|
||||
LWOOBJID_EMPTY,
|
||||
originator->GetObjectID(),
|
||||
false,
|
||||
ePetTamingNotifyType::BEGIN,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternion(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.PetID = LWOOBJID_EMPTY;
|
||||
msg.PlayerTamingID = originator->GetObjectID();
|
||||
msg.bForceTeleport = false;
|
||||
msg.notifyType = ePetTamingNotifyType::BEGIN;
|
||||
msg.petsDestPos = NiPoint3Constant::ZERO;
|
||||
msg.telePos = NiPoint3Constant::ZERO;
|
||||
msg.teleRot = NiQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
GameMessages::SendNotifyPetTamingPuzzleSelected(originator->GetObjectID(), bricks, originator->GetSystemAddress());
|
||||
{
|
||||
GameMessages::NotifyPetTamingPuzzleSelected msg;
|
||||
msg.target = originator->GetObjectID();
|
||||
msg.bricks = bricks;
|
||||
msg.Send(originator->GetSystemAddress());
|
||||
}
|
||||
|
||||
m_Tamer = originator->GetObjectID();
|
||||
SetStatus(5);
|
||||
@@ -440,7 +448,11 @@ void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) {
|
||||
|
||||
if (numBricks == 0) return;
|
||||
|
||||
GameMessages::SendPetTamingTryBuildResult(m_Tamer, !clientFailed, numBricks, tamer->GetSystemAddress());
|
||||
GameMessages::PetTamingTryBuildResult msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.bSuccess = !clientFailed;
|
||||
msg.iNumCorrect = numBricks;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
@@ -472,9 +484,21 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
|
||||
Game::entityManager->ConstructEntity(modelEntity);
|
||||
|
||||
GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::NotifyTamingModelLoadedOnServer msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendPetResponse(m_Tamer, m_Parent->GetObjectID(), 0, 10, 0, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::PetResponse msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.ObjIDPet = m_Parent->GetObjectID();
|
||||
msg.iPetCommandType = 0;
|
||||
msg.iResponse = 10;
|
||||
msg.iTypeID = 0;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
auto* inventoryComponent = tamer->GetComponent<InventoryComponent>();
|
||||
|
||||
@@ -501,11 +525,29 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
std::string petName = tamer->GetCharacter()->GetName();
|
||||
petName += "'s Pet";
|
||||
|
||||
GameMessages::SendAddPetToPlayer(m_Tamer, 0, GeneralUtils::UTF8ToUTF16(petName), petSubKey, m_Parent->GetLOT(), tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::AddPetToPlayer msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.iElementalType = 0;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(petName);
|
||||
msg.petDBID = petSubKey;
|
||||
msg.petLOT = m_Parent->GetLOT();
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetID(m_Tamer, m_Parent->GetObjectID(), tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetID msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.objID = m_Parent->GetObjectID();
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetDBID msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.petDBID = petSubKey;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
inventoryComponent->AddItem(m_Parent->GetLOT(), 1, eLootSourceType::INVENTORY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey);
|
||||
auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS);
|
||||
@@ -526,17 +568,18 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
|
||||
m_Timer = 0;
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
m_Tamer,
|
||||
LWOOBJID_EMPTY,
|
||||
LWOOBJID_EMPTY,
|
||||
false,
|
||||
ePetTamingNotifyType::NAMINGPET,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.PetID = LWOOBJID_EMPTY;
|
||||
msg.PlayerTamingID = LWOOBJID_EMPTY;
|
||||
msg.bForceTeleport = false;
|
||||
msg.notifyType = ePetTamingNotifyType::NAMINGPET;
|
||||
msg.petsDestPos = NiPoint3Constant::ZERO;
|
||||
msg.telePos = NiPoint3Constant::ZERO;
|
||||
msg.teleRot = QuatUtils::IDENTITY;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
// Triggers the catch a pet missions
|
||||
constexpr auto PET_FLAG_BASE = 800;
|
||||
@@ -569,8 +612,20 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
std::string forcedName = "Pet";
|
||||
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ forcedName, static_cast<int32_t>(m_ModerationStatus), m_Owner });
|
||||
DashboardNotify::Changed("pet_names", m_DatabaseId);
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Owner;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetNameModerated msg;
|
||||
msg.target = m_Owner;
|
||||
msg.PetDBID = m_DatabaseId;
|
||||
msg.nModerationStatus = m_ModerationStatus;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
} else {
|
||||
m_ModerationStatus = 1; // Pending
|
||||
m_Name = "";
|
||||
@@ -578,8 +633,20 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
//Save our pet's new name to the db:
|
||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name), m_Owner);
|
||||
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Owner;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetNameModerated msg;
|
||||
msg.target = m_Owner;
|
||||
msg.PetDBID = m_DatabaseId;
|
||||
msg.nModerationStatus = m_ModerationStatus;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,22 +690,48 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
|
||||
std::u16string u16name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
std::u16string u16ownerName = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
||||
GameMessages::SendSetPetName(m_Tamer, u16name, m_DatabaseId, tamer->GetSystemAddress());
|
||||
GameMessages::SendSetPetName(m_Tamer, u16name, LWOOBJID_EMPTY, tamer->GetSystemAddress());
|
||||
GameMessages::SendPetNameChanged(m_Parent->GetObjectID(), m_ModerationStatus, u16name, u16ownerName, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendSetPetNameModerated(m_Tamer, m_DatabaseId, m_ModerationStatus, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.name = u16name;
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.name = u16name;
|
||||
msg.petDBID = LWOOBJID_EMPTY;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::PetNameChanged msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.moderationStatus = m_ModerationStatus;
|
||||
msg.name = u16name;
|
||||
msg.ownerName = u16ownerName;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetNameModerated msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.PetDBID = m_DatabaseId;
|
||||
msg.nModerationStatus = m_ModerationStatus;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
m_Tamer,
|
||||
m_Parent->GetObjectID(),
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::SUCCESS,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.PetID = m_Parent->GetObjectID();
|
||||
msg.PlayerTamingID = m_Tamer;
|
||||
msg.bForceTeleport = false;
|
||||
msg.notifyType = ePetTamingNotifyType::SUCCESS;
|
||||
msg.petsDestPos = NiPoint3Constant::ZERO;
|
||||
msg.telePos = NiPoint3Constant::ZERO;
|
||||
msg.teleRot = QuatUtils::IDENTITY;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
auto* characterComponent = tamer->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
@@ -672,24 +765,29 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
m_Tamer,
|
||||
m_Parent->GetObjectID(),
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::QUIT,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.PetID = m_Parent->GetObjectID();
|
||||
msg.PlayerTamingID = m_Tamer;
|
||||
msg.bForceTeleport = false;
|
||||
msg.notifyType = ePetTamingNotifyType::QUIT;
|
||||
msg.petsDestPos = NiPoint3Constant::ZERO;
|
||||
msg.telePos = NiPoint3Constant::ZERO;
|
||||
msg.teleRot = QuatUtils::IDENTITY;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
auto* characterComponent = tamer->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
characterComponent->SetCurrentActivity(eGameActivity::NONE);
|
||||
Game::entityManager->SerializeEntity(tamer);
|
||||
}
|
||||
GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::NotifyTamingModelLoadedOnServer msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
||||
|
||||
@@ -723,24 +821,29 @@ void PetComponent::ClientFailTamingMinigame() {
|
||||
return;
|
||||
}
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
m_Tamer,
|
||||
m_Parent->GetObjectID(),
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::FAILED,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
{
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.PetID = m_Parent->GetObjectID();
|
||||
msg.PlayerTamingID = m_Tamer;
|
||||
msg.bForceTeleport = false;
|
||||
msg.notifyType = ePetTamingNotifyType::FAILED;
|
||||
msg.petsDestPos = NiPoint3Constant::ZERO;
|
||||
msg.telePos = NiPoint3Constant::ZERO;
|
||||
msg.teleRot = QuatUtils::IDENTITY;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
auto* characterComponent = tamer->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
characterComponent->SetCurrentActivity(eGameActivity::NONE);
|
||||
Game::entityManager->SerializeEntity(tamer);
|
||||
}
|
||||
GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress());
|
||||
{
|
||||
GameMessages::NotifyTamingModelLoadedOnServer msg;
|
||||
msg.target = m_Tamer;
|
||||
msg.Send(tamer->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
||||
|
||||
@@ -840,8 +943,20 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
||||
m_OwnerName = owner->GetCharacter()->GetName();
|
||||
|
||||
if (updatedModerationStatus) {
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Owner;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetNameModerated msg;
|
||||
msg.target = m_Owner;
|
||||
msg.PetDBID = m_DatabaseId;
|
||||
msg.nModerationStatus = m_ModerationStatus;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
|
||||
GameMessages::SendMarkInventoryItemAsActive(m_Owner, true, eUnequippableActiveType::PET, m_ItemId, GetOwner()->GetSystemAddress());
|
||||
@@ -855,11 +970,29 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
||||
owner->GetCharacter()->SetPlayerFlag(ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE, true);
|
||||
|
||||
if (registerPet) {
|
||||
GameMessages::SendAddPetToPlayer(m_Owner, 0, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, m_Parent->GetLOT(), owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::AddPetToPlayer msg;
|
||||
msg.target = m_Owner;
|
||||
msg.iElementalType = 0;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.petLOT = m_Parent->GetLOT();
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetID(m_Owner, m_Parent->GetObjectID(), owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetID msg;
|
||||
msg.target = m_Owner;
|
||||
msg.objID = m_Parent->GetObjectID();
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetDBID(m_Owner, m_DatabaseId, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetDBID msg;
|
||||
msg.target = m_Owner;
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,13 +1048,37 @@ void PetComponent::Deactivate() {
|
||||
|
||||
GameMessages::SendMarkInventoryItemAsActive(m_Owner, false, eUnequippableActiveType::PET, m_ItemId, owner->GetSystemAddress());
|
||||
|
||||
GameMessages::SendAddPetToPlayer(m_Owner, 0, u"", LWOOBJID_EMPTY, LOT_NULL, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::AddPetToPlayer msg;
|
||||
msg.target = m_Owner;
|
||||
msg.iElementalType = 0;
|
||||
msg.name = u"";
|
||||
msg.petDBID = LWOOBJID_EMPTY;
|
||||
msg.petLOT = LOT_NULL;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetID(m_Owner, LWOOBJID_EMPTY, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetID msg;
|
||||
msg.target = m_Owner;
|
||||
msg.objID = LWOOBJID_EMPTY;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendRegisterPetDBID(m_Owner, LWOOBJID_EMPTY, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::RegisterPetDBID msg;
|
||||
msg.target = m_Owner;
|
||||
msg.petDBID = LWOOBJID_EMPTY;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
|
||||
GameMessages::SendShowPetActionButton(m_Owner, ePetAbilityType::Invalid, false, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::ShowPetActionButton msg;
|
||||
msg.target = m_Owner;
|
||||
msg.ButtonLabel = ePetAbilityType::Invalid;
|
||||
msg.bShow = false;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
|
||||
void PetComponent::Release() {
|
||||
@@ -1092,9 +1249,28 @@ void PetComponent::ApplyNameModeration(const bool approved) {
|
||||
data.moderationState = m_ModerationStatus;
|
||||
inventoryComponent->SetDatabasePet(m_DatabaseId, data);
|
||||
}
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
{
|
||||
GameMessages::SetPetName msg;
|
||||
msg.target = m_Owner;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.petDBID = m_DatabaseId;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
{
|
||||
GameMessages::SetPetNameModerated msg;
|
||||
msg.target = m_Owner;
|
||||
msg.PetDBID = m_DatabaseId;
|
||||
msg.nModerationStatus = m_ModerationStatus;
|
||||
msg.Send(owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
{
|
||||
GameMessages::PetNameChanged msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.moderationStatus = m_ModerationStatus;
|
||||
msg.name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
msg.ownerName = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
GameMessages::SendPetNameChanged(m_Parent->GetObjectID(), m_ModerationStatus, GeneralUtils::UTF8ToUTF16(m_Name), GeneralUtils::UTF8ToUTF16(m_OwnerName), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ set(DGAME_DGAMEMESSAGES_SOURCES
|
||||
"GameMessageHandler.cpp"
|
||||
"GameMessages.cpp"
|
||||
"MissionMessages.cpp"
|
||||
"PetMessages.cpp"
|
||||
"RacingMessages.cpp"
|
||||
"PropertyDataMessage.cpp"
|
||||
"PropertySelectQueryProperty.cpp")
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "ActivityMessages.h"
|
||||
#include "RacingMessages.h"
|
||||
#include "MissionMessages.h"
|
||||
#include "PetMessages.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "ServiceType.h"
|
||||
@@ -73,6 +74,15 @@ namespace {
|
||||
{ REQUEST_LINKED_MISSION, []() { return std::make_unique<RequestLinkedMission>(); } },
|
||||
{ SET_FLAG, []() { return std::make_unique<SetFlag>(); } },
|
||||
{ HAS_BEEN_COLLECTED, []() { return std::make_unique<HasBeenCollected>(); } },
|
||||
|
||||
// Pets
|
||||
{ PET_TAMING_TRY_BUILD, []() { return std::make_unique<PetTamingTryBuild>(); } },
|
||||
{ NOTIFY_TAMING_BUILD_SUCCESS, []() { return std::make_unique<NotifyTamingBuildSuccess>(); } },
|
||||
{ REQUEST_SET_PET_NAME, []() { return std::make_unique<RequestSetPetName>(); } },
|
||||
{ START_SERVER_PET_MINIGAME_TIMER, []() { return std::make_unique<StartServerPetMinigameTimer>(); } },
|
||||
{ CLIENT_EXIT_TAMING_MINIGAME, []() { return std::make_unique<ClientExitTamingMinigame>(); } },
|
||||
{ COMMAND_PET, []() { return std::make_unique<CommandPet>(); } },
|
||||
{ DESPAWN_PET, []() { return std::make_unique<DespawnPet>(); } },
|
||||
};
|
||||
};
|
||||
|
||||
@@ -506,35 +516,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
||||
GameMessages::HandleClientTradeUpdate(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
// Pets
|
||||
case MessageType::Game::PET_TAMING_TRY_BUILD:
|
||||
GameMessages::HandlePetTamingTryBuild(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::NOTIFY_TAMING_BUILD_SUCCESS:
|
||||
GameMessages::HandleNotifyTamingBuildSuccess(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::REQUEST_SET_PET_NAME:
|
||||
GameMessages::HandleRequestSetPetName(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::START_SERVER_PET_MINIGAME_TIMER:
|
||||
GameMessages::HandleStartServerPetMinigameTimer(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::CLIENT_EXIT_TAMING_MINIGAME:
|
||||
GameMessages::HandleClientExitTamingMinigame(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::COMMAND_PET:
|
||||
GameMessages::HandleCommandPet(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::DESPAWN_PET:
|
||||
GameMessages::HandleDespawnPet(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case MessageType::Game::MESSAGE_BOX_RESPOND:
|
||||
GameMessages::HandleMessageBoxResponse(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
@@ -3188,133 +3188,6 @@ void GameMessages::HandleClientTradeUpdate(RakNet::BitStream& inStream, Entity*
|
||||
|
||||
//Pets:
|
||||
|
||||
void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId, LWOOBJID playerTamingId, bool bForceTeleport, ePetTamingNotifyType notifyType, NiPoint3 petsDestPos, NiPoint3 telePos, NiQuaternion teleRot, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_PET_TAMING_MINIGAME);
|
||||
|
||||
bitStream.Write(petId);
|
||||
bitStream.Write(playerTamingId);
|
||||
bitStream.Write(bForceTeleport);
|
||||
bitStream.Write(notifyType);
|
||||
bitStream.Write(petsDestPos);
|
||||
bitStream.Write(telePos);
|
||||
|
||||
const bool hasDefault = teleRot != QuatUtils::IDENTITY;
|
||||
bitStream.Write(hasDefault);
|
||||
if (hasDefault) bitStream.Write(teleRot);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_TAMING_MODEL_LOADED_ON_SERVER);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, const std::vector<Brick>& bricks, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_TAMING_PUZZLE_SELECTED);
|
||||
|
||||
bitStream.Write<uint32_t>(bricks.size());
|
||||
for (const auto& brick : bricks) {
|
||||
bitStream.Write(brick.designerID);
|
||||
bitStream.Write(brick.materialID);
|
||||
}
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, int32_t iNumCorrect, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_TAMING_TRY_BUILD_RESULT);
|
||||
|
||||
bitStream.Write(bSuccess);
|
||||
bitStream.Write(iNumCorrect != 0);
|
||||
if (iNumCorrect != 0) bitStream.Write(iNumCorrect);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t iPetCommandType, int32_t iResponse, int32_t iTypeID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_RESPONSE);
|
||||
|
||||
bitStream.Write(objIDPet);
|
||||
bitStream.Write(iPetCommandType);
|
||||
bitStream.Write(iResponse);
|
||||
bitStream.Write(iTypeID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, std::u16string name, LWOOBJID petDBID, LOT petLOT, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::ADD_PET_TO_PLAYER);
|
||||
|
||||
bitStream.Write(iElementalType);
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write(petDBID);
|
||||
bitStream.Write(petLOT);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::REGISTER_PET_ID);
|
||||
|
||||
bitStream.Write(objID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::REGISTER_PET_DBID);
|
||||
|
||||
bitStream.Write(petDBID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive, eUnequippableActiveType iType, LWOOBJID itemID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -3334,33 +3207,6 @@ void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::CLIENT_EXIT_TAMING_MINIGAME);
|
||||
|
||||
bitStream.Write(bVoluntaryExit);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendShowPetActionButton(const LWOOBJID objectId, const ePetAbilityType petAbility, const bool bShow, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SHOW_PET_ACTION_BUTTON);
|
||||
|
||||
bitStream.Write(petAbility);
|
||||
bitStream.Write(bShow);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
@@ -3390,213 +3236,6 @@ void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeI
|
||||
SEND_PACKET_BROADCAST;
|
||||
}
|
||||
|
||||
void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::BOUNCER_ACTIVE_STATUS);
|
||||
|
||||
bitStream.Write(bActive);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJID petDBID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SET_PET_NAME);
|
||||
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write(petDBID != LWOOBJID_EMPTY);
|
||||
if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, int32_t nModerationStatus, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SET_PET_NAME_MODERATED);
|
||||
|
||||
bitStream.Write(petDBID != LWOOBJID_EMPTY);
|
||||
if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID);
|
||||
|
||||
bitStream.Write(nModerationStatus);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatus, std::u16string name, std::u16string ownerName, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_NAME_CHANGED);
|
||||
|
||||
bitStream.Write(moderationStatus);
|
||||
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write<uint32_t>(ownerName.size());
|
||||
for (const auto character : ownerName) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::HandleClientExitTamingMinigame(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
bool bVoluntaryExit = inStream.ReadBit();
|
||||
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
petComponent->ClientExitTamingMinigame(bVoluntaryExit);
|
||||
}
|
||||
|
||||
void GameMessages::HandleStartServerPetMinigameTimer(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
petComponent->StartTimer();
|
||||
}
|
||||
|
||||
void GameMessages::HandlePetTamingTryBuild(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
uint32_t brickCount;
|
||||
std::vector<Brick> bricks;
|
||||
bool clientFailed;
|
||||
|
||||
inStream.Read(brickCount);
|
||||
|
||||
if (brickCount > MAX_MESSAGE_LENGTH) return; // Prevent DoS via unbounded brick count
|
||||
|
||||
bricks.reserve(brickCount);
|
||||
|
||||
for (uint32_t i = 0; i < brickCount; i++) {
|
||||
Brick brick;
|
||||
|
||||
inStream.Read(brick);
|
||||
|
||||
bricks.push_back(brick);
|
||||
}
|
||||
|
||||
clientFailed = inStream.ReadBit();
|
||||
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
petComponent->TryBuild(bricks.size(), clientFailed);
|
||||
}
|
||||
|
||||
void GameMessages::HandleNotifyTamingBuildSuccess(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
NiPoint3 position;
|
||||
|
||||
inStream.Read(position);
|
||||
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
petComponent->NotifyTamingBuildSuccess(position);
|
||||
}
|
||||
|
||||
void GameMessages::HandleRequestSetPetName(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
uint32_t nameLength;
|
||||
std::u16string name;
|
||||
|
||||
inStream.Read(nameLength);
|
||||
|
||||
if (nameLength > MAX_MESSAGE_LENGTH) return;
|
||||
for (size_t i = 0; i < nameLength; i++) {
|
||||
char16_t character;
|
||||
inStream.Read(character);
|
||||
name.push_back(character);
|
||||
}
|
||||
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
petComponent = PetComponent::GetActivePet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
petComponent->RequestSetPetName(name);
|
||||
}
|
||||
|
||||
void GameMessages::HandleCommandPet(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
NiPoint3 genericPosInfo;
|
||||
LWOOBJID objIdSource;
|
||||
int32_t iPetCommandType;
|
||||
int32_t iTypeID;
|
||||
bool overrideObey;
|
||||
|
||||
inStream.Read(genericPosInfo);
|
||||
inStream.Read(objIdSource);
|
||||
inStream.Read(iPetCommandType);
|
||||
inStream.Read(iTypeID);
|
||||
overrideObey = inStream.ReadBit();
|
||||
|
||||
auto* petComponent = entity->GetComponent<PetComponent>();
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
petComponent->Command(genericPosInfo, objIdSource, iPetCommandType, iTypeID, overrideObey);
|
||||
}
|
||||
|
||||
void GameMessages::HandleDespawnPet(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
bool bDeletePet;
|
||||
|
||||
bDeletePet = inStream.ReadBit();
|
||||
|
||||
auto* petComponent = PetComponent::GetActivePet(entity->GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bDeletePet) {
|
||||
petComponent->Release();
|
||||
} else {
|
||||
petComponent->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::HandleMessageBoxResponse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
int32_t iButton;
|
||||
uint32_t identifierLength;
|
||||
|
||||
@@ -446,52 +446,10 @@ namespace GameMessages {
|
||||
void HandleClientTradeUpdate(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
//Pets:
|
||||
void SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId, LWOOBJID playerTamingId, bool bForceTeleport, ePetTamingNotifyType notifyType, NiPoint3 petsDestPos, NiPoint3 telePos, NiQuaternion teleRot, const SystemAddress& sysAddr);
|
||||
|
||||
void SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, const std::vector<Brick>& bricks, const SystemAddress& sysAddr);
|
||||
|
||||
void SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SystemAddress& sysAddr);
|
||||
|
||||
void SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, int32_t iNumCorrect, const SystemAddress& sysAddr);
|
||||
|
||||
void SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t iPetCommandType, int32_t iResponse, int32_t iTypeID, const SystemAddress& sysAddr);
|
||||
|
||||
void SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, std::u16string name, LWOOBJID petDBID, LOT petLOT, const SystemAddress& sysAddr);
|
||||
|
||||
void SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const SystemAddress& sysAddr);
|
||||
|
||||
void SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, const SystemAddress& sysAddr);
|
||||
|
||||
void SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive, eUnequippableActiveType iType, LWOOBJID itemID, const SystemAddress& sysAddr);
|
||||
|
||||
void SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr);
|
||||
|
||||
void SendShowPetActionButton(const LWOOBJID objectId, const ePetAbilityType petAbility, const bool bShow, const SystemAddress& sysAddr);
|
||||
|
||||
void SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr);
|
||||
|
||||
void SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr);
|
||||
|
||||
void SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJID petDBID, const SystemAddress& sysAddr);
|
||||
|
||||
void SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, int32_t nModerationStatus, const SystemAddress& sysAddr);
|
||||
|
||||
void SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatus, std::u16string name, std::u16string ownerName, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleClientExitTamingMinigame(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleStartServerPetMinigameTimer(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandlePetTamingTryBuild(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleNotifyTamingBuildSuccess(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleRequestSetPetName(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleCommandPet(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleDespawnPet(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleMessageBoxResponse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void HandleChoiceBoxRespond(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
292
dGame/dGameMessages/PetMessages.cpp
Normal file
292
dGame/dGameMessages/PetMessages.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
#include "PetMessages.h"
|
||||
|
||||
#include "BitStreamUtils.h"
|
||||
#include "Entity.h"
|
||||
#include "PetComponent.h"
|
||||
|
||||
namespace {
|
||||
bool ReadBricks(RakNet::BitStream& bitStream, std::vector<Brick>& bricks) {
|
||||
uint32_t count{};
|
||||
VALIDATE_READ(bitStream.Read(count));
|
||||
if (count > MAX_MESSAGE_LENGTH) return false; // Prevent DoS via unbounded brick count
|
||||
if (static_cast<uint64_t>(count) * 64 > bitStream.GetNumberOfUnreadBits()) return false;
|
||||
bricks.resize(count);
|
||||
for (auto& brick : bricks) {
|
||||
VALIDATE_READ(bitStream.Read(brick.designerID));
|
||||
VALIDATE_READ(bitStream.Read(brick.materialID));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteBricks(RakNet::BitStream& bitStream, const std::vector<Brick>& bricks) {
|
||||
bitStream.Write<uint32_t>(bricks.size());
|
||||
for (const auto& brick : bricks) {
|
||||
bitStream.Write(brick.designerID);
|
||||
bitStream.Write(brick.materialID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace GameMessages {
|
||||
void NotifyPetTamingMinigame::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(PetID);
|
||||
bitStream.Write(PlayerTamingID);
|
||||
bitStream.Write(bForceTeleport);
|
||||
bitStream.Write(notifyType);
|
||||
bitStream.Write(petsDestPos);
|
||||
bitStream.Write(telePos);
|
||||
BitStreamUtils::WriteOptional(bitStream, teleRot, QuatUtils::IDENTITY);
|
||||
}
|
||||
|
||||
bool NotifyPetTamingMinigame::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(PetID));
|
||||
VALIDATE_READ(bitStream.Read(PlayerTamingID));
|
||||
VALIDATE_READ(bitStream.Read(bForceTeleport));
|
||||
VALIDATE_READ(bitStream.Read(notifyType));
|
||||
VALIDATE_READ(bitStream.Read(petsDestPos));
|
||||
VALIDATE_READ(bitStream.Read(telePos));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, teleRot, QuatUtils::IDENTITY));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientExitTamingMinigame::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(bVoluntaryExit);
|
||||
}
|
||||
|
||||
bool ClientExitTamingMinigame::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(bVoluntaryExit));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientExitTamingMinigame::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity.GetObjectID());
|
||||
if (petComponent == nullptr) return;
|
||||
petComponent->ClientExitTamingMinigame(bVoluntaryExit);
|
||||
}
|
||||
|
||||
void StartServerPetMinigameTimer::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity.GetObjectID());
|
||||
if (petComponent == nullptr) return;
|
||||
petComponent->StartTimer();
|
||||
}
|
||||
|
||||
void NotifyPetTamingPuzzleSelected::Serialize(RakNet::BitStream& bitStream) const {
|
||||
WriteBricks(bitStream, bricks);
|
||||
}
|
||||
|
||||
bool NotifyPetTamingPuzzleSelected::Deserialize(RakNet::BitStream& bitStream) {
|
||||
return ReadBricks(bitStream, bricks);
|
||||
}
|
||||
|
||||
void PetTamingTryBuild::Serialize(RakNet::BitStream& bitStream) const {
|
||||
WriteBricks(bitStream, bricks);
|
||||
bitStream.Write(clientFailed);
|
||||
}
|
||||
|
||||
bool PetTamingTryBuild::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(ReadBricks(bitStream, bricks));
|
||||
VALIDATE_READ(bitStream.Read(clientFailed));
|
||||
return true;
|
||||
}
|
||||
|
||||
void PetTamingTryBuild::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity.GetObjectID());
|
||||
if (petComponent == nullptr) return;
|
||||
petComponent->TryBuild(bricks.size(), clientFailed);
|
||||
}
|
||||
|
||||
void PetTamingTryBuildResult::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(bSuccess);
|
||||
BitStreamUtils::WriteOptional(bitStream, iNumCorrect, 0);
|
||||
}
|
||||
|
||||
bool PetTamingTryBuildResult::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(bSuccess));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, iNumCorrect, 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
void NotifyTamingBuildSuccess::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(buildPosition);
|
||||
}
|
||||
|
||||
bool NotifyTamingBuildSuccess::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(buildPosition));
|
||||
return true;
|
||||
}
|
||||
|
||||
void NotifyTamingBuildSuccess::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity.GetObjectID());
|
||||
if (petComponent == nullptr) return;
|
||||
petComponent->NotifyTamingBuildSuccess(buildPosition);
|
||||
}
|
||||
|
||||
void PetResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(ObjIDPet);
|
||||
bitStream.Write(iPetCommandType);
|
||||
bitStream.Write(iResponse);
|
||||
bitStream.Write(iTypeID);
|
||||
}
|
||||
|
||||
bool PetResponse::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(ObjIDPet));
|
||||
VALIDATE_READ(bitStream.Read(iPetCommandType));
|
||||
VALIDATE_READ(bitStream.Read(iResponse));
|
||||
VALIDATE_READ(bitStream.Read(iTypeID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddPetToPlayer::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(iElementalType);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, name);
|
||||
bitStream.Write(petDBID);
|
||||
bitStream.Write(petLOT);
|
||||
}
|
||||
|
||||
bool AddPetToPlayer::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(iElementalType));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, name));
|
||||
VALIDATE_READ(bitStream.Read(petDBID));
|
||||
VALIDATE_READ(bitStream.Read(petLOT));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterPetID::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(objID);
|
||||
}
|
||||
|
||||
bool RegisterPetID::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(objID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterPetDBID::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(petDBID);
|
||||
}
|
||||
|
||||
bool RegisterPetDBID::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(petDBID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShowPetActionButton::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(ButtonLabel);
|
||||
bitStream.Write(bShow);
|
||||
}
|
||||
|
||||
bool ShowPetActionButton::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(ButtonLabel));
|
||||
VALIDATE_READ(bitStream.Read(bShow));
|
||||
return true;
|
||||
}
|
||||
|
||||
void BouncerActiveStatus::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(bActive);
|
||||
}
|
||||
|
||||
bool BouncerActiveStatus::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(bActive));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RequestSetPetName::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, name);
|
||||
}
|
||||
|
||||
bool RequestSetPetName::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, name));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RequestSetPetName::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetTamingPet(entity.GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
petComponent = PetComponent::GetActivePet(entity.GetObjectID());
|
||||
|
||||
if (petComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
petComponent->RequestSetPetName(name);
|
||||
}
|
||||
|
||||
void SetPetName::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, name);
|
||||
BitStreamUtils::WriteOptional(bitStream, petDBID, LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
bool SetPetName::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, name));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, petDBID, LWOOBJID_EMPTY));
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetPetNameModerated::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteOptional(bitStream, PetDBID, LWOOBJID_EMPTY);
|
||||
bitStream.Write(nModerationStatus);
|
||||
}
|
||||
|
||||
bool SetPetNameModerated::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, PetDBID, LWOOBJID_EMPTY));
|
||||
VALIDATE_READ(bitStream.Read(nModerationStatus));
|
||||
return true;
|
||||
}
|
||||
|
||||
void PetNameChanged::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(moderationStatus);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, name);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, ownerName);
|
||||
}
|
||||
|
||||
bool PetNameChanged::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(moderationStatus));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, name));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, ownerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandPet::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(GenericPosInfo);
|
||||
bitStream.Write(ObjIDSource);
|
||||
bitStream.Write(iPetCommandType);
|
||||
bitStream.Write(iTypeID);
|
||||
bitStream.Write(overrideObey);
|
||||
}
|
||||
|
||||
bool CommandPet::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(GenericPosInfo));
|
||||
VALIDATE_READ(bitStream.Read(ObjIDSource));
|
||||
VALIDATE_READ(bitStream.Read(iPetCommandType));
|
||||
VALIDATE_READ(bitStream.Read(iTypeID));
|
||||
VALIDATE_READ(bitStream.Read(overrideObey));
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandPet::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = entity.GetComponent<PetComponent>();
|
||||
if (petComponent == nullptr) return;
|
||||
petComponent->Command(GenericPosInfo, ObjIDSource, iPetCommandType, iTypeID, overrideObey);
|
||||
}
|
||||
|
||||
void DespawnPet::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(bDeletePet);
|
||||
}
|
||||
|
||||
bool DespawnPet::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(bDeletePet));
|
||||
return true;
|
||||
}
|
||||
|
||||
void DespawnPet::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||
auto* petComponent = PetComponent::GetActivePet(entity.GetObjectID());
|
||||
if (petComponent == nullptr) return;
|
||||
|
||||
if (bDeletePet) {
|
||||
petComponent->Release();
|
||||
} else {
|
||||
petComponent->Deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
222
dGame/dGameMessages/PetMessages.h
Normal file
222
dGame/dGameMessages/PetMessages.h
Normal file
@@ -0,0 +1,222 @@
|
||||
#ifndef PETMESSAGES_H
|
||||
#define PETMESSAGES_H
|
||||
|
||||
#include "GameMessages.h"
|
||||
|
||||
#include "Brick.h"
|
||||
#include "ePetAbilityType.h"
|
||||
#include "ePetTamingNotifyType.h"
|
||||
#include "NiQuaternion.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Game messages for pets: the taming minigame, naming, commands and pet bouncers.
|
||||
// Field names follow the client (legouniverse.exe 1.10.64); fields are listed in wire order.
|
||||
// Messages received from a client are handled by the player's taming or active pet (PetComponent).
|
||||
namespace GameMessages {
|
||||
// Server -> client.
|
||||
struct NotifyPetTamingMinigame : public NetGameMsg {
|
||||
NotifyPetTamingMinigame() : NetGameMsg(MessageType::Game::NOTIFY_PET_TAMING_MINIGAME) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
LWOOBJID PetID{};
|
||||
LWOOBJID PlayerTamingID{};
|
||||
bool bForceTeleport{};
|
||||
ePetTamingNotifyType notifyType{};
|
||||
NiPoint3 petsDestPos{};
|
||||
NiPoint3 telePos{};
|
||||
NiQuaternion teleRot{ QuatUtils::IDENTITY }; // optional
|
||||
};
|
||||
|
||||
// Both directions. The server never sends it; the client sends it when the player leaves the minigame.
|
||||
struct ClientExitTamingMinigame : public NetGameMsg {
|
||||
ClientExitTamingMinigame() : NetGameMsg(MessageType::Game::CLIENT_EXIT_TAMING_MINIGAME) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
bool bVoluntaryExit{ true };
|
||||
};
|
||||
|
||||
// Client -> server. No payload.
|
||||
struct StartServerPetMinigameTimer : public NetGameMsg {
|
||||
StartServerPetMinigameTimer() : NetGameMsg(MessageType::Game::START_SERVER_PET_MINIGAME_TIMER) {}
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
};
|
||||
|
||||
// Server -> client. No payload.
|
||||
struct NotifyTamingModelLoadedOnServer : public NetGameMsg {
|
||||
NotifyTamingModelLoadedOnServer() : NetGameMsg(MessageType::Game::NOTIFY_TAMING_MODEL_LOADED_ON_SERVER) {}
|
||||
};
|
||||
|
||||
// Server -> client. The client's Deserialize (0x00e3a7c0) reads one more u32 after the bricks that its own
|
||||
// Serialize (0x00db6880) never writes; DLU writes what Serialize writes.
|
||||
struct NotifyPetTamingPuzzleSelected : public NetGameMsg {
|
||||
NotifyPetTamingPuzzleSelected() : NetGameMsg(MessageType::Game::NOTIFY_TAMING_PUZZLE_SELECTED) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
std::vector<Brick> bricks{}; // u32 count, then designerID and materialID per brick
|
||||
};
|
||||
|
||||
// Client -> server.
|
||||
struct PetTamingTryBuild : public NetGameMsg {
|
||||
PetTamingTryBuild() : NetGameMsg(MessageType::Game::PET_TAMING_TRY_BUILD) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
std::vector<Brick> bricks{}; // u32 count, then designerID and materialID per brick
|
||||
bool clientFailed{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct PetTamingTryBuildResult : public NetGameMsg {
|
||||
PetTamingTryBuildResult() : NetGameMsg(MessageType::Game::PET_TAMING_TRY_BUILD_RESULT) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
bool bSuccess{ true };
|
||||
int32_t iNumCorrect{}; // optional
|
||||
};
|
||||
|
||||
// Client -> server.
|
||||
struct NotifyTamingBuildSuccess : public NetGameMsg {
|
||||
NotifyTamingBuildSuccess() : NetGameMsg(MessageType::Game::NOTIFY_TAMING_BUILD_SUCCESS) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
NiPoint3 buildPosition{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct PetResponse : public NetGameMsg {
|
||||
PetResponse() : NetGameMsg(MessageType::Game::PET_RESPONSE) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
LWOOBJID ObjIDPet{};
|
||||
int32_t iPetCommandType{};
|
||||
int32_t iResponse{};
|
||||
int32_t iTypeID{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct AddPetToPlayer : public NetGameMsg {
|
||||
AddPetToPlayer() : NetGameMsg(MessageType::Game::ADD_PET_TO_PLAYER) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
int32_t iElementalType{};
|
||||
std::u16string name{};
|
||||
LWOOBJID petDBID{};
|
||||
LOT petLOT{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct RegisterPetID : public NetGameMsg {
|
||||
RegisterPetID() : NetGameMsg(MessageType::Game::REGISTER_PET_ID) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
LWOOBJID objID{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct RegisterPetDBID : public NetGameMsg {
|
||||
RegisterPetDBID() : NetGameMsg(MessageType::Game::REGISTER_PET_DBID) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
LWOOBJID petDBID{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct ShowPetActionButton : public NetGameMsg {
|
||||
ShowPetActionButton() : NetGameMsg(MessageType::Game::SHOW_PET_ACTION_BUTTON) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
ePetAbilityType ButtonLabel{};
|
||||
bool bShow{};
|
||||
};
|
||||
|
||||
// Server -> client. Turns a bouncer (usually one a pet uncovered) on or off.
|
||||
struct BouncerActiveStatus : public NetGameMsg {
|
||||
BouncerActiveStatus() : NetGameMsg(MessageType::Game::BOUNCER_ACTIVE_STATUS) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
bool bActive{};
|
||||
};
|
||||
|
||||
// Client -> server.
|
||||
struct RequestSetPetName : public NetGameMsg {
|
||||
RequestSetPetName() : NetGameMsg(MessageType::Game::REQUEST_SET_PET_NAME) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
std::u16string name{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct SetPetName : public NetGameMsg {
|
||||
SetPetName() : NetGameMsg(MessageType::Game::SET_PET_NAME) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
std::u16string name{};
|
||||
LWOOBJID petDBID{ LWOOBJID_EMPTY }; // optional
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct SetPetNameModerated : public NetGameMsg {
|
||||
SetPetNameModerated() : NetGameMsg(MessageType::Game::SET_PET_NAME_MODERATED) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
LWOOBJID PetDBID{ LWOOBJID_EMPTY }; // optional
|
||||
int32_t nModerationStatus{};
|
||||
};
|
||||
|
||||
// Server -> client.
|
||||
struct PetNameChanged : public NetGameMsg {
|
||||
PetNameChanged() : NetGameMsg(MessageType::Game::PET_NAME_CHANGED) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
|
||||
int32_t moderationStatus{};
|
||||
std::u16string name{};
|
||||
std::u16string ownerName{};
|
||||
};
|
||||
|
||||
// Client -> server.
|
||||
struct CommandPet : public NetGameMsg {
|
||||
CommandPet() : NetGameMsg(MessageType::Game::COMMAND_PET) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
NiPoint3 GenericPosInfo{};
|
||||
LWOOBJID ObjIDSource{};
|
||||
int32_t iPetCommandType{};
|
||||
int32_t iTypeID{};
|
||||
bool overrideObey{};
|
||||
};
|
||||
|
||||
// Client -> server.
|
||||
struct DespawnPet : public NetGameMsg {
|
||||
DespawnPet() : NetGameMsg(MessageType::Game::DESPAWN_PET) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
bool bDeletePet{};
|
||||
};
|
||||
};
|
||||
|
||||
#endif // PETMESSAGES_H
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "HydrantBroken.h"
|
||||
#include "PetMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
@@ -12,7 +13,10 @@ void HydrantBroken::OnStartup(Entity* self) {
|
||||
for (auto* bouncer : bouncers) {
|
||||
self->SetVar<LWOOBJID>(u"bouncer", bouncer->GetObjectID());
|
||||
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = bouncer->GetObjectID();
|
||||
msg.bActive = true;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
@@ -25,7 +29,10 @@ void HydrantBroken::OnTimerDone(Entity* self, std::string timerName) {
|
||||
auto* bouncer = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(u"bouncer"));
|
||||
|
||||
if (bouncer != nullptr) {
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = bouncer->GetObjectID();
|
||||
msg.bActive = false;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "CatapultBaseServer.h"
|
||||
#include "PetMessages.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Entity.h"
|
||||
@@ -12,7 +13,10 @@ void CatapultBaseServer::OnNotifyObject(Entity* self, Entity* sender, const std:
|
||||
// set the bouncer so we can use it later
|
||||
self->SetVar(u"Bouncer", sender->GetObjectID());
|
||||
|
||||
GameMessages::SendBouncerActiveStatus(sender->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = sender->GetObjectID();
|
||||
msg.bActive = true;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "RockHydrantBroken.h"
|
||||
#include "PetMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
@@ -13,7 +14,10 @@ void RockHydrantBroken::OnStartup(Entity* self) {
|
||||
self->SetVar<LWOOBJID>(u"bouncer", bouncer->GetObjectID());
|
||||
|
||||
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = bouncer->GetObjectID();
|
||||
msg.bActive = true;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
@@ -26,7 +30,10 @@ void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) {
|
||||
auto* bouncer = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(u"bouncer"));
|
||||
|
||||
if (bouncer != nullptr) {
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::BouncerActiveStatus msg;
|
||||
msg.target = bouncer->GetObjectID();
|
||||
msg.bActive = false;
|
||||
msg.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ SET(DGAMEMESSAGES_TESTS
|
||||
"GameMessageTests.cpp"
|
||||
"GameMsgSplitTests.cpp"
|
||||
"MissionMessagesTests.cpp"
|
||||
"PetMessagesTests.cpp"
|
||||
"RacingMessagesTests.cpp"
|
||||
"UnSmashTests.cpp"
|
||||
"LegacyGameMessageTests.cpp"
|
||||
|
||||
333
tests/dGameTests/dGameMessagesTests/Legacy/PetMessagesLegacy.h
Normal file
333
tests/dGameTests/dGameMessagesTests/Legacy/PetMessagesLegacy.h
Normal file
@@ -0,0 +1,333 @@
|
||||
#ifndef PETMESSAGESLEGACY_H
|
||||
#define PETMESSAGESLEGACY_H
|
||||
|
||||
// FROZEN ORACLE - DO NOT EDIT.
|
||||
// Verbatim copies of the hand written GameMessages functions that PetMessages.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 "BitStreamUtils.h"
|
||||
#include "Brick.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "dServer.h"
|
||||
#include "ePetAbilityType.h"
|
||||
#include "ePetTamingNotifyType.h"
|
||||
#include "Game.h"
|
||||
#include "MessageType/Client.h"
|
||||
#include "MessageType/Game.h"
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "ServiceType.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace LegacyGameMessages {
|
||||
inline void SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId, LWOOBJID playerTamingId, bool bForceTeleport, ePetTamingNotifyType notifyType, NiPoint3 petsDestPos, NiPoint3 telePos, NiQuaternion teleRot, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_PET_TAMING_MINIGAME);
|
||||
|
||||
bitStream.Write(petId);
|
||||
bitStream.Write(playerTamingId);
|
||||
bitStream.Write(bForceTeleport);
|
||||
bitStream.Write(notifyType);
|
||||
bitStream.Write(petsDestPos);
|
||||
bitStream.Write(telePos);
|
||||
|
||||
const bool hasDefault = teleRot != QuatUtils::IDENTITY;
|
||||
bitStream.Write(hasDefault);
|
||||
if (hasDefault) bitStream.Write(teleRot);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendNotifyTamingModelLoadedOnServer(LWOOBJID objectId, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_TAMING_MODEL_LOADED_ON_SERVER);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendNotifyPetTamingPuzzleSelected(LWOOBJID objectId, const std::vector<Brick>& bricks, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::NOTIFY_TAMING_PUZZLE_SELECTED);
|
||||
|
||||
bitStream.Write<uint32_t>(bricks.size());
|
||||
for (const auto& brick : bricks) {
|
||||
bitStream.Write(brick.designerID);
|
||||
bitStream.Write(brick.materialID);
|
||||
}
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendPetTamingTryBuildResult(LWOOBJID objectId, bool bSuccess, int32_t iNumCorrect, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_TAMING_TRY_BUILD_RESULT);
|
||||
|
||||
bitStream.Write(bSuccess);
|
||||
bitStream.Write(iNumCorrect != 0);
|
||||
if (iNumCorrect != 0) bitStream.Write(iNumCorrect);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendPetResponse(LWOOBJID objectId, LWOOBJID objIDPet, int32_t iPetCommandType, int32_t iResponse, int32_t iTypeID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_RESPONSE);
|
||||
|
||||
bitStream.Write(objIDPet);
|
||||
bitStream.Write(iPetCommandType);
|
||||
bitStream.Write(iResponse);
|
||||
bitStream.Write(iTypeID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendAddPetToPlayer(LWOOBJID objectId, int32_t iElementalType, std::u16string name, LWOOBJID petDBID, LOT petLOT, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::ADD_PET_TO_PLAYER);
|
||||
|
||||
bitStream.Write(iElementalType);
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write(petDBID);
|
||||
bitStream.Write(petLOT);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendRegisterPetID(LWOOBJID objectId, LWOOBJID objID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::REGISTER_PET_ID);
|
||||
|
||||
bitStream.Write(objID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendRegisterPetDBID(LWOOBJID objectId, LWOOBJID petDBID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::REGISTER_PET_DBID);
|
||||
|
||||
bitStream.Write(petDBID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::CLIENT_EXIT_TAMING_MINIGAME);
|
||||
|
||||
bitStream.Write(bVoluntaryExit);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendShowPetActionButton(const LWOOBJID objectId, const ePetAbilityType petAbility, const bool bShow, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SHOW_PET_ACTION_BUTTON);
|
||||
|
||||
bitStream.Write(petAbility);
|
||||
bitStream.Write(bShow);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::BOUNCER_ACTIVE_STATUS);
|
||||
|
||||
bitStream.Write(bActive);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendSetPetName(LWOOBJID objectId, std::u16string name, LWOOBJID petDBID, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SET_PET_NAME);
|
||||
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write(petDBID != LWOOBJID_EMPTY);
|
||||
if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendSetPetNameModerated(LWOOBJID objectId, LWOOBJID petDBID, int32_t nModerationStatus, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::SET_PET_NAME_MODERATED);
|
||||
|
||||
bitStream.Write(petDBID != LWOOBJID_EMPTY);
|
||||
if (petDBID != LWOOBJID_EMPTY) bitStream.Write(petDBID);
|
||||
|
||||
bitStream.Write(nModerationStatus);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
inline void SendPetNameChanged(LWOOBJID objectId, int32_t moderationStatus, std::u16string name, std::u16string ownerName, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(MessageType::Game::PET_NAME_CHANGED);
|
||||
|
||||
bitStream.Write(moderationStatus);
|
||||
|
||||
bitStream.Write<uint32_t>(name.size());
|
||||
for (const auto character : name) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write<uint32_t>(ownerName.size());
|
||||
for (const auto character : ownerName) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
// GameMessages::HandleClientExitTamingMinigame
|
||||
inline bool ReadClientExitTamingMinigame(RakNet::BitStream& inStream) {
|
||||
bool bVoluntaryExit = inStream.ReadBit();
|
||||
return bVoluntaryExit;
|
||||
}
|
||||
|
||||
// GameMessages::HandlePetTamingTryBuild
|
||||
struct LegacyPetTamingTryBuild { std::vector<Brick> bricks; bool clientFailed{}; bool rejected{}; };
|
||||
inline LegacyPetTamingTryBuild ReadPetTamingTryBuild(RakNet::BitStream& inStream) {
|
||||
uint32_t brickCount;
|
||||
std::vector<Brick> bricks;
|
||||
bool clientFailed;
|
||||
|
||||
inStream.Read(brickCount);
|
||||
|
||||
if (brickCount > MAX_MESSAGE_LENGTH) return { {}, false, true }; // Prevent DoS via unbounded brick count
|
||||
|
||||
bricks.reserve(brickCount);
|
||||
|
||||
for (uint32_t i = 0; i < brickCount; i++) {
|
||||
Brick brick;
|
||||
|
||||
inStream.Read(brick);
|
||||
|
||||
bricks.push_back(brick);
|
||||
}
|
||||
|
||||
clientFailed = inStream.ReadBit();
|
||||
return { bricks, clientFailed, false };
|
||||
}
|
||||
|
||||
// GameMessages::HandleNotifyTamingBuildSuccess
|
||||
inline NiPoint3 ReadNotifyTamingBuildSuccess(RakNet::BitStream& inStream) {
|
||||
NiPoint3 position;
|
||||
|
||||
inStream.Read(position);
|
||||
return position;
|
||||
}
|
||||
|
||||
// GameMessages::HandleRequestSetPetName
|
||||
struct LegacyRequestSetPetName { std::u16string name; bool rejected{}; };
|
||||
inline LegacyRequestSetPetName ReadRequestSetPetName(RakNet::BitStream& inStream) {
|
||||
uint32_t nameLength;
|
||||
std::u16string name;
|
||||
|
||||
inStream.Read(nameLength);
|
||||
|
||||
if (nameLength > MAX_MESSAGE_LENGTH) return { {}, true };
|
||||
for (size_t i = 0; i < nameLength; i++) {
|
||||
char16_t character;
|
||||
inStream.Read(character);
|
||||
name.push_back(character);
|
||||
}
|
||||
return { name, false };
|
||||
}
|
||||
|
||||
// GameMessages::HandleCommandPet
|
||||
struct LegacyCommandPet { NiPoint3 genericPosInfo; LWOOBJID objIdSource{}; int32_t iPetCommandType{}; int32_t iTypeID{}; bool overrideObey{}; };
|
||||
inline LegacyCommandPet ReadCommandPet(RakNet::BitStream& inStream) {
|
||||
NiPoint3 genericPosInfo;
|
||||
LWOOBJID objIdSource;
|
||||
int32_t iPetCommandType;
|
||||
int32_t iTypeID;
|
||||
bool overrideObey;
|
||||
|
||||
inStream.Read(genericPosInfo);
|
||||
inStream.Read(objIdSource);
|
||||
inStream.Read(iPetCommandType);
|
||||
inStream.Read(iTypeID);
|
||||
overrideObey = inStream.ReadBit();
|
||||
return { genericPosInfo, objIdSource, iPetCommandType, iTypeID, overrideObey };
|
||||
}
|
||||
|
||||
// GameMessages::HandleDespawnPet
|
||||
inline bool ReadDespawnPet(RakNet::BitStream& inStream) {
|
||||
bool bDeletePet;
|
||||
|
||||
bDeletePet = inStream.ReadBit();
|
||||
return bDeletePet;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PETMESSAGESLEGACY_H
|
||||
351
tests/dGameTests/dGameMessagesTests/PetMessagesTests.cpp
Normal file
351
tests/dGameTests/dGameMessagesTests/PetMessagesTests.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
#include "PetMessages.h"
|
||||
#include "GameDependencies.h"
|
||||
#include "GameMessageTestUtils.h"
|
||||
#include "Legacy/PetMessagesLegacy.h"
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace GameMessageTestUtils;
|
||||
|
||||
namespace {
|
||||
const std::vector<int32_t> g_Ints = { 0, 1, -1, 1727, std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min() };
|
||||
const std::vector<std::u16string> g_Strings = { u"", u"Rex", u"Pét ☃ \U0001F436", std::u16string(300, u'x') };
|
||||
const std::vector<NiPoint3> g_Points = { NiPoint3Constant::ZERO, NiPoint3(1.5f, -2.0f, 1e6f) };
|
||||
const std::vector<NiQuaternion> g_Rotations = { QuatUtils::IDENTITY, NiQuaternion(0.0f, 0.0f, 0.0f, 0.0f), NiQuaternion(0.5f, 0.5f, -0.5f, 0.5f) };
|
||||
const std::vector<std::vector<Brick>> g_BrickSets = { {}, { { 3001, 21 } }, { { 1, 2 }, { 0xFFFFFFFF, 0 }, { 3040, 194 } } };
|
||||
|
||||
PacketBytes Payload(const GameMessages::NetGameMsg& msg) {
|
||||
RakNet::BitStream bitStream;
|
||||
msg.Serialize(bitStream);
|
||||
return FromBitStream(bitStream);
|
||||
}
|
||||
|
||||
// Serializes msg, then reads it with the legacy read sequence; both must consume exactly the same bits.
|
||||
template<typename Result>
|
||||
Result ReadWithLegacy(const GameMessages::NetGameMsg& msg, const std::function<Result(RakNet::BitStream&)>& read) {
|
||||
RakNet::BitStream wire;
|
||||
msg.Serialize(wire);
|
||||
RakNet::BitStream legacyStream(wire.GetData(), wire.GetNumberOfBytesUsed(), false);
|
||||
auto result = read(legacyStream);
|
||||
EXPECT_EQ(legacyStream.GetReadOffset(), wire.GetNumberOfBitsUsed());
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SameBricks(const std::vector<Brick>& a, const std::vector<Brick>& b) {
|
||||
if (a.size() != b.size()) return false;
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
if (a[i].designerID != b[i].designerID || a[i].materialID != b[i].materialID) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class PetMessagesTests : public GameDependenciesTest {
|
||||
protected:
|
||||
void SetUp() override { SetUpDependencies(); }
|
||||
void TearDown() override { TearDownDependencies(); }
|
||||
};
|
||||
|
||||
TEST_F(PetMessagesTests, NotifyPetTamingMinigameMatchesLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto id : g_Targets) {
|
||||
for (const bool force : { false, true }) {
|
||||
for (const auto type : { ePetTamingNotifyType::SUCCESS, ePetTamingNotifyType::BEGIN, ePetTamingNotifyType::NAMINGPET, static_cast<ePetTamingNotifyType>(0xFFFFFFFF) }) {
|
||||
for (const auto& point : g_Points) {
|
||||
for (const auto& rotation : g_Rotations) {
|
||||
GameMessages::NotifyPetTamingMinigame msg;
|
||||
msg.target = target;
|
||||
msg.PetID = id;
|
||||
msg.PlayerTamingID = target;
|
||||
msg.bForceTeleport = force;
|
||||
msg.notifyType = type;
|
||||
msg.petsDestPos = point;
|
||||
msg.telePos = NiPoint3(point.z, point.x, point.y);
|
||||
msg.teleRot = rotation;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendNotifyPetTamingMinigame(target, id, target, force, type, point, msg.telePos, rotation, a); }, msg);
|
||||
const auto copy = RoundTrip(msg);
|
||||
EXPECT_EQ(copy.PetID, id);
|
||||
EXPECT_EQ(copy.notifyType, type);
|
||||
EXPECT_EQ(copy.teleRot, rotation);
|
||||
ExpectTruncatedFails(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, NoPayloadMessagesMatchLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
GameMessages::NotifyTamingModelLoadedOnServer msg;
|
||||
msg.target = target;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendNotifyTamingModelLoadedOnServer(target, a); }, msg);
|
||||
EXPECT_EQ(Payload(msg).bits, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, BrickMessagesMatchLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto& bricks : g_BrickSets) {
|
||||
GameMessages::NotifyPetTamingPuzzleSelected msg;
|
||||
msg.target = target;
|
||||
msg.bricks = bricks;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendNotifyPetTamingPuzzleSelected(target, bricks, a); }, msg);
|
||||
EXPECT_TRUE(SameBricks(RoundTrip(msg).bricks, bricks));
|
||||
ExpectTruncatedFails(msg);
|
||||
|
||||
for (const bool clientFailed : { false, true }) {
|
||||
GameMessages::PetTamingTryBuild tryBuild;
|
||||
tryBuild.bricks = bricks;
|
||||
tryBuild.clientFailed = clientFailed;
|
||||
const auto legacy = ReadWithLegacy<LegacyGameMessages::LegacyPetTamingTryBuild>(tryBuild, LegacyGameMessages::ReadPetTamingTryBuild);
|
||||
const auto copy = RoundTrip(tryBuild);
|
||||
EXPECT_FALSE(legacy.rejected);
|
||||
EXPECT_TRUE(SameBricks(copy.bricks, legacy.bricks));
|
||||
EXPECT_EQ(copy.clientFailed, legacy.clientFailed);
|
||||
ExpectTruncatedFails(tryBuild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A brick count the stream cannot hold is rejected before anything is allocated.
|
||||
RakNet::BitStream huge;
|
||||
huge.Write<uint32_t>(MAX_MESSAGE_LENGTH + 1);
|
||||
GameMessages::PetTamingTryBuild tryBuild;
|
||||
EXPECT_FALSE(tryBuild.Deserialize(huge));
|
||||
RakNet::BitStream lying;
|
||||
lying.Write<uint32_t>(1000);
|
||||
lying.Write<uint64_t>(0);
|
||||
EXPECT_FALSE(tryBuild.Deserialize(lying));
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, PetTamingTryBuildResultMatchesLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const bool success : { false, true }) {
|
||||
for (const auto numCorrect : g_Ints) {
|
||||
GameMessages::PetTamingTryBuildResult msg;
|
||||
msg.target = target;
|
||||
msg.bSuccess = success;
|
||||
msg.iNumCorrect = numCorrect;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendPetTamingTryBuildResult(target, success, numCorrect, a); }, msg);
|
||||
const auto copy = RoundTrip(msg);
|
||||
EXPECT_EQ(copy.bSuccess, success);
|
||||
EXPECT_EQ(copy.iNumCorrect, numCorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, PetResponseMatchesLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto value : g_Ints) {
|
||||
GameMessages::PetResponse msg;
|
||||
msg.target = target;
|
||||
msg.ObjIDPet = target ^ 0x55;
|
||||
msg.iPetCommandType = value;
|
||||
msg.iResponse = -value;
|
||||
msg.iTypeID = value / 2;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendPetResponse(target, msg.ObjIDPet, msg.iPetCommandType, msg.iResponse, msg.iTypeID, a); }, msg);
|
||||
const auto copy = RoundTrip(msg);
|
||||
EXPECT_EQ(copy.ObjIDPet, msg.ObjIDPet);
|
||||
EXPECT_EQ(copy.iResponse, msg.iResponse);
|
||||
ExpectTruncatedFails(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, AddPetToPlayerMatchesLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto& name : g_Strings) {
|
||||
for (const LOT lot : { LOT_NULL, 3050, 0 }) {
|
||||
GameMessages::AddPetToPlayer msg;
|
||||
msg.target = target;
|
||||
msg.iElementalType = lot / 7;
|
||||
msg.name = name;
|
||||
msg.petDBID = target;
|
||||
msg.petLOT = lot;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendAddPetToPlayer(target, msg.iElementalType, name, target, lot, a); }, msg);
|
||||
const auto copy = RoundTrip(msg);
|
||||
EXPECT_EQ(copy.name, name);
|
||||
EXPECT_EQ(copy.petLOT, lot);
|
||||
ExpectTruncatedFails(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, RegisterPetMessagesMatchLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto id : g_Targets) {
|
||||
GameMessages::RegisterPetID petId;
|
||||
petId.target = target;
|
||||
petId.objID = id;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendRegisterPetID(target, id, a); }, petId);
|
||||
EXPECT_EQ(RoundTrip(petId).objID, id);
|
||||
|
||||
GameMessages::RegisterPetDBID dbId;
|
||||
dbId.target = target;
|
||||
dbId.petDBID = id;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendRegisterPetDBID(target, id, a); }, dbId);
|
||||
EXPECT_EQ(RoundTrip(dbId).petDBID, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, BoolMessagesMatchLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const bool value : { false, true }) {
|
||||
GameMessages::ClientExitTamingMinigame exit;
|
||||
exit.target = target;
|
||||
exit.bVoluntaryExit = value;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendClientExitTamingMinigame(target, value, a); }, exit);
|
||||
EXPECT_EQ(ReadWithLegacy<bool>(exit, LegacyGameMessages::ReadClientExitTamingMinigame), value);
|
||||
EXPECT_EQ(RoundTrip(exit).bVoluntaryExit, value);
|
||||
ExpectTruncatedFails(exit);
|
||||
|
||||
GameMessages::BouncerActiveStatus bouncer;
|
||||
bouncer.target = target;
|
||||
bouncer.bActive = value;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendBouncerActiveStatus(target, value, a); }, bouncer);
|
||||
EXPECT_EQ(RoundTrip(bouncer).bActive, value);
|
||||
|
||||
GameMessages::DespawnPet despawn;
|
||||
despawn.bDeletePet = value;
|
||||
EXPECT_EQ(ReadWithLegacy<bool>(despawn, LegacyGameMessages::ReadDespawnPet), value);
|
||||
EXPECT_EQ(RoundTrip(despawn).bDeletePet, value);
|
||||
ExpectTruncatedFails(despawn);
|
||||
|
||||
for (const auto ability : { ePetAbilityType::Invalid, ePetAbilityType::DigAtPosition, static_cast<ePetAbilityType>(0xFFFFFFFF) }) {
|
||||
GameMessages::ShowPetActionButton button;
|
||||
button.target = target;
|
||||
button.ButtonLabel = ability;
|
||||
button.bShow = value;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendShowPetActionButton(target, ability, value, a); }, button);
|
||||
const auto copy = RoundTrip(button);
|
||||
EXPECT_EQ(copy.ButtonLabel, ability);
|
||||
EXPECT_EQ(copy.bShow, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, PetNameMessagesMatchLegacy) {
|
||||
for (const auto target : g_Targets) {
|
||||
for (const auto& name : g_Strings) {
|
||||
for (const auto dbId : g_Targets) {
|
||||
GameMessages::SetPetName setName;
|
||||
setName.target = target;
|
||||
setName.name = name;
|
||||
setName.petDBID = dbId;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendSetPetName(target, name, dbId, a); }, setName);
|
||||
const auto copy = RoundTrip(setName);
|
||||
EXPECT_EQ(copy.name, name);
|
||||
EXPECT_EQ(copy.petDBID, dbId);
|
||||
ExpectTruncatedFails(setName);
|
||||
}
|
||||
|
||||
for (const auto status : g_Ints) {
|
||||
GameMessages::PetNameChanged changed;
|
||||
changed.target = target;
|
||||
changed.moderationStatus = status;
|
||||
changed.name = name;
|
||||
changed.ownerName = name + u"'s owner";
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendPetNameChanged(target, status, name, changed.ownerName, a); }, changed);
|
||||
const auto copy = RoundTrip(changed);
|
||||
EXPECT_EQ(copy.name, name);
|
||||
EXPECT_EQ(copy.ownerName, changed.ownerName);
|
||||
ExpectTruncatedFails(changed);
|
||||
}
|
||||
|
||||
GameMessages::RequestSetPetName request;
|
||||
request.name = name;
|
||||
const auto legacy = ReadWithLegacy<LegacyGameMessages::LegacyRequestSetPetName>(request, LegacyGameMessages::ReadRequestSetPetName);
|
||||
EXPECT_FALSE(legacy.rejected);
|
||||
EXPECT_EQ(RoundTrip(request).name, legacy.name);
|
||||
ExpectTruncatedFails(request);
|
||||
}
|
||||
|
||||
for (const auto dbId : g_Targets) {
|
||||
for (const auto status : g_Ints) {
|
||||
GameMessages::SetPetNameModerated moderated;
|
||||
moderated.target = target;
|
||||
moderated.PetDBID = dbId;
|
||||
moderated.nModerationStatus = status;
|
||||
ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendSetPetNameModerated(target, dbId, status, a); }, moderated);
|
||||
const auto copy = RoundTrip(moderated);
|
||||
EXPECT_EQ(copy.PetDBID, dbId);
|
||||
EXPECT_EQ(copy.nModerationStatus, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PetMessagesTests, InboundReadsLikeLegacy) {
|
||||
for (const auto& point : g_Points) {
|
||||
GameMessages::NotifyTamingBuildSuccess success;
|
||||
success.buildPosition = point;
|
||||
EXPECT_EQ(ReadWithLegacy<NiPoint3>(success, LegacyGameMessages::ReadNotifyTamingBuildSuccess), point);
|
||||
EXPECT_EQ(RoundTrip(success).buildPosition, point);
|
||||
ExpectTruncatedFails(success);
|
||||
|
||||
for (const auto id : g_Targets) {
|
||||
for (const auto value : g_Ints) {
|
||||
for (const bool obey : { false, true }) {
|
||||
GameMessages::CommandPet command;
|
||||
command.GenericPosInfo = point;
|
||||
command.ObjIDSource = id;
|
||||
command.iPetCommandType = value;
|
||||
command.iTypeID = -value;
|
||||
command.overrideObey = obey;
|
||||
const auto legacy = ReadWithLegacy<LegacyGameMessages::LegacyCommandPet>(command, LegacyGameMessages::ReadCommandPet);
|
||||
const auto copy = RoundTrip(command);
|
||||
EXPECT_EQ(copy.GenericPosInfo, legacy.genericPosInfo);
|
||||
EXPECT_EQ(copy.ObjIDSource, legacy.objIdSource);
|
||||
EXPECT_EQ(copy.iPetCommandType, legacy.iPetCommandType);
|
||||
EXPECT_EQ(copy.iTypeID, legacy.iTypeID);
|
||||
EXPECT_EQ(copy.overrideObey, legacy.overrideObey);
|
||||
ExpectTruncatedFails(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Independent of the legacy code: hand computed payloads (RakNet writes MSB first).
|
||||
TEST_F(PetMessagesTests, GoldenBytes) {
|
||||
GameMessages::PetTamingTryBuildResult result;
|
||||
EXPECT_PACKET_EQ(FromHex("80", 2), Payload(result));
|
||||
result.bSuccess = false;
|
||||
result.iNumCorrect = 3;
|
||||
// 0, 1, then 03 00 00 00 shifted right by two bits
|
||||
EXPECT_PACKET_EQ(FromHex("40 c0 00 00 00", 34), Payload(result));
|
||||
|
||||
GameMessages::NotifyPetTamingPuzzleSelected puzzle;
|
||||
puzzle.bricks = { { 3001, 21 } };
|
||||
EXPECT_PACKET_EQ(FromHex("01 00 00 00 b9 0b 00 00 15 00 00 00"), Payload(puzzle));
|
||||
|
||||
GameMessages::SetPetName setName;
|
||||
setName.name = u"Hi";
|
||||
EXPECT_PACKET_EQ(FromHex("02 00 00 00 48 00 69 00 00", 65), Payload(setName));
|
||||
setName.petDBID = 0x11;
|
||||
EXPECT_PACKET_EQ(FromHex("02 00 00 00 48 00 69 00 88 80 00 00 00 00 00 00 00", 129), Payload(setName));
|
||||
|
||||
GameMessages::SetPetNameModerated moderated;
|
||||
moderated.nModerationStatus = 2;
|
||||
EXPECT_PACKET_EQ(FromHex("01 00 00 00 00", 33), Payload(moderated));
|
||||
|
||||
GameMessages::ShowPetActionButton button;
|
||||
button.ButtonLabel = ePetAbilityType::JumpOnObject;
|
||||
button.bShow = true;
|
||||
EXPECT_PACKET_EQ(FromHex("02 00 00 00 80", 33), Payload(button));
|
||||
|
||||
GameMessages::DespawnPet despawn;
|
||||
despawn.bDeletePet = true;
|
||||
EXPECT_PACKET_EQ(FromHex("80", 1), Payload(despawn));
|
||||
}
|
||||
Reference in New Issue
Block a user