eq2go/internal/groups/manager_methods.go

517 lines
12 KiB
Go

package groups
import (
"fmt"
"time"
)
// Group utility methods
// GetGroupSize returns the size of a group
func (m *Manager) GetGroupSize(groupID int32) int32 {
group := m.GetGroup(groupID)
if group == nil {
return 0
}
return group.GetSize()
}
// IsInGroup checks if an entity is in a specific group
func (m *Manager) IsInGroup(groupID int32, member Entity) bool {
group := m.GetGroup(groupID)
if group == nil || member == nil {
return false
}
members := group.GetMembers()
for _, gmi := range members {
if gmi.Member == member {
return true
}
}
return false
}
// IsPlayerInGroup checks if a player with the given character ID is in a group
func (m *Manager) IsPlayerInGroup(groupID int32, charID int32) Entity {
group := m.GetGroup(groupID)
if group == nil {
return nil
}
members := group.GetMembers()
for _, gmi := range members {
if gmi.IsClient && gmi.Member != nil {
// TODO: Check character ID
// if gmi.Member.GetCharacterID() == charID {
// return gmi.Member
// }
}
}
return nil
}
// IsSpawnInGroup checks if a spawn with the given name is in a group
func (m *Manager) IsSpawnInGroup(groupID int32, name string) bool {
group := m.GetGroup(groupID)
if group == nil {
return false
}
members := group.GetMembers()
for _, gmi := range members {
if gmi.Name == name {
return true
}
}
return false
}
// GetGroupLeader returns the leader of a group
func (m *Manager) GetGroupLeader(groupID int32) Entity {
group := m.GetGroup(groupID)
if group == nil {
return nil
}
members := group.GetMembers()
for _, gmi := range members {
if gmi.Leader {
return gmi.Member
}
}
return nil
}
// MakeLeader changes the leader of a group
func (m *Manager) MakeLeader(groupID int32, newLeader Entity) bool {
group := m.GetGroup(groupID)
if group == nil {
return false
}
err := group.MakeLeader(newLeader)
return err == nil
}
// Group messaging
// SimpleGroupMessage sends a simple message to all members of a group
func (m *Manager) SimpleGroupMessage(groupID int32, message string) {
group := m.GetGroup(groupID)
if group != nil {
group.SimpleGroupMessage(message)
}
}
// SendGroupMessage sends a formatted message to all members of a group
func (m *Manager) SendGroupMessage(groupID int32, msgType int8, message string) {
group := m.GetGroup(groupID)
if group != nil {
group.SendGroupMessage(msgType, message)
}
}
// GroupMessage sends a message to all members of a group (alias for SimpleGroupMessage)
func (m *Manager) GroupMessage(groupID int32, message string) {
m.SimpleGroupMessage(groupID, message)
}
// GroupChatMessage sends a chat message from a member to the group
func (m *Manager) GroupChatMessage(groupID int32, from Entity, language int32, message string, channel int16) {
group := m.GetGroup(groupID)
if group != nil {
group.GroupChatMessage(from, language, message, channel)
}
}
// GroupChatMessageFromName sends a chat message from a named sender to the group
func (m *Manager) GroupChatMessageFromName(groupID int32, fromName string, language int32, message string, channel int16) {
group := m.GetGroup(groupID)
if group != nil {
group.GroupChatMessageFromName(fromName, language, message, channel)
}
}
// SendGroupChatMessage sends a formatted chat message to the group
func (m *Manager) SendGroupChatMessage(groupID int32, channel int16, message string) {
m.GroupChatMessageFromName(groupID, "System", 0, message, channel)
}
// Raid functionality
// ClearGroupRaid clears raid associations for a group
func (m *Manager) ClearGroupRaid(groupID int32) {
group := m.GetGroup(groupID)
if group != nil {
group.ClearGroupRaid()
}
}
// RemoveGroupFromRaid removes a group from a raid
func (m *Manager) RemoveGroupFromRaid(groupID, targetGroupID int32) {
group := m.GetGroup(groupID)
if group != nil {
group.RemoveGroupFromRaid(targetGroupID)
}
}
// IsInRaidGroup checks if two groups are in the same raid
func (m *Manager) IsInRaidGroup(groupID, targetGroupID int32, isLeaderGroup bool) bool {
group := m.GetGroup(groupID)
if group == nil {
return false
}
return group.IsInRaidGroup(targetGroupID, isLeaderGroup)
}
// GetRaidGroups returns the raid groups for a specific group
func (m *Manager) GetRaidGroups(groupID int32) []int32 {
group := m.GetGroup(groupID)
if group == nil {
return []int32{}
}
return group.GetRaidGroups()
}
// ReplaceRaidGroups replaces the raid groups for a specific group
func (m *Manager) ReplaceRaidGroups(groupID int32, newGroups []int32) {
group := m.GetGroup(groupID)
if group != nil {
group.ReplaceRaidGroups(newGroups)
}
}
// Group options
// GetDefaultGroupOptions returns the default group options for a group
func (m *Manager) GetDefaultGroupOptions(groupID int32) (GroupOptions, bool) {
group := m.GetGroup(groupID)
if group == nil {
return GroupOptions{}, false
}
return group.GetGroupOptions(), true
}
// SetGroupOptions sets group options for a specific group
func (m *Manager) SetGroupOptions(groupID int32, options *GroupOptions) error {
group := m.GetGroup(groupID)
if group == nil {
return fmt.Errorf("group %d not found", groupID)
}
return group.SetGroupOptions(options)
}
// Background processing loops
// updateGroupsLoop periodically updates all groups
func (m *Manager) updateGroupsLoop() {
defer m.wg.Done()
ticker := time.NewTicker(m.Config.UpdateInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
m.processGroupUpdates()
case <-m.stopChan:
return
}
}
}
// updateBuffsLoop periodically updates group buffs
func (m *Manager) updateBuffsLoop() {
defer m.wg.Done()
ticker := time.NewTicker(m.Config.BuffUpdateInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
m.updateGroupBuffs()
case <-m.stopChan:
return
}
}
}
// cleanupExpiredInvitesLoop periodically cleans up expired invites
func (m *Manager) cleanupExpiredInvitesLoop() {
defer m.wg.Done()
ticker := time.NewTicker(30 * time.Second) // Check every 30 seconds
defer ticker.Stop()
for {
select {
case <-ticker.C:
m.cleanupExpiredInvites()
case <-m.stopChan:
return
}
}
}
// updateStatsLoop periodically updates statistics
func (m *Manager) updateStatsLoop() {
defer m.wg.Done()
ticker := time.NewTicker(1 * time.Minute) // Update stats every minute
defer ticker.Stop()
for {
select {
case <-ticker.C:
m.updateStatistics()
case <-m.stopChan:
return
}
}
}
// processGroupUpdates processes periodic group updates
func (m *Manager) processGroupUpdates() {
groups := m.GetAllGroups()
for _, group := range groups {
if !group.IsDisbanded() {
// Update member information
members := group.GetMembers()
for _, gmi := range members {
if gmi.Member != nil {
group.UpdateGroupMemberInfo(gmi.Member, false)
}
}
}
}
}
// updateGroupBuffs updates group buffs for all groups
func (m *Manager) updateGroupBuffs() {
// TODO: Implement group buff updates
// This would require integration with the spell/buff system
}
// cleanupExpiredInvites removes expired invitations
func (m *Manager) cleanupExpiredInvites() {
m.invitesMutex.Lock()
defer m.invitesMutex.Unlock()
now := time.Now()
expiredCount := 0
// Clean up regular invites
for key, invite := range m.PendingInvites {
if now.After(invite.ExpiresTime) {
delete(m.PendingInvites, key)
expiredCount++
}
}
// Clean up raid invites
for key, invite := range m.RaidPendingInvites {
if now.After(invite.ExpiresTime) {
delete(m.RaidPendingInvites, key)
expiredCount++
}
}
// Update statistics
if expiredCount > 0 {
m.statsMutex.Lock()
m.Stats.ExpiredInvites += int64(expiredCount)
m.statsMutex.Unlock()
}
}
// updateStatistics updates manager statistics
func (m *Manager) updateStatistics() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
activeGroups := m.MasterList.GetActiveGroups()
raidGroups := m.MasterList.GetRaidGroups()
var totalMembers int64
var raidMembers int64
for _, group := range activeGroups {
totalMembers += int64(group.GetSize())
if group.IsGroupRaid() {
raidMembers += int64(group.GetSize())
}
}
m.Stats.ActiveGroups = int64(len(activeGroups))
m.Stats.ActiveRaids = int64(len(raidGroups))
if len(activeGroups) > 0 {
m.Stats.AverageGroupSize = float64(totalMembers) / float64(len(activeGroups))
} else {
m.Stats.AverageGroupSize = 0
}
m.Stats.LastStatsUpdate = time.Now()
}
// Statistics update methods
// updateStatsForNewGroup updates statistics when a new group is created
func (m *Manager) updateStatsForNewGroup() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
m.Stats.TotalGroups++
}
// updateStatsForRemovedGroup updates statistics when a group is removed
func (m *Manager) updateStatsForRemovedGroup() {
// Statistics are primarily tracked in updateStatistics()
}
// updateStatsForInvite updates statistics when an invite is sent
func (m *Manager) updateStatsForInvite() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
m.Stats.TotalInvites++
}
// updateStatsForAcceptedInvite updates statistics when an invite is accepted
func (m *Manager) updateStatsForAcceptedInvite() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
m.Stats.AcceptedInvites++
}
// updateStatsForDeclinedInvite updates statistics when an invite is declined
func (m *Manager) updateStatsForDeclinedInvite() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
m.Stats.DeclinedInvites++
}
// updateStatsForExpiredInvite updates statistics when an invite expires
func (m *Manager) updateStatsForExpiredInvite() {
if !m.Config.EnableStatistics {
return
}
m.statsMutex.Lock()
defer m.statsMutex.Unlock()
m.Stats.ExpiredInvites++
}
// Event system integration
// AddEventHandler adds an event handler
func (m *Manager) AddEventHandler(handler GroupEventHandler) {
m.eventHandlersMutex.Lock()
defer m.eventHandlersMutex.Unlock()
m.EventHandlers = append(m.EventHandlers, handler)
}
// Integration interfaces
// SetDatabase sets the database interface
func (m *Manager) SetDatabase(db GroupDatabase) {
m.database = db
}
// SetPacketHandler sets the packet handler interface
func (m *Manager) SetPacketHandler(handler GroupPacketHandler) {
m.packetHandler = handler
}
// SetValidator sets the validator interface
func (m *Manager) SetValidator(validator GroupValidator) {
m.validator = validator
}
// SetNotifier sets the notifier interface
func (m *Manager) SetNotifier(notifier GroupNotifier) {
m.notifier = notifier
}
// Event firing methods
// fireGroupCreatedEvent fires a group created event
func (m *Manager) fireGroupCreatedEvent(group *Group, leader Entity) {
m.eventHandlersMutex.RLock()
defer m.eventHandlersMutex.RUnlock()
for _, handler := range m.EventHandlers {
go handler.OnGroupCreated(group, leader)
}
}
// fireGroupDisbandedEvent fires a group disbanded event
func (m *Manager) fireGroupDisbandedEvent(group *Group) {
m.eventHandlersMutex.RLock()
defer m.eventHandlersMutex.RUnlock()
for _, handler := range m.EventHandlers {
go handler.OnGroupDisbanded(group)
}
}
// fireGroupInviteSentEvent fires a group invite sent event
func (m *Manager) fireGroupInviteSentEvent(leader, member Entity) {
m.eventHandlersMutex.RLock()
defer m.eventHandlersMutex.RUnlock()
for _, handler := range m.EventHandlers {
go handler.OnGroupInviteSent(leader, member)
}
}
// fireGroupInviteAcceptedEvent fires a group invite accepted event
func (m *Manager) fireGroupInviteAcceptedEvent(leader, member Entity, groupID int32) {
m.eventHandlersMutex.RLock()
defer m.eventHandlersMutex.RUnlock()
for _, handler := range m.EventHandlers {
go handler.OnGroupInviteAccepted(leader, member, groupID)
}
}
// fireGroupInviteDeclinedEvent fires a group invite declined event
func (m *Manager) fireGroupInviteDeclinedEvent(leader, member Entity) {
m.eventHandlersMutex.RLock()
defer m.eventHandlersMutex.RUnlock()
for _, handler := range m.EventHandlers {
go handler.OnGroupInviteDeclined(leader, member)
}
}