mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
WIRE FIX. DLU sent NotifyNotEnoughInvSpace with the ID of VehicleNotifyFinishedRace (1396). The 1.10.64 client registers it as NOTIFY_NOT_ENOUGH_INV_SPACE (1516, 0x00545c90) and reads freeSlotsNeeded followed by the optional inventoryType (0x00d8b850), which is what the payload already was. Only the message ID changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
367 lines
15 KiB
C++
367 lines
15 KiB
C++
#ifndef INVENTORYMESSAGES_H
|
|
#define INVENTORYMESSAGES_H
|
|
|
|
#include "GameMessages.h"
|
|
#include "eInventoryType.h"
|
|
#include "eLootSourceType.h"
|
|
#include "eReponseMoveItemBetweenInventoryTypeCode.h"
|
|
#include "eUnequippableActiveType.h"
|
|
#include "eUseItemResponse.h"
|
|
#include "NiPoint3.h"
|
|
|
|
#include <string>
|
|
|
|
class Item;
|
|
|
|
// Game messages for inventories and items: adding, removing, moving, equipping and using items, inventory sizes
|
|
// and groups.
|
|
// Field names follow the client (legouniverse.exe 1.10.64); fields are listed in wire order.
|
|
// Received messages are handled by the target's InventoryComponent.
|
|
namespace GameMessages {
|
|
// Server -> client.
|
|
struct AddItemToInventoryClientSync : public NetGameMsg {
|
|
AddItemToInventoryClientSync() : NetGameMsg(MessageType::Game::ADD_ITEM_TO_INVENTORY_CLIENT_SYNC) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
// Fills the fields that describe the item itself (bound flags, extra info, LOT, inventory, stack total and
|
|
// slot). The caller sets the rest.
|
|
void SetItem(const Item& item);
|
|
|
|
bool bBound{};
|
|
bool bIsBOE{};
|
|
bool bIsBOP{};
|
|
eLootSourceType eLootTypeSource{ eLootSourceType::NONE }; // optional
|
|
// Name value text: u32 length and the characters, then a null character if it is not empty.
|
|
std::u16string extraInfo{};
|
|
LOT iObjTemplate{};
|
|
LWOOBJID iSubkey{ LWOOBJID_EMPTY }; // optional
|
|
eInventoryType invType{ eInventoryType::ITEMS }; // optional
|
|
int32_t itemCount{ 1 }; // optional
|
|
uint32_t itemsTotal{ 0 }; // optional
|
|
LWOOBJID newObjID{};
|
|
NiPoint3 ni3FlyingLootPosit{};
|
|
bool showFlyingLoot{};
|
|
uint32_t slotID{};
|
|
};
|
|
|
|
// Server -> client.
|
|
struct SetInventorySize : public NetGameMsg {
|
|
SetInventorySize() : NetGameMsg(MessageType::Game::SET_INVENTORY_SIZE) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
eInventoryType inventoryType{};
|
|
int32_t size{};
|
|
};
|
|
|
|
// Both directions: the client asks to delete (trash) an item, and the server tells the client an item left
|
|
// its inventory. DLU always sends the flag of the fields marked "always sent" (they are still read as optional).
|
|
struct RemoveItemFromInventory : public NetGameMsg {
|
|
RemoveItemFromInventory() : NetGameMsg(MessageType::Game::REMOVE_ITEM_FROM_INVENTORY) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
bool bConfirmed{};
|
|
bool bDeleteItem{ true };
|
|
bool bOutSuccess{};
|
|
int32_t eInvType{ INVENTORY_MAX }; // optional, always sent
|
|
int32_t eLootTypeSource{ LOOTTYPE_NONE }; // optional, always sent
|
|
// Name value text: u32 length and the characters, then a null character if it is not empty.
|
|
std::u16string extraInfo{};
|
|
bool forceDeletion{ true };
|
|
LWOOBJID iLootTypeSource{ LWOOBJID_EMPTY }; // optional
|
|
LWOOBJID iObjID{ LWOOBJID_EMPTY }; // optional, always sent
|
|
LOT iObjTemplate{ LOT_NULL }; // optional, always sent
|
|
LWOOBJID iRequestingObjID{ LWOOBJID_EMPTY }; // optional
|
|
uint32_t iStackCount{ 1 }; // optional, always sent
|
|
uint32_t iStackRemaining{ 0 }; // optional, always sent
|
|
LWOOBJID iSubkey{ LWOOBJID_EMPTY }; // optional
|
|
LWOOBJID iTradeID{ LWOOBJID_EMPTY }; // optional
|
|
};
|
|
|
|
// Client -> server.
|
|
struct EquipInventory : public NetGameMsg {
|
|
EquipInventory() : NetGameMsg(MessageType::Game::EQUIP_INVENTORY) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
bool bIgnoreCooldown{};
|
|
bool bOutSuccess{};
|
|
LWOOBJID itemToEquip{};
|
|
};
|
|
|
|
// Client -> server. The client also sends an optional replacementObjectID after itemToUnequip, which DLU
|
|
// has never read (and still does not).
|
|
struct UnEquipInventory : public NetGameMsg {
|
|
UnEquipInventory() : NetGameMsg(MessageType::Game::UN_EQUIP_INVENTORY) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
bool bEvenIfDead{};
|
|
bool bIgnoreCooldown{};
|
|
bool bOutSuccess{};
|
|
LWOOBJID itemToUnequip{};
|
|
};
|
|
|
|
// Client -> server.
|
|
struct MoveItemInInventory : public NetGameMsg {
|
|
MoveItemInInventory() : NetGameMsg(MessageType::Game::MOVE_ITEM_IN_INVENTORY) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
int32_t destInvType{ eInventoryType::INVALID }; // optional
|
|
LWOOBJID iObjID{};
|
|
int32_t inventoryType{};
|
|
int32_t responseCode{};
|
|
int32_t slot{};
|
|
};
|
|
|
|
// Client -> server.
|
|
struct MoveItemBetweenInventoryTypes : public NetGameMsg {
|
|
MoveItemBetweenInventoryTypes() : NetGameMsg(MessageType::Game::MOVE_ITEM_BETWEEN_INVENTORY_TYPES) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
eInventoryType inventoryTypeA{};
|
|
eInventoryType inventoryTypeB{};
|
|
LWOOBJID objectID{};
|
|
bool showFlyingLoot{ true };
|
|
uint32_t stackCount{ 1 }; // optional
|
|
LOT templateID{ LOT_NULL }; // optional
|
|
};
|
|
|
|
// Client -> server. Answered with ResponseMoveItemBetweenInventoryTypes.
|
|
struct RequestMoveItemBetweenInventoryTypes : public NetGameMsg {
|
|
RequestMoveItemBetweenInventoryTypes() : NetGameMsg(MessageType::Game::REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
bool bAllowPartial{};
|
|
int32_t destSlot{ -1 }; // optional
|
|
int32_t iStackCount{ 1 }; // optional
|
|
eInventoryType invTypeDst{ eInventoryType::ITEMS }; // optional
|
|
eInventoryType invTypeSrc{ eInventoryType::ITEMS }; // optional
|
|
LWOOBJID itemID{ LWOOBJID_EMPTY }; // optional
|
|
bool showFlyingLoot{};
|
|
LWOOBJID subkey{ LWOOBJID_EMPTY }; // optional
|
|
LOT itemLOT{ LOT_NULL }; // optional
|
|
};
|
|
|
|
// Server -> client.
|
|
struct ResponseMoveItemBetweenInventoryTypes : public NetGameMsg {
|
|
ResponseMoveItemBetweenInventoryTypes() : NetGameMsg(MessageType::Game::RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
eInventoryType inventoryTypeDestination{ eInventoryType::ITEMS }; // optional
|
|
eInventoryType inventoryTypeSource{ eInventoryType::ITEMS }; // optional
|
|
eReponseMoveItemBetweenInventoryTypeCode response{ eReponseMoveItemBetweenInventoryTypeCode::FAIL_GENERIC }; // optional
|
|
};
|
|
|
|
// Server -> client. Moves count items out of srcBag (the client fills dstBag from a following
|
|
// AddItemToInventoryClientSync). Laid out as the client reads it; DLU does not send it.
|
|
struct MoveInventoryBatch : public NetGameMsg {
|
|
MoveInventoryBatch() : NetGameMsg(MessageType::Game::MOVE_INVENTORY_BATCH) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
// Client -> server: brick by brick moving bricks between BRICKS and BRICKS_IN_BBB. The client has already taken
|
|
// them out of srcBag (LWOInventoryComponent_Common::msgMoveInventoryBatch, 0x00ce1310) and waits for
|
|
// AddItemToInventoryClientSync for dstBag.
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
bool bAllowPartial{};
|
|
bool bOutSuccess{};
|
|
uint32_t count{ 1 }; // optional
|
|
eInventoryType dstBag{ eInventoryType::ITEMS }; // optional
|
|
LOT moveLOT{ LOT_NULL }; // optional
|
|
LWOOBJID moveSubkey{ LWOOBJID_EMPTY }; // optional
|
|
bool showFlyingLoot{};
|
|
eInventoryType srcBag{ eInventoryType::ITEMS }; // optional
|
|
LWOOBJID startObjectID{ LWOOBJID_EMPTY }; // optional
|
|
};
|
|
|
|
// Server -> client. WIRE FIX: DLU used to send this with the ID of VehicleNotifyFinishedRace (1396); the client
|
|
// registers it as NOTIFY_NOT_ENOUGH_INV_SPACE (1516, msgNotifyNotEnoughInvSpace::GetMsgID @ 00545c90 in 1.10.64)
|
|
// and reads freeSlotsNeeded then the optional inventoryType (00d8b850).
|
|
struct NotifyNotEnoughInvSpace : public NetGameMsg {
|
|
NotifyNotEnoughInvSpace() : NetGameMsg(MessageType::Game::NOTIFY_NOT_ENOUGH_INV_SPACE) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
uint32_t freeSlotsNeeded{};
|
|
eInventoryType inventoryType{ eInventoryType::ITEMS }; // optional
|
|
};
|
|
|
|
// Server -> client. No payload. The client sends it to itself normally; DLU sends it to refresh the inventory
|
|
// UI (its defaults get around items that would otherwise stay invisible).
|
|
struct UpdateInventoryUi : public NetGameMsg {
|
|
UpdateInventoryUi() : NetGameMsg(MessageType::Game::UPDATE_INVENTORY_UI) {}
|
|
};
|
|
|
|
// Server -> client. Marks a pet or mount item as in use (or no longer).
|
|
struct MarkInventoryItemAsActive : public NetGameMsg {
|
|
MarkInventoryItemAsActive() : NetGameMsg(MessageType::Game::MARK_INVENTORY_ITEM_AS_ACTIVE) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
bool bActive{};
|
|
eUnequippableActiveType iType{ eUnequippableActiveType::INVALID }; // optional
|
|
LWOOBJID itemID{ LWOOBJID_EMPTY }; // optional
|
|
};
|
|
|
|
// Server -> client.
|
|
struct ConsumeClientItem : public NetGameMsg {
|
|
ConsumeClientItem() : NetGameMsg(MessageType::Game::CONSUME_CLIENT_ITEM) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
bool bSuccess{};
|
|
LWOOBJID item{};
|
|
};
|
|
|
|
// Client -> server.
|
|
struct ClientItemConsumed : public NetGameMsg {
|
|
ClientItemConsumed() : NetGameMsg(MessageType::Game::CLIENT_ITEM_CONSUMED) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
LWOOBJID item{};
|
|
};
|
|
|
|
// Client -> server.
|
|
struct UseNonEquipmentItem : public NetGameMsg {
|
|
UseNonEquipmentItem() : NetGameMsg(MessageType::Game::USE_NON_EQUIPMENT_ITEM) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
LWOOBJID itemToUse{};
|
|
};
|
|
|
|
// Server -> client.
|
|
struct UseItemResult : public NetGameMsg {
|
|
UseItemResult() : NetGameMsg(MessageType::Game::USE_ITEM_RESULT) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
LOT itemTemplateID{};
|
|
bool useItemResult{};
|
|
};
|
|
|
|
// Server -> client.
|
|
struct UseItemRequirementsResponse : public NetGameMsg {
|
|
UseItemRequirementsResponse() : NetGameMsg(MessageType::Game::USE_ITEM_REQUIREMENTS_RESPONSE) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
eUseItemResponse eUseResponse{};
|
|
};
|
|
|
|
// Client -> server.
|
|
struct SetConsumableItem : public NetGameMsg {
|
|
SetConsumableItem() : NetGameMsg(MessageType::Game::SET_CONSUMABLE_ITEM) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
LOT itemTemplateID{};
|
|
};
|
|
|
|
// Client -> server. No payload.
|
|
struct PushEquippedItemsState : public NetGameMsg {
|
|
PushEquippedItemsState() : NetGameMsg(MessageType::Game::PUSH_EQUIPPED_ITEMS_STATE) {}
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
};
|
|
|
|
// Client -> server. No payload.
|
|
struct PopEquippedItemsState : public NetGameMsg {
|
|
PopEquippedItemsState() : NetGameMsg(MessageType::Game::POP_EQUIPPED_ITEMS_STATE) {}
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
};
|
|
|
|
// Client -> server. Adds, modifies or removes an inventory group.
|
|
struct UpdateInventoryGroup : public NetGameMsg {
|
|
UpdateInventoryGroup() : NetGameMsg(MessageType::Game::UPDATE_INVENTORY_GROUP) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
std::string action{}; // ADD, MODIFY or REMOVE
|
|
std::string groupID{};
|
|
std::u16string groupName{};
|
|
eInventoryType inventoryType{};
|
|
bool locked{};
|
|
};
|
|
|
|
// Client -> server. Adds a LOT to or removes one from an inventory group.
|
|
struct UpdateInventoryGroupContents : public NetGameMsg {
|
|
UpdateInventoryGroupContents() : NetGameMsg(MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
std::string action{}; // ADD or REMOVE
|
|
std::string groupID{};
|
|
eInventoryType inventoryType{};
|
|
LOT lot{};
|
|
};
|
|
|
|
struct UseItemOnClient : public NetGameMsg {
|
|
UseItemOnClient() : NetGameMsg(MessageType::Game::USE_ITEM_ON_CLIENT) {}
|
|
LWOOBJID playerId{};
|
|
LWOOBJID itemToUse{};
|
|
uint32_t itemType{};
|
|
LOT itemLOT{};
|
|
NiPoint3 targetPosition{};
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
};
|
|
|
|
struct DropClientLoot : public NetGameMsg {
|
|
DropClientLoot() : NetGameMsg(MessageType::Game::DROP_CLIENT_LOOT) {}
|
|
|
|
void Serialize(RakNet::BitStream& stream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
LWOOBJID sourceID{ LWOOBJID_EMPTY };
|
|
LOT item{ LOT_NULL };
|
|
int32_t currency{};
|
|
NiPoint3 spawnPos{};
|
|
NiPoint3 finalPosition{};
|
|
int32_t count{};
|
|
bool bUsePosition{};
|
|
LWOOBJID lootID{ LWOOBJID_EMPTY };
|
|
LWOOBJID ownerID{ LWOOBJID_EMPTY };
|
|
};
|
|
using DropClientLootEvent = NetGameMsgEvent<DropClientLoot>;
|
|
|
|
struct PickupItem : public NetGameMsg {
|
|
PickupItem() : NetGameMsg(MessageType::Game::PICKUP_ITEM) {}
|
|
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
bool Deserialize(RakNet::BitStream& stream) override;
|
|
LWOOBJID lootID{};
|
|
LWOOBJID lootOwnerID{};
|
|
};
|
|
using PickupItemEvent = NetGameMsgEvent<PickupItem>;
|
|
|
|
struct TeamPickupItem : public NetGameMsg {
|
|
TeamPickupItem() : NetGameMsg(MessageType::Game::TEAM_PICKUP_ITEM) {}
|
|
|
|
void Serialize(RakNet::BitStream& stream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
LWOOBJID lootID{};
|
|
LWOOBJID lootOwnerID{};
|
|
};
|
|
};
|
|
|
|
#endif // INVENTORYMESSAGES_H
|