491 lines
12 KiB
Go
491 lines
12 KiB
Go
package guilds
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// NewGuildMember creates a new guild member instance
|
|
func NewGuildMember(characterID int32, name string, rank int8) *GuildMember {
|
|
return &GuildMember{
|
|
CharacterID: characterID,
|
|
Name: name,
|
|
Rank: rank,
|
|
JoinDate: time.Now(),
|
|
LastLoginDate: time.Now(),
|
|
PointHistory: make([]PointHistory, 0),
|
|
RecruitingShowAdventureClass: 1,
|
|
}
|
|
}
|
|
|
|
// GetCharacterID returns the character ID
|
|
func (gm *GuildMember) GetCharacterID() int32 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.CharacterID
|
|
}
|
|
|
|
// GetName returns the member name
|
|
func (gm *GuildMember) GetName() string {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Name
|
|
}
|
|
|
|
// SetName sets the member name
|
|
func (gm *GuildMember) SetName(name string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
if len(name) > MaxMemberNameLength {
|
|
name = name[:MaxMemberNameLength]
|
|
}
|
|
gm.Name = name
|
|
}
|
|
|
|
// GetRank returns the member rank
|
|
func (gm *GuildMember) GetRank() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Rank
|
|
}
|
|
|
|
// SetRank sets the member rank
|
|
func (gm *GuildMember) SetRank(rank int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
if rank >= RankLeader && rank <= RankRecruit {
|
|
gm.Rank = rank
|
|
}
|
|
}
|
|
|
|
// GetPoints returns the member's guild points
|
|
func (gm *GuildMember) GetPoints() float64 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Points
|
|
}
|
|
|
|
// SetPoints sets the member's guild points
|
|
func (gm *GuildMember) SetPoints(points float64) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.Points = points
|
|
}
|
|
|
|
// AddPoints adds points to the member
|
|
func (gm *GuildMember) AddPoints(points float64) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.Points += points
|
|
}
|
|
|
|
// GetAdventureLevel returns the adventure level
|
|
func (gm *GuildMember) GetAdventureLevel() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.AdventureLevel
|
|
}
|
|
|
|
// SetAdventureLevel sets the adventure level
|
|
func (gm *GuildMember) SetAdventureLevel(level int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.AdventureLevel = level
|
|
}
|
|
|
|
// GetAdventureClass returns the adventure class
|
|
func (gm *GuildMember) GetAdventureClass() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.AdventureClass
|
|
}
|
|
|
|
// SetAdventureClass sets the adventure class
|
|
func (gm *GuildMember) SetAdventureClass(class int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.AdventureClass = class
|
|
}
|
|
|
|
// GetTradeskillLevel returns the tradeskill level
|
|
func (gm *GuildMember) GetTradeskillLevel() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.TradeskillLevel
|
|
}
|
|
|
|
// SetTradeskillLevel sets the tradeskill level
|
|
func (gm *GuildMember) SetTradeskillLevel(level int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.TradeskillLevel = level
|
|
}
|
|
|
|
// GetTradeskillClass returns the tradeskill class
|
|
func (gm *GuildMember) GetTradeskillClass() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.TradeskillClass
|
|
}
|
|
|
|
// SetTradeskillClass sets the tradeskill class
|
|
func (gm *GuildMember) SetTradeskillClass(class int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.TradeskillClass = class
|
|
}
|
|
|
|
// GetZone returns the member's current zone
|
|
func (gm *GuildMember) GetZone() string {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Zone
|
|
}
|
|
|
|
// SetZone sets the member's current zone
|
|
func (gm *GuildMember) SetZone(zone string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.Zone = zone
|
|
}
|
|
|
|
// GetJoinDate returns when the member joined the guild
|
|
func (gm *GuildMember) GetJoinDate() time.Time {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.JoinDate
|
|
}
|
|
|
|
// SetJoinDate sets when the member joined the guild
|
|
func (gm *GuildMember) SetJoinDate(date time.Time) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.JoinDate = date
|
|
}
|
|
|
|
// GetLastLoginDate returns the member's last login date
|
|
func (gm *GuildMember) GetLastLoginDate() time.Time {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.LastLoginDate
|
|
}
|
|
|
|
// SetLastLoginDate sets the member's last login date
|
|
func (gm *GuildMember) SetLastLoginDate(date time.Time) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.LastLoginDate = date
|
|
}
|
|
|
|
// GetNote returns the member's personal note
|
|
func (gm *GuildMember) GetNote() string {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Note
|
|
}
|
|
|
|
// SetNote sets the member's personal note
|
|
func (gm *GuildMember) SetNote(note string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.Note = note
|
|
}
|
|
|
|
// GetOfficerNote returns the member's officer note
|
|
func (gm *GuildMember) GetOfficerNote() string {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.OfficerNote
|
|
}
|
|
|
|
// SetOfficerNote sets the member's officer note
|
|
func (gm *GuildMember) SetOfficerNote(note string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.OfficerNote = note
|
|
}
|
|
|
|
// GetMemberFlags returns the member flags
|
|
func (gm *GuildMember) GetMemberFlags() int8 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.MemberFlags
|
|
}
|
|
|
|
// SetMemberFlags sets the member flags
|
|
func (gm *GuildMember) SetMemberFlags(flags int8) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.MemberFlags = flags
|
|
}
|
|
|
|
// HasMemberFlag checks if the member has a specific flag
|
|
func (gm *GuildMember) HasMemberFlag(flag int8) bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.MemberFlags&flag != 0
|
|
}
|
|
|
|
// SetMemberFlag sets or unsets a specific member flag
|
|
func (gm *GuildMember) SetMemberFlag(flag int8, value bool) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
|
|
if value {
|
|
gm.MemberFlags |= flag
|
|
} else {
|
|
gm.MemberFlags &^= flag
|
|
}
|
|
}
|
|
|
|
// IsRecruiter checks if the member is a recruiter
|
|
func (gm *GuildMember) IsRecruiter() bool {
|
|
return gm.HasMemberFlag(MemberFlagRecruitingForGuild)
|
|
}
|
|
|
|
// SetRecruiter sets or unsets the recruiter flag
|
|
func (gm *GuildMember) SetRecruiter(isRecruiter bool) {
|
|
gm.SetMemberFlag(MemberFlagRecruitingForGuild, isRecruiter)
|
|
}
|
|
|
|
// GetRecruiterID returns the recruiter ID
|
|
func (gm *GuildMember) GetRecruiterID() int32 {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.RecruiterID
|
|
}
|
|
|
|
// SetRecruiterID sets the recruiter ID
|
|
func (gm *GuildMember) SetRecruiterID(id int32) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.RecruiterID = id
|
|
}
|
|
|
|
// GetRecruiterDescription returns the recruiter description
|
|
func (gm *GuildMember) GetRecruiterDescription() string {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.RecruiterDescription
|
|
}
|
|
|
|
// SetRecruiterDescription sets the recruiter description
|
|
func (gm *GuildMember) SetRecruiterDescription(description string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
gm.RecruiterDescription = description
|
|
}
|
|
|
|
// GetRecruiterPictureData returns the recruiter picture data
|
|
func (gm *GuildMember) GetRecruiterPictureData() []byte {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
// Return a copy to prevent external modification
|
|
if gm.RecruiterPictureData == nil {
|
|
return nil
|
|
}
|
|
|
|
data := make([]byte, len(gm.RecruiterPictureData))
|
|
copy(data, gm.RecruiterPictureData)
|
|
return data
|
|
}
|
|
|
|
// SetRecruiterPictureData sets the recruiter picture data
|
|
func (gm *GuildMember) SetRecruiterPictureData(data []byte) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
|
|
if data == nil {
|
|
gm.RecruiterPictureData = nil
|
|
return
|
|
}
|
|
|
|
// Make a copy to prevent external modification
|
|
gm.RecruiterPictureData = make([]byte, len(data))
|
|
copy(gm.RecruiterPictureData, data)
|
|
}
|
|
|
|
// GetRecruitingShowAdventureClass returns whether to show adventure class
|
|
func (gm *GuildMember) GetRecruitingShowAdventureClass() bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.RecruitingShowAdventureClass != 0
|
|
}
|
|
|
|
// SetRecruitingShowAdventureClass sets whether to show adventure class
|
|
func (gm *GuildMember) SetRecruitingShowAdventureClass(show bool) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
|
|
if show {
|
|
gm.RecruitingShowAdventureClass = 1
|
|
} else {
|
|
gm.RecruitingShowAdventureClass = 0
|
|
}
|
|
}
|
|
|
|
// GetPointHistory returns a copy of the point history
|
|
func (gm *GuildMember) GetPointHistory() []PointHistory {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
history := make([]PointHistory, len(gm.PointHistory))
|
|
copy(history, gm.PointHistory)
|
|
return history
|
|
}
|
|
|
|
// AddPointHistory adds a point history entry
|
|
func (gm *GuildMember) AddPointHistory(date time.Time, modifiedBy string, points float64, comment string) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
|
|
// Limit history size
|
|
if len(gm.PointHistory) >= MaxPointHistory {
|
|
// Remove oldest entry
|
|
gm.PointHistory = gm.PointHistory[1:]
|
|
}
|
|
|
|
history := PointHistory{
|
|
Date: date,
|
|
ModifiedBy: modifiedBy,
|
|
Points: points,
|
|
Comment: comment,
|
|
SaveNeeded: true,
|
|
}
|
|
|
|
gm.PointHistory = append(gm.PointHistory, history)
|
|
}
|
|
|
|
// GetMemberInfo returns formatted member information
|
|
func (gm *GuildMember) GetMemberInfo(rankName string, isOnline bool) MemberInfo {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
return MemberInfo{
|
|
CharacterID: gm.CharacterID,
|
|
Name: gm.Name,
|
|
Rank: gm.Rank,
|
|
RankName: rankName,
|
|
Points: gm.Points,
|
|
AdventureClass: gm.AdventureClass,
|
|
AdventureLevel: gm.AdventureLevel,
|
|
TradeskillClass: gm.TradeskillClass,
|
|
TradeskillLevel: gm.TradeskillLevel,
|
|
Zone: gm.Zone,
|
|
JoinDate: gm.JoinDate,
|
|
LastLoginDate: gm.LastLoginDate,
|
|
IsOnline: isOnline,
|
|
IsRecruiter: gm.MemberFlags&MemberFlagRecruitingForGuild != 0,
|
|
Note: gm.Note,
|
|
OfficerNote: gm.OfficerNote,
|
|
}
|
|
}
|
|
|
|
// GetRecruiterInfo returns formatted recruiter information
|
|
func (gm *GuildMember) GetRecruiterInfo(isOnline bool) RecruiterInfo {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
return RecruiterInfo{
|
|
CharacterID: gm.CharacterID,
|
|
Name: gm.Name,
|
|
Description: gm.RecruiterDescription,
|
|
PictureData: gm.GetRecruiterPictureData(), // This will make a copy
|
|
ShowAdventureClass: gm.RecruitingShowAdventureClass != 0,
|
|
AdventureClass: gm.AdventureClass,
|
|
IsOnline: isOnline,
|
|
}
|
|
}
|
|
|
|
// UpdatePlayerInfo updates member info from player data
|
|
func (gm *GuildMember) UpdatePlayerInfo(playerInfo PlayerInfo) {
|
|
gm.mu.Lock()
|
|
defer gm.mu.Unlock()
|
|
|
|
gm.AdventureLevel = playerInfo.AdventureLevel
|
|
gm.AdventureClass = playerInfo.AdventureClass
|
|
gm.TradeskillLevel = playerInfo.TradeskillLevel
|
|
gm.TradeskillClass = playerInfo.TradeskillClass
|
|
gm.Zone = playerInfo.Zone
|
|
|
|
if playerInfo.IsOnline {
|
|
gm.LastLoginDate = time.Now()
|
|
}
|
|
}
|
|
|
|
// ValidateRank checks if the rank is valid
|
|
func (gm *GuildMember) ValidateRank() bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
return gm.Rank >= RankLeader && gm.Rank <= RankRecruit
|
|
}
|
|
|
|
// CanPromote checks if this member can promote another member
|
|
func (gm *GuildMember) CanPromote(targetRank int8) bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
// Can only promote members with lower rank (higher rank number)
|
|
// Cannot promote to same or higher rank than self
|
|
return gm.Rank < targetRank && targetRank > RankLeader
|
|
}
|
|
|
|
// CanDemote checks if this member can demote another member
|
|
func (gm *GuildMember) CanDemote(targetRank int8) bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
// Can only demote members with equal or lower rank (same or higher rank number)
|
|
// Cannot demote to recruit (already lowest)
|
|
return gm.Rank <= targetRank && targetRank < RankRecruit
|
|
}
|
|
|
|
// CanKick checks if this member can kick another member
|
|
func (gm *GuildMember) CanKick(targetRank int8) bool {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
// Can only kick members with lower rank (higher rank number)
|
|
return gm.Rank < targetRank
|
|
}
|
|
|
|
// Copy creates a deep copy of the guild member
|
|
func (gm *GuildMember) Copy() *GuildMember {
|
|
gm.mu.RLock()
|
|
defer gm.mu.RUnlock()
|
|
|
|
newMember := &GuildMember{
|
|
CharacterID: gm.CharacterID,
|
|
AccountID: gm.AccountID,
|
|
RecruiterID: gm.RecruiterID,
|
|
Name: gm.Name,
|
|
GuildStatus: gm.GuildStatus,
|
|
Points: gm.Points,
|
|
AdventureClass: gm.AdventureClass,
|
|
AdventureLevel: gm.AdventureLevel,
|
|
TradeskillClass: gm.TradeskillClass,
|
|
TradeskillLevel: gm.TradeskillLevel,
|
|
Rank: gm.Rank,
|
|
MemberFlags: gm.MemberFlags,
|
|
Zone: gm.Zone,
|
|
JoinDate: gm.JoinDate,
|
|
LastLoginDate: gm.LastLoginDate,
|
|
Note: gm.Note,
|
|
OfficerNote: gm.OfficerNote,
|
|
RecruiterDescription: gm.RecruiterDescription,
|
|
RecruitingShowAdventureClass: gm.RecruitingShowAdventureClass,
|
|
PointHistory: make([]PointHistory, len(gm.PointHistory)),
|
|
}
|
|
|
|
// Deep copy point history
|
|
copy(newMember.PointHistory, gm.PointHistory)
|
|
|
|
// Deep copy picture data
|
|
if gm.RecruiterPictureData != nil {
|
|
newMember.RecruiterPictureData = make([]byte, len(gm.RecruiterPictureData))
|
|
copy(newMember.RecruiterPictureData, gm.RecruiterPictureData)
|
|
}
|
|
|
|
return newMember
|
|
}
|