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 }