189 lines
5.0 KiB
Go
189 lines
5.0 KiB
Go
package trade
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// TradeItemInfo represents an item in a trade slot
|
|
// Converted from C++ TradeItemInfo struct
|
|
type TradeItemInfo struct {
|
|
Item *Item // TODO: Replace with actual Item type when available
|
|
Quantity int32 // Quantity of the item being traded
|
|
}
|
|
|
|
// CoinAmounts represents the breakdown of coins in EQ2 currency
|
|
type CoinAmounts struct {
|
|
Platinum int32 // Platinum coins
|
|
Gold int32 // Gold coins
|
|
Silver int32 // Silver coins
|
|
Copper int32 // Copper coins (base unit)
|
|
}
|
|
|
|
// TradeState represents the current state of a trade
|
|
type TradeState int32
|
|
|
|
const (
|
|
TradeStateActive TradeState = 0 // Trade is active and ongoing
|
|
TradeStateAccepted TradeState = 1 // Trade has been accepted by both parties
|
|
TradeStateCanceled TradeState = 2 // Trade was canceled
|
|
TradeStateCompleted TradeState = 3 // Trade was completed successfully
|
|
)
|
|
|
|
// TradeValidationError represents validation errors during trade operations
|
|
type TradeValidationError struct {
|
|
Code int32 // Error code from trade constants
|
|
Message string // Human readable error message
|
|
}
|
|
|
|
// Error implements the error interface
|
|
func (e *TradeValidationError) Error() string {
|
|
return e.Message
|
|
}
|
|
|
|
// TradeParticipant represents one side of a trade
|
|
type TradeParticipant struct {
|
|
EntityID int32 // Entity ID of the participant
|
|
Items map[int8]TradeItemInfo // Items being traded by slot
|
|
Coins int64 // Total coins being offered (in copper)
|
|
HasAccepted bool // Whether participant has accepted the trade
|
|
MaxSlots int8 // Maximum trade slots for this participant
|
|
IsBot bool // Whether this participant is a bot
|
|
ClientVersion int32 // Client version (affects slot count)
|
|
}
|
|
|
|
// NewTradeParticipant creates a new trade participant
|
|
func NewTradeParticipant(entityID int32, isBot bool, clientVersion int32) *TradeParticipant {
|
|
maxSlots := TradeMaxSlotsDefault
|
|
if clientVersion <= 561 {
|
|
maxSlots = TradeMaxSlotsLegacy
|
|
}
|
|
|
|
return &TradeParticipant{
|
|
EntityID: entityID,
|
|
Items: make(map[int8]TradeItemInfo),
|
|
Coins: 0,
|
|
HasAccepted: false,
|
|
MaxSlots: int8(maxSlots),
|
|
IsBot: isBot,
|
|
ClientVersion: clientVersion,
|
|
}
|
|
}
|
|
|
|
// GetNextFreeSlot finds the next available slot for items
|
|
func (tp *TradeParticipant) GetNextFreeSlot() int8 {
|
|
for slot := int8(0); slot < tp.MaxSlots; slot++ {
|
|
if _, exists := tp.Items[slot]; !exists {
|
|
return slot
|
|
}
|
|
}
|
|
return TradeSlotAutoFind // No free slots available
|
|
}
|
|
|
|
// HasItem checks if participant has a specific item in trade
|
|
func (tp *TradeParticipant) HasItem(itemID int32) bool {
|
|
for _, itemInfo := range tp.Items {
|
|
if itemInfo.Item != nil && itemInfo.Item.GetID() == itemID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetItemCount returns the total number of items in trade
|
|
func (tp *TradeParticipant) GetItemCount() int {
|
|
return len(tp.Items)
|
|
}
|
|
|
|
// ClearItems removes all items from the trade
|
|
func (tp *TradeParticipant) ClearItems() {
|
|
tp.Items = make(map[int8]TradeItemInfo)
|
|
}
|
|
|
|
// GetCoinAmounts converts total copper to coin denominations
|
|
func (tp *TradeParticipant) GetCoinAmounts() CoinAmounts {
|
|
return CalculateCoins(tp.Coins)
|
|
}
|
|
|
|
// Item represents a placeholder item interface
|
|
// TODO: Replace with actual Item implementation when available
|
|
type Item interface {
|
|
GetID() int32
|
|
GetName() string
|
|
GetQuantity() int32
|
|
GetIcon(version int32) int32
|
|
IsNoTrade() bool
|
|
IsHeirloom() bool
|
|
IsAttuned() bool
|
|
GetCreationTime() time.Time
|
|
GetGroupCharacterIDs() []int32
|
|
}
|
|
|
|
// Entity represents a placeholder entity interface
|
|
// TODO: Replace with actual Entity implementation when available
|
|
type Entity interface {
|
|
GetID() int32
|
|
GetName() string
|
|
IsPlayer() bool
|
|
IsBot() bool
|
|
HasCoins(amount int64) bool
|
|
GetClientVersion() int32
|
|
}
|
|
|
|
// TradeManager handles multiple active trades
|
|
type TradeManager struct {
|
|
trades map[int32]*Trade // Active trades by trader1 ID
|
|
mutex sync.RWMutex // Thread safety
|
|
}
|
|
|
|
// NewTradeManager creates a new trade manager
|
|
func NewTradeManager() *TradeManager {
|
|
return &TradeManager{
|
|
trades: make(map[int32]*Trade),
|
|
}
|
|
}
|
|
|
|
// GetTrade retrieves an active trade for an entity
|
|
func (tm *TradeManager) GetTrade(entityID int32) *Trade {
|
|
tm.mutex.RLock()
|
|
defer tm.mutex.RUnlock()
|
|
|
|
// Check if entity is trader1
|
|
if trade, exists := tm.trades[entityID]; exists {
|
|
return trade
|
|
}
|
|
|
|
// Check if entity is trader2
|
|
for _, trade := range tm.trades {
|
|
if trade.GetTrader2ID() == entityID {
|
|
return trade
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddTrade adds a new trade to management
|
|
func (tm *TradeManager) AddTrade(trade *Trade) {
|
|
tm.mutex.Lock()
|
|
defer tm.mutex.Unlock()
|
|
|
|
tm.trades[trade.GetTrader1ID()] = trade
|
|
}
|
|
|
|
// RemoveTrade removes a trade from management
|
|
func (tm *TradeManager) RemoveTrade(trader1ID int32) {
|
|
tm.mutex.Lock()
|
|
defer tm.mutex.Unlock()
|
|
|
|
delete(tm.trades, trader1ID)
|
|
}
|
|
|
|
// GetActiveTradeCount returns the number of active trades
|
|
func (tm *TradeManager) GetActiveTradeCount() int {
|
|
tm.mutex.RLock()
|
|
defer tm.mutex.RUnlock()
|
|
|
|
return len(tm.trades)
|
|
}
|