eq2go/internal/guilds/manager.go

909 lines
24 KiB
Go

package guilds
import (
"context"
"fmt"
"sort"
"strings"
"time"
)
// NewGuildList creates a new guild list instance
func NewGuildList() *GuildList {
return &GuildList{
guilds: make(map[int32]*Guild),
}
}
// AddGuild adds a guild to the list
func (gl *GuildList) AddGuild(guild *Guild) {
gl.mu.Lock()
defer gl.mu.Unlock()
gl.guilds[guild.GetID()] = guild
}
// GetGuild retrieves a guild by ID
func (gl *GuildList) GetGuild(guildID int32) *Guild {
gl.mu.RLock()
defer gl.mu.RUnlock()
return gl.guilds[guildID]
}
// RemoveGuild removes a guild from the list
func (gl *GuildList) RemoveGuild(guildID int32) {
gl.mu.Lock()
defer gl.mu.Unlock()
delete(gl.guilds, guildID)
}
// GetAllGuilds returns all guilds
func (gl *GuildList) GetAllGuilds() []*Guild {
gl.mu.RLock()
defer gl.mu.RUnlock()
guilds := make([]*Guild, 0, len(gl.guilds))
for _, guild := range gl.guilds {
guilds = append(guilds, guild)
}
return guilds
}
// GetGuildCount returns the number of guilds
func (gl *GuildList) GetGuildCount() int {
gl.mu.RLock()
defer gl.mu.RUnlock()
return len(gl.guilds)
}
// FindGuildByName finds a guild by name (case-insensitive)
func (gl *GuildList) FindGuildByName(name string) *Guild {
gl.mu.RLock()
defer gl.mu.RUnlock()
for _, guild := range gl.guilds {
if strings.EqualFold(guild.GetName(), name) {
return guild
}
}
return nil
}
// NewGuildManager creates a new guild manager instance
func NewGuildManager(database GuildDatabase, clientManager ClientManager, playerManager PlayerManager) *GuildManager {
return &GuildManager{
guildList: NewGuildList(),
database: database,
clientManager: clientManager,
playerManager: playerManager,
}
}
// SetEventHandler sets the guild event handler
func (gm *GuildManager) SetEventHandler(handler GuildEventHandler) {
gm.eventHandler = handler
}
// SetLogger sets the logger for the manager
func (gm *GuildManager) SetLogger(logger LogHandler) {
gm.logger = logger
}
// Initialize loads all guilds from the database
func (gm *GuildManager) Initialize(ctx context.Context) error {
// Load all guilds
guildData, err := gm.database.LoadGuilds(ctx)
if err != nil {
return fmt.Errorf("failed to load guilds: %w", err)
}
for _, data := range guildData {
guild, err := gm.loadGuildFromData(ctx, data)
if err != nil {
if gm.logger != nil {
gm.logger.LogError("guilds", "Failed to load guild %d (%s): %v", data.ID, data.Name, err)
}
continue
}
gm.guildList.AddGuild(guild)
if gm.logger != nil {
gm.logger.LogDebug("guilds", "Loaded guild %d (%s) with %d members",
guild.GetID(), guild.GetName(), len(guild.GetAllMembers()))
}
}
if gm.logger != nil {
gm.logger.LogInfo("guilds", "Loaded %d guilds", gm.guildList.GetGuildCount())
}
return nil
}
// LoadGuild loads a specific guild by ID
func (gm *GuildManager) LoadGuild(ctx context.Context, guildID int32) (*Guild, error) {
// Check if already loaded
if guild := gm.guildList.GetGuild(guildID); guild != nil {
return guild, nil
}
// Load from database
guildData, err := gm.database.LoadGuild(ctx, guildID)
if err != nil {
return nil, fmt.Errorf("failed to load guild data: %w", err)
}
guild, err := gm.loadGuildFromData(ctx, *guildData)
if err != nil {
return nil, fmt.Errorf("failed to create guild from data: %w", err)
}
gm.guildList.AddGuild(guild)
return guild, nil
}
// CreateGuild creates a new guild
func (gm *GuildManager) CreateGuild(ctx context.Context, name, motd string, leaderCharacterID int32) (*Guild, error) {
// Validate guild name
if err := gm.validateGuildName(name); err != nil {
return nil, err
}
// Check if guild name already exists
if gm.guildList.FindGuildByName(name) != nil {
return nil, fmt.Errorf("guild name '%s' already exists", name)
}
// Get leader player info
leaderInfo, err := gm.playerManager.GetPlayerInfo(leaderCharacterID)
if err != nil {
return nil, fmt.Errorf("failed to get leader info: %w", err)
}
// Create guild data
guildData := GuildData{
Name: name,
MOTD: motd,
Level: 1,
EXPCurrent: 111,
EXPToNextLevel: 2521,
FormedDate: time.Now(),
}
// Save to database
guildID, err := gm.database.CreateGuild(ctx, guildData)
if err != nil {
return nil, fmt.Errorf("failed to create guild in database: %w", err)
}
guildData.ID = guildID
// Create guild instance
guild := NewGuild()
guild.SetID(guildData.ID)
guild.SetName(guildData.Name, false)
guild.SetMOTD(guildData.MOTD, false)
guild.SetLevel(guildData.Level, false)
guild.SetEXPCurrent(guildData.EXPCurrent, false)
guild.SetEXPToNextLevel(guildData.EXPToNextLevel, false)
guild.SetFormedDate(guildData.FormedDate)
// Add leader as first member
leader := NewGuildMember(leaderCharacterID, leaderInfo.CharacterName, RankLeader)
leader.AccountID = leaderInfo.AccountID
leader.UpdatePlayerInfo(leaderInfo)
guild.members[leaderCharacterID] = leader
// Save member to database
if err := gm.database.SaveGuildMembers(ctx, guildID, []*GuildMember{leader}); err != nil {
return nil, fmt.Errorf("failed to save guild leader: %w", err)
}
// Add to guild list
gm.guildList.AddGuild(guild)
// Add guild creation event
guild.AddNewGuildEvent(EventGuildLevelUp, fmt.Sprintf("Guild '%s' has been formed by %s", name, leaderInfo.CharacterName), time.Now(), true)
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnGuildCreated(guild)
}
if gm.logger != nil {
gm.logger.LogInfo("guilds", "Created guild %d (%s) with leader %s (%d)",
guildID, name, leaderInfo.CharacterName, leaderCharacterID)
}
return guild, nil
}
// DeleteGuild deletes a guild
func (gm *GuildManager) DeleteGuild(ctx context.Context, guildID int32, deleterName string) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
guildName := guild.GetName()
// Remove from database
if err := gm.database.DeleteGuild(ctx, guildID); err != nil {
return fmt.Errorf("failed to delete guild from database: %w", err)
}
// Remove from guild list
gm.guildList.RemoveGuild(guildID)
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnGuildDeleted(guildID, guildName)
}
if gm.logger != nil {
gm.logger.LogInfo("guilds", "Deleted guild %d (%s) by %s", guildID, guildName, deleterName)
}
return nil
}
// GetGuild returns a guild by ID
func (gm *GuildManager) GetGuild(guildID int32) *Guild {
return gm.guildList.GetGuild(guildID)
}
// GetGuildByName returns a guild by name
func (gm *GuildManager) GetGuildByName(name string) *Guild {
return gm.guildList.FindGuildByName(name)
}
// GetAllGuilds returns all guilds
func (gm *GuildManager) GetAllGuilds() []*Guild {
return gm.guildList.GetAllGuilds()
}
// GetGuildByCharacterID returns the guild for a character
func (gm *GuildManager) GetGuildByCharacterID(ctx context.Context, characterID int32) (*Guild, error) {
// Try to find in loaded guilds first
for _, guild := range gm.guildList.GetAllGuilds() {
if guild.GetGuildMember(characterID) != nil {
return guild, nil
}
}
// Look up in database
guildID, err := gm.database.GetGuildIDByCharacterID(ctx, characterID)
if err != nil {
return nil, fmt.Errorf("character %d is not in a guild: %w", characterID, err)
}
// Load the guild if not already loaded
return gm.LoadGuild(ctx, guildID)
}
// InvitePlayer invites a player to a guild
func (gm *GuildManager) InvitePlayer(ctx context.Context, guildID, inviterID int32, playerName string, rank int8) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
// Validate inviter permissions
inviter := guild.GetGuildMember(inviterID)
if inviter == nil {
return fmt.Errorf("inviter %d is not a guild member", inviterID)
}
if guild.GetPermission(inviter.GetRank(), PermissionInvite) == 0 {
return fmt.Errorf("inviter does not have permission to invite")
}
// Validate target player
targetID, err := gm.playerManager.ValidatePlayerExists(playerName)
if err != nil {
return fmt.Errorf("player '%s' not found: %w", playerName, err)
}
// Check if player is already in a guild
if existingGuild, _ := gm.GetGuildByCharacterID(ctx, targetID); existingGuild != nil {
return fmt.Errorf("player '%s' is already in guild '%s'", playerName, existingGuild.GetName())
}
// TODO: Send guild invitation to player
// This would typically involve sending a packet to the client
if gm.logger != nil {
gm.logger.LogDebug("guilds", "Player %s invited to guild %s by %s",
playerName, guild.GetName(), inviter.GetName())
}
return nil
}
// AddMemberToGuild adds a member to a guild
func (gm *GuildManager) AddMemberToGuild(ctx context.Context, guildID, characterID int32, inviterName string, rank int8) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
// Check if already a member
if guild.GetGuildMember(characterID) != nil {
return fmt.Errorf("character %d is already a guild member", characterID)
}
// Get player info
playerInfo, err := gm.playerManager.GetPlayerInfo(characterID)
if err != nil {
return fmt.Errorf("failed to get player info: %w", err)
}
// Create guild member
member := NewGuildMember(characterID, playerInfo.CharacterName, rank)
member.AccountID = playerInfo.AccountID
member.UpdatePlayerInfo(playerInfo)
// Add to guild
guild.members[characterID] = member
guild.memberSaveNeeded = true
// Save to database
if err := gm.database.SaveGuildMembers(ctx, guildID, []*GuildMember{member}); err != nil {
return fmt.Errorf("failed to save new guild member: %w", err)
}
// Add guild event
guild.AddNewGuildEvent(EventMemberJoins,
fmt.Sprintf("%s has joined the guild (invited by %s)", playerInfo.CharacterName, inviterName),
time.Now(), true)
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnMemberJoined(guild, member, inviterName)
}
if gm.logger != nil {
gm.logger.LogInfo("guilds", "Player %s (%d) joined guild %s (%d)",
playerInfo.CharacterName, characterID, guild.GetName(), guildID)
}
return nil
}
// RemoveMemberFromGuild removes a member from a guild
func (gm *GuildManager) RemoveMemberFromGuild(ctx context.Context, guildID, characterID int32, removerName, reason string) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
member := guild.GetGuildMember(characterID)
if member == nil {
return fmt.Errorf("character %d is not a guild member", characterID)
}
memberName := member.GetName()
// Remove from guild
guild.RemoveGuildMember(characterID, true)
// Save changes
if err := gm.saveGuildChanges(ctx, guild); err != nil {
if gm.logger != nil {
gm.logger.LogError("guilds", "Failed to save guild after removing member: %v", err)
}
}
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnMemberLeft(guild, member, reason)
}
if gm.logger != nil {
gm.logger.LogInfo("guilds", "Player %s (%d) removed from guild %s (%d) by %s - %s",
memberName, characterID, guild.GetName(), guildID, removerName, reason)
}
return nil
}
// PromoteMember promotes a guild member
func (gm *GuildManager) PromoteMember(ctx context.Context, guildID, characterID int32, promoterName string) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
member := guild.GetGuildMember(characterID)
if member == nil {
return fmt.Errorf("character %d is not a guild member", characterID)
}
oldRank := member.GetRank()
if oldRank <= RankLeader {
return fmt.Errorf("cannot promote guild leader")
}
// Promote
if !guild.PromoteGuildMember(characterID, promoterName, true) {
return fmt.Errorf("failed to promote member")
}
// Save changes
if err := gm.saveGuildChanges(ctx, guild); err != nil {
if gm.logger != nil {
gm.logger.LogError("guilds", "Failed to save guild after promotion: %v", err)
}
}
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnMemberPromoted(guild, member, oldRank, member.GetRank(), promoterName)
}
return nil
}
// DemoteMember demotes a guild member
func (gm *GuildManager) DemoteMember(ctx context.Context, guildID, characterID int32, demoterName string) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
member := guild.GetGuildMember(characterID)
if member == nil {
return fmt.Errorf("character %d is not a guild member", characterID)
}
oldRank := member.GetRank()
if oldRank >= RankRecruit {
return fmt.Errorf("cannot demote recruit further")
}
// Demote
if !guild.DemoteGuildMember(characterID, demoterName, true) {
return fmt.Errorf("failed to demote member")
}
// Save changes
if err := gm.saveGuildChanges(ctx, guild); err != nil {
if gm.logger != nil {
gm.logger.LogError("guilds", "Failed to save guild after demotion: %v", err)
}
}
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnMemberDemoted(guild, member, oldRank, member.GetRank(), demoterName)
}
return nil
}
// AwardPoints awards points to guild members
func (gm *GuildManager) AwardPoints(ctx context.Context, guildID int32, characterIDs []int32, points float64, comment, awardedBy string) error {
guild := gm.guildList.GetGuild(guildID)
if guild == nil {
return fmt.Errorf("guild %d not found", guildID)
}
for _, characterID := range characterIDs {
if !guild.AddPointsToGuildMember(characterID, points, awardedBy, comment, true) {
if gm.logger != nil {
gm.logger.LogWarning("guilds", "Failed to award points to character %d", characterID)
}
}
}
// Save changes
if err := gm.saveGuildChanges(ctx, guild); err != nil {
if gm.logger != nil {
gm.logger.LogError("guilds", "Failed to save guild after awarding points: %v", err)
}
}
// Notify event handler
if gm.eventHandler != nil {
gm.eventHandler.OnPointsAwarded(guild, characterIDs, points, comment, awardedBy)
}
return nil
}
// SaveAllGuilds saves all guilds that need saving
func (gm *GuildManager) SaveAllGuilds(ctx context.Context) error {
guilds := gm.guildList.GetAllGuilds()
var saveErrors []error
for _, guild := range guilds {
if err := gm.saveGuildChanges(ctx, guild); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("guild %d: %w", guild.GetID(), err))
}
}
if len(saveErrors) > 0 {
return fmt.Errorf("failed to save some guilds: %v", saveErrors)
}
return nil
}
// SearchGuilds searches for guilds based on criteria
func (gm *GuildManager) SearchGuilds(criteria GuildSearchCriteria) []*Guild {
guilds := gm.guildList.GetAllGuilds()
var results []*Guild
for _, guild := range guilds {
if gm.matchesSearchCriteria(guild, criteria) {
results = append(results, guild)
}
}
// Sort by name
sort.Slice(results, func(i, j int) bool {
return results[i].GetName() < results[j].GetName()
})
return results
}
// GetGuildStatistics returns guild system statistics
func (gm *GuildManager) GetGuildStatistics() GuildStatistics {
guilds := gm.guildList.GetAllGuilds()
stats := GuildStatistics{
TotalGuilds: len(guilds),
}
totalMembers := 0
activeGuilds := 0
totalEvents := 0
totalRecruiters := 0
uniqueAccounts := make(map[int32]bool)
highestLevel := int8(1)
for _, guild := range guilds {
members := guild.GetAllMembers()
memberCount := len(members)
totalMembers += memberCount
if memberCount > 0 {
activeGuilds++
}
// Track unique accounts
for _, member := range members {
uniqueAccounts[member.AccountID] = true
if member.IsRecruiter() {
totalRecruiters++
}
}
// Guild level
if guild.GetLevel() > highestLevel {
highestLevel = guild.GetLevel()
}
// Event count (approximate)
totalEvents += len(guild.guildEvents)
}
stats.TotalMembers = totalMembers
stats.ActiveGuilds = activeGuilds
stats.TotalEvents = totalEvents
stats.TotalRecruiters = totalRecruiters
stats.UniqueAccounts = len(uniqueAccounts)
stats.HighestGuildLevel = highestLevel
if len(guilds) > 0 {
stats.AverageGuildSize = float64(totalMembers) / float64(len(guilds))
}
return stats
}
// Helper methods
// loadGuildFromData creates a guild instance from database data
func (gm *GuildManager) loadGuildFromData(ctx context.Context, data GuildData) (*Guild, error) {
guild := NewGuild()
guild.SetID(data.ID)
guild.SetName(data.Name, false)
guild.SetMOTD(data.MOTD, false)
guild.SetLevel(data.Level, false)
guild.SetEXPCurrent(data.EXPCurrent, false)
guild.SetEXPToNextLevel(data.EXPToNextLevel, false)
guild.SetFormedDate(data.FormedDate)
// Load members
memberData, err := gm.database.LoadGuildMembers(ctx, data.ID)
if err != nil {
return nil, fmt.Errorf("failed to load guild members: %w", err)
}
for _, md := range memberData {
member := &GuildMember{
CharacterID: md.CharacterID,
AccountID: md.AccountID,
RecruiterID: md.RecruiterID,
Name: md.Name,
GuildStatus: md.GuildStatus,
Points: md.Points,
AdventureClass: md.AdventureClass,
AdventureLevel: md.AdventureLevel,
TradeskillClass: md.TradeskillClass,
TradeskillLevel: md.TradeskillLevel,
Rank: md.Rank,
MemberFlags: md.MemberFlags,
Zone: md.Zone,
JoinDate: md.JoinDate,
LastLoginDate: md.LastLoginDate,
Note: md.Note,
OfficerNote: md.OfficerNote,
RecruiterDescription: md.RecruiterDescription,
RecruiterPictureData: md.RecruiterPictureData,
RecruitingShowAdventureClass: md.RecruitingShowAdventureClass,
PointHistory: make([]PointHistory, 0),
}
// Load point history
historyData, err := gm.database.LoadPointHistory(ctx, md.CharacterID)
if err == nil {
for _, hd := range historyData {
member.PointHistory = append(member.PointHistory, PointHistory{
Date: hd.Date,
ModifiedBy: hd.ModifiedBy,
Comment: hd.Comment,
Points: hd.Points,
SaveNeeded: false,
})
}
}
guild.members[md.CharacterID] = member
}
// Load events
eventData, err := gm.database.LoadGuildEvents(ctx, data.ID)
if err == nil {
for _, ed := range eventData {
guild.guildEvents = append(guild.guildEvents, GuildEvent{
EventID: ed.EventID,
Date: ed.Date,
Type: ed.Type,
Description: ed.Description,
Locked: ed.Locked,
SaveNeeded: false,
})
}
}
// Load ranks
rankData, err := gm.database.LoadGuildRanks(ctx, data.ID)
if err == nil {
for _, rd := range rankData {
guild.ranks[rd.Rank] = rd.Name
}
}
// Load permissions
permissionData, err := gm.database.LoadGuildPermissions(ctx, data.ID)
if err == nil {
for _, pd := range permissionData {
if guild.permissions[pd.Rank] == nil {
guild.permissions[pd.Rank] = make(map[int8]int8)
}
guild.permissions[pd.Rank][pd.Permission] = pd.Value
}
}
// Load event filters
filterData, err := gm.database.LoadGuildEventFilters(ctx, data.ID)
if err == nil {
for _, fd := range filterData {
if guild.eventFilters[fd.EventID] == nil {
guild.eventFilters[fd.EventID] = make(map[int8]int8)
}
guild.eventFilters[fd.EventID][fd.Category] = fd.Value
}
}
// Load recruiting settings
recruitingData, err := gm.database.LoadGuildRecruiting(ctx, data.ID)
if err == nil {
for _, rd := range recruitingData {
if rd.Flag < 0 {
// Description tag (stored with negative flag values)
guild.recruitingDescTags[-rd.Flag-1] = rd.Value
} else {
// Recruiting flag
guild.recruitingFlags[rd.Flag] = rd.Value
}
}
}
// Update next event ID
if len(guild.guildEvents) > 0 {
maxEventID := int64(0)
for _, event := range guild.guildEvents {
if event.EventID > maxEventID {
maxEventID = event.EventID
}
}
guild.nextEventID = maxEventID + 1
}
// Clear save flags
guild.saveNeeded = false
guild.memberSaveNeeded = false
guild.eventsSaveNeeded = false
guild.ranksSaveNeeded = false
guild.eventFiltersSaveNeeded = false
guild.pointsHistorySaveNeeded = false
guild.recruitingSaveNeeded = false
return guild, nil
}
// saveGuildChanges saves any pending changes for a guild
func (gm *GuildManager) saveGuildChanges(ctx context.Context, guild *Guild) error {
var saveErrors []error
if guild.GetSaveNeeded() {
if err := gm.database.SaveGuild(ctx, guild); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild data: %w", err))
} else {
guild.SetSaveNeeded(false)
}
}
if guild.memberSaveNeeded {
members := guild.GetAllMembers()
if err := gm.database.SaveGuildMembers(ctx, guild.GetID(), members); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild members: %w", err))
} else {
guild.memberSaveNeeded = false
}
}
if guild.eventsSaveNeeded {
if err := gm.database.SaveGuildEvents(ctx, guild.GetID(), guild.guildEvents); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild events: %w", err))
} else {
guild.eventsSaveNeeded = false
}
}
if guild.ranksSaveNeeded {
if err := gm.database.SaveGuildRanks(ctx, guild.GetID(), guild.ranks); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild ranks: %w", err))
} else {
guild.ranksSaveNeeded = false
}
}
if guild.eventFiltersSaveNeeded {
if err := gm.database.SaveGuildEventFilters(ctx, guild.GetID(), guild.eventFilters); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild event filters: %w", err))
} else {
guild.eventFiltersSaveNeeded = false
}
}
if guild.recruitingSaveNeeded {
if err := gm.database.SaveGuildRecruiting(ctx, guild.GetID(), guild.recruitingFlags, guild.recruitingDescTags); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save guild recruiting: %w", err))
} else {
guild.recruitingSaveNeeded = false
}
}
if guild.pointsHistorySaveNeeded {
for _, member := range guild.GetAllMembers() {
if err := gm.database.SavePointHistory(ctx, member.GetCharacterID(), member.GetPointHistory()); err != nil {
saveErrors = append(saveErrors, fmt.Errorf("failed to save point history for %d: %w", member.GetCharacterID(), err))
}
}
guild.pointsHistorySaveNeeded = false
}
if len(saveErrors) > 0 {
return fmt.Errorf("save errors: %v", saveErrors)
}
return nil
}
// validateGuildName validates a guild name
func (gm *GuildManager) validateGuildName(name string) error {
if len(strings.TrimSpace(name)) == 0 {
return fmt.Errorf("guild name cannot be empty")
}
if len(name) > MaxGuildNameLength {
return fmt.Errorf("guild name too long: %d > %d", len(name), MaxGuildNameLength)
}
// Check for invalid characters
if strings.ContainsAny(name, "<>&\"'") {
return fmt.Errorf("guild name contains invalid characters")
}
return nil
}
// matchesSearchCriteria checks if a guild matches search criteria
func (gm *GuildManager) matchesSearchCriteria(guild *Guild, criteria GuildSearchCriteria) bool {
// Name pattern matching
if criteria.NamePattern != "" {
if !strings.Contains(strings.ToLower(guild.GetName()), strings.ToLower(criteria.NamePattern)) {
return false
}
}
// Level range
level := guild.GetLevel()
if criteria.MinLevel > 0 && level < criteria.MinLevel {
return false
}
if criteria.MaxLevel > 0 && level > criteria.MaxLevel {
return false
}
// Member count range
memberCount := len(guild.GetAllMembers())
if criteria.MinMembers > 0 && memberCount < criteria.MinMembers {
return false
}
if criteria.MaxMembers > 0 && memberCount > criteria.MaxMembers {
return false
}
// Recruiting only
if criteria.RecruitingOnly && guild.GetNumRecruiters() == 0 {
return false
}
// Play style
if criteria.PlayStyle > 0 && guild.GetRecruitingPlayStyle() != criteria.PlayStyle {
return false
}
// Required flags
for _, flag := range criteria.RequiredFlags {
if guild.GetRecruitingFlag(flag) == 0 {
return false
}
}
// Required description tags
for _, tag := range criteria.RequiredDescTags {
found := false
for i := int8(0); i < 4; i++ {
if guild.GetRecruitingDescTag(i) == tag {
found = true
break
}
}
if !found {
return false
}
}
// Excluded description tags
for _, tag := range criteria.ExcludedDescTags {
for i := int8(0); i < 4; i++ {
if guild.GetRecruitingDescTag(i) == tag {
return false
}
}
}
return true
}