Files
DarkflameServer/dGame/dComponents/VendorComponent.h
Aaron Kimbrell 2711c69e3e refactor: vendor, donation and trade game messages as structs
Converts the vendor, donation vendor and trade game messages to
NetGameMsgs in VendorMessages.{h,cpp} and TradeMessages.{h,cpp}:
VendorOpenWindow and VendorTransactionResult (SendToClient: the old
functions never broadcast), VendorStatusUpdate, ServerTradeInvite,
ServerTradeInitialReply, ServerTradeFinalReply, ServerTradeAccept,
ServerTradeCancel and ServerTradeUpdate, and the received
RequestVendorStatusUpdate, BuyFromVendor, SellToVendor,
BuybackFromVendor, AddDonationItem, RemoveDonationItem,
ConfirmDonationOnPlayer, CancelDonationOnPlayer, ClientTradeRequest,
ClientTradeCancel, ClientTradeAccept and ClientTradeUpdate. A trade
offer entry (the client's inventory item layout, optional fields and
config block included) is TradeItemEntry, shared by both trade updates.

Selling and buying back move into VendorComponent (SellToVendor,
BuybackFromVendor), adding and confirming donations into
DonationVendorComponent, and VendorComponent builds its own status
update and transaction results. Only the VENDOR component sends its
stock, as before. The received messages are registered in
GameMessageHandler's map, the switch cases and the old functions are
deleted. Handler logic is unchanged.

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 (every optional field of a trade entry,
raw and compressed config blocks) and truncated payloads rejected, hand
computed golden bytes, round trips, and a deliberate width mutation made
the tests fail. ConfirmDonationOnPlayer still accepts a message without
its vendor ID, since the old handler read nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:53 -05:00

78 lines
2.6 KiB
C++

#pragma once
#ifndef VENDORCOMPONENT_H
#define VENDORCOMPONENT_H
#include "CDClientManager.h"
#include "Component.h"
#include "Entity.h"
#include "GameMessages.h"
#include "RakNetTypes.h"
#include "eReplicaComponentType.h"
enum class eVendorTransactionResult : uint32_t;
struct SoldItem {
SoldItem(const LOT lot, const int32_t sortPriority) {
this->lot = lot;
this->sortPriority = sortPriority;
};
LOT lot = 0;
int32_t sortPriority = 0;
};
class VendorComponent : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR;
VendorComponent(Entity* parent, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void OnUse(Entity* originator) override;
virtual void RefreshInventory(bool isCreation = false);
void SetupConstants();
bool SellsItem(const LOT item) const;
float GetBuyScalar() const { return m_BuyScalar; }
float GetSellScalar() const { return m_SellScalar; }
void SetBuyScalar(const float value) { m_BuyScalar = value; }
void SetSellScalar(const float value) { m_SellScalar = value; }
const std::vector<SoldItem>& GetInventory() { return m_Inventory; }
void SetHasMultiCostItems(const bool hasMultiCostItems) {
if (m_HasMultiCostItems == hasMultiCostItems) return;
m_HasMultiCostItems = hasMultiCostItems;
m_DirtyVendor = true;
}
void SetHasStandardCostItems(const bool hasStandardCostItems) {
if (m_HasStandardCostItems == hasStandardCostItems) return;
m_HasStandardCostItems = hasStandardCostItems;
m_DirtyVendor = true;
}
void Buy(Entity* buyer, LOT lot, uint32_t count);
// SellToVendor / BuybackFromVendor from player (sent from sysAddr), for the item with object ID itemObjID.
void SellToVendor(Entity& player, const SystemAddress& sysAddr, LWOOBJID itemObjID, int32_t count);
void BuybackFromVendor(Entity& player, const SystemAddress& sysAddr, LWOOBJID itemObjID, int32_t count);
// Sends this vendor's stock (VendorStatusUpdate) to sysAddr; UNASSIGNED_SYSTEM_ADDRESS broadcasts.
void SendStatusUpdate(const SystemAddress& sysAddr, bool bUpdateOnly = false);
// Sends a VendorTransactionResult targeting target to sysAddr only.
static void SendTransactionResult(LWOOBJID target, const SystemAddress& sysAddr, eVendorTransactionResult result);
private:
void HandleMrReeCameras();
bool SetupItem(LOT item);
float m_BuyScalar = 0.0f;
float m_SellScalar = 0.0f;
float m_RefreshTimeSeconds = 0.0f;
uint32_t m_LootMatrixID = 0;
std::vector<SoldItem> m_Inventory;
bool m_DirtyVendor = false;
bool m_HasStandardCostItems = false;
bool m_HasMultiCostItems = false;
};
#endif // VENDORCOMPONENT_H