package groups import ( "eq2emu/internal/entity" ) // GroupAware interface for entities that can be part of groups type GroupAware interface { // GetGroupMemberInfo returns the group member info for this entity GetGroupMemberInfo() *GroupMemberInfo // SetGroupMemberInfo sets the group member info for this entity SetGroupMemberInfo(info *GroupMemberInfo) // GetGroupID returns the current group ID GetGroupID() int32 // SetGroupID sets the current group ID SetGroupID(groupID int32) // IsInGroup returns true if the entity is in a group IsInGroup() bool } // GroupManager interface for managing groups type GroupManagerInterface interface { // Group creation and management NewGroup(leader entity.Entity, options *GroupOptions, overrideGroupID int32) (int32, error) RemoveGroup(groupID int32) error GetGroup(groupID int32) *Group IsGroupIDValid(groupID int32) bool // Member management AddGroupMember(groupID int32, member entity.Entity, isLeader bool) error AddGroupMemberFromPeer(groupID int32, info *GroupMemberInfo) error RemoveGroupMember(groupID int32, member entity.Entity) error RemoveGroupMemberByName(groupID int32, name string, isClient bool, charID int32) error // Group updates SendGroupUpdate(groupID int32, excludeClient interface{}, forceRaidUpdate bool) // Invitations Invite(leader entity.Entity, member entity.Entity) int8 AddInvite(leader entity.Entity, member entity.Entity) bool AcceptInvite(member entity.Entity, groupOverrideID *int32, autoAddGroup bool) int8 DeclineInvite(member entity.Entity) ClearPendingInvite(member entity.Entity) HasPendingInvite(member entity.Entity) string // Group utilities GetGroupSize(groupID int32) int32 IsInGroup(groupID int32, member entity.Entity) bool IsPlayerInGroup(groupID int32, charID int32) entity.Entity IsSpawnInGroup(groupID int32, name string) bool GetGroupLeader(groupID int32) entity.Entity MakeLeader(groupID int32, newLeader entity.Entity) bool // Messaging SimpleGroupMessage(groupID int32, message string) SendGroupMessage(groupID int32, msgType int8, message string) GroupMessage(groupID int32, message string) GroupChatMessage(groupID int32, from entity.Entity, language int32, message string, channel int16) GroupChatMessageFromName(groupID int32, fromName string, language int32, message string, channel int16) SendGroupChatMessage(groupID int32, channel int16, message string) // Raid functionality ClearGroupRaid(groupID int32) RemoveGroupFromRaid(groupID, targetGroupID int32) IsInRaidGroup(groupID, targetGroupID int32, isLeaderGroup bool) bool GetRaidGroups(groupID int32) []int32 ReplaceRaidGroups(groupID int32, newGroups []int32) // Group options GetDefaultGroupOptions(groupID int32) (GroupOptions, bool) SetGroupOptions(groupID int32, options *GroupOptions) error // Statistics GetStats() GroupManagerStats GetGroupCount() int32 GetAllGroups() []*Group } // GroupEventHandler interface for handling group events type GroupEventHandler interface { // Group lifecycle events OnGroupCreated(group *Group, leader entity.Entity) error OnGroupDisbanded(group *Group) error OnGroupMemberJoined(group *Group, member entity.Entity) error OnGroupMemberLeft(group *Group, member entity.Entity) error OnGroupLeaderChanged(group *Group, oldLeader, newLeader entity.Entity) error // Invitation events OnGroupInviteSent(leader, member entity.Entity) error OnGroupInviteAccepted(leader, member entity.Entity, groupID int32) error OnGroupInviteDeclined(leader, member entity.Entity) error OnGroupInviteExpired(leader, member entity.Entity) error // Raid events OnRaidFormed(groups []*Group) error OnRaidDisbanded(groups []*Group) error OnRaidInviteSent(leaderGroup *Group, targetGroup *Group) error OnRaidInviteAccepted(leaderGroup *Group, targetGroup *Group) error OnRaidInviteDeclined(leaderGroup *Group, targetGroup *Group) error // Group activity events OnGroupMessage(group *Group, from entity.Entity, message string, channel int16) error OnGroupOptionsChanged(group *Group, oldOptions, newOptions *GroupOptions) error OnGroupMemberUpdate(group *Group, member *GroupMemberInfo) error } // GroupDatabase interface for database operations type GroupDatabase interface { // Group persistence SaveGroup(group *Group) error LoadGroup(groupID int32) (*Group, error) DeleteGroup(groupID int32) error // Group member persistence SaveGroupMember(groupID int32, member *GroupMemberInfo) error LoadGroupMembers(groupID int32) ([]*GroupMemberInfo, error) DeleteGroupMember(groupID int32, memberName string) error // Group options persistence SaveGroupOptions(groupID int32, options *GroupOptions) error LoadGroupOptions(groupID int32) (*GroupOptions, error) // Raid persistence SaveRaidGroups(groupID int32, raidGroups []int32) error LoadRaidGroups(groupID int32) ([]int32, error) // Statistics persistence SaveGroupStats(stats *GroupManagerStats) error LoadGroupStats() (*GroupManagerStats, error) // Cleanup operations CleanupExpiredGroups() error CleanupOrphanedMembers() error } // GroupPacketHandler interface for handling group-related packets type GroupPacketHandler interface { // Group update packets SendGroupUpdate(members []*GroupMemberInfo, excludeClient interface{}) error SendGroupMemberUpdate(member *GroupMemberInfo, excludeClient interface{}) error SendGroupOptionsUpdate(groupID int32, options *GroupOptions, excludeClient interface{}) error // Group invitation packets SendGroupInvite(inviter, invitee entity.Entity) error SendGroupInviteResponse(inviter, invitee entity.Entity, accepted bool) error // Group messaging packets SendGroupMessage(members []*GroupMemberInfo, message *GroupMessage) error SendGroupChatMessage(members []*GroupMemberInfo, from string, message string, channel int16, language int32) error // Raid packets SendRaidUpdate(raidGroups []*Group, excludeClient interface{}) error SendRaidInvite(leaderGroup, targetGroup *Group) error SendRaidInviteResponse(leaderGroup, targetGroup *Group, accepted bool) error // Group UI packets SendGroupWindowUpdate(client interface{}, group *Group) error SendRaidWindowUpdate(client interface{}, raidGroups []*Group) error // Group member packets SendGroupMemberStats(member *GroupMemberInfo, excludeClient interface{}) error SendGroupMemberZoneChange(member *GroupMemberInfo, oldZoneID, newZoneID int32) error } // GroupValidator interface for validating group operations type GroupValidator interface { // Group creation validation ValidateGroupCreation(leader entity.Entity, options *GroupOptions) error ValidateGroupJoin(group *Group, member entity.Entity) error ValidateGroupLeave(group *Group, member entity.Entity) error // Invitation validation ValidateGroupInvite(leader, member entity.Entity) error ValidateRaidInvite(leaderGroup, targetGroup *Group) error // Group operation validation ValidateLeadershipChange(group *Group, oldLeader, newLeader entity.Entity) error ValidateGroupOptions(group *Group, options *GroupOptions) error ValidateGroupMessage(group *Group, from entity.Entity, message string) error // Raid validation ValidateRaidFormation(groups []*Group) error ValidateRaidOperation(raidGroups []*Group, operation string) error } // GroupNotifier interface for sending notifications type GroupNotifier interface { // Group notifications NotifyGroupCreated(group *Group, leader entity.Entity) error NotifyGroupDisbanded(group *Group, reason string) error NotifyGroupMemberJoined(group *Group, member entity.Entity) error NotifyGroupMemberLeft(group *Group, member entity.Entity, reason string) error NotifyGroupLeaderChanged(group *Group, oldLeader, newLeader entity.Entity) error // Invitation notifications NotifyGroupInviteSent(leader, member entity.Entity) error NotifyGroupInviteReceived(leader, member entity.Entity) error NotifyGroupInviteAccepted(leader, member entity.Entity, groupID int32) error NotifyGroupInviteDeclined(leader, member entity.Entity) error NotifyGroupInviteExpired(leader, member entity.Entity) error // Raid notifications NotifyRaidFormed(groups []*Group) error NotifyRaidDisbanded(groups []*Group, reason string) error NotifyRaidInviteSent(leaderGroup, targetGroup *Group) error NotifyRaidInviteReceived(leaderGroup, targetGroup *Group) error NotifyRaidInviteAccepted(leaderGroup, targetGroup *Group) error NotifyRaidInviteDeclined(leaderGroup, targetGroup *Group) error // System notifications NotifyGroupSystemMessage(group *Group, message string, msgType int8) error NotifyGroupError(group *Group, error string, errorCode int8) error } // GroupStatistics interface for tracking group statistics type GroupStatistics interface { // Group statistics RecordGroupCreated(group *Group, leader entity.Entity) RecordGroupDisbanded(group *Group, duration int64) RecordGroupMemberJoined(group *Group, member entity.Entity) RecordGroupMemberLeft(group *Group, member entity.Entity, duration int64) // Invitation statistics RecordInviteSent(leader, member entity.Entity) RecordInviteAccepted(leader, member entity.Entity, responseTime int64) RecordInviteDeclined(leader, member entity.Entity, responseTime int64) RecordInviteExpired(leader, member entity.Entity) // Raid statistics RecordRaidFormed(groups []*Group) RecordRaidDisbanded(groups []*Group, duration int64) // Activity statistics RecordGroupMessage(group *Group, from entity.Entity, messageType int8) RecordGroupActivity(group *Group, activityType string) // Performance statistics RecordGroupProcessingTime(operation string, duration int64) RecordGroupMemoryUsage(groups int32, members int32) // Statistics retrieval GetGroupStatistics(groupID int32) map[string]interface{} GetOverallStatistics() map[string]interface{} GetStatisticsSummary() *GroupManagerStats } // GroupAdapter adapts group functionality for other systems type GroupAdapter struct { group *Group } // NewGroupAdapter creates a new group adapter func NewGroupAdapter(group *Group) *GroupAdapter { return &GroupAdapter{group: group} } // GetGroup returns the wrapped group func (ga *GroupAdapter) GetGroup() *Group { return ga.group } // GetGroupID returns the group ID func (ga *GroupAdapter) GetGroupID() int32 { return ga.group.GetID() } // GetGroupSize returns the group size func (ga *GroupAdapter) GetGroupSize() int32 { return ga.group.GetSize() } // GetMembers returns group members func (ga *GroupAdapter) GetMembers() []*GroupMemberInfo { return ga.group.GetMembers() } // GetLeader returns the group leader func (ga *GroupAdapter) GetLeader() entity.Entity { members := ga.group.GetMembers() for _, member := range members { if member.Leader { return member.Member } } return nil } // GetLeaderName returns the group leader's name func (ga *GroupAdapter) GetLeaderName() string { return ga.group.GetLeaderName() } // IsInRaid returns true if the group is part of a raid func (ga *GroupAdapter) IsInRaid() bool { return ga.group.IsGroupRaid() } // GetRaidGroups returns the raid groups func (ga *GroupAdapter) GetRaidGroups() []int32 { return ga.group.GetRaidGroups() } // IsMember checks if an entity is a member of the group func (ga *GroupAdapter) IsMember(entity entity.Entity) bool { if entity == nil { return false } members := ga.group.GetMembers() for _, member := range members { if member.Member == entity { return true } } return false } // HasMemberNamed checks if the group has a member with the given name func (ga *GroupAdapter) HasMemberNamed(name string) bool { members := ga.group.GetMembers() for _, member := range members { if member.Name == name { return true } } return false } // GetMemberByName returns a member by name func (ga *GroupAdapter) GetMemberByName(name string) *GroupMemberInfo { members := ga.group.GetMembers() for _, member := range members { if member.Name == name { return member } } return nil } // GetMemberByEntity returns a member by entity func (ga *GroupAdapter) GetMemberByEntity(entity entity.Entity) *GroupMemberInfo { if entity == nil { return nil } members := ga.group.GetMembers() for _, member := range members { if member.Member == entity { return member } } return nil } // IsLeader checks if an entity is the group leader func (ga *GroupAdapter) IsLeader(entity entity.Entity) bool { if entity == nil { return false } members := ga.group.GetMembers() for _, member := range members { if member.Member == entity && member.Leader { return true } } return false } // GetOptions returns the group options func (ga *GroupAdapter) GetOptions() GroupOptions { return ga.group.GetGroupOptions() } // IsDisbanded returns true if the group has been disbanded func (ga *GroupAdapter) IsDisbanded() bool { return ga.group.IsDisbanded() } // GetCreatedTime returns when the group was created func (ga *GroupAdapter) GetCreatedTime() time.Time { return ga.group.GetCreatedTime() } // GetLastActivity returns the last activity time func (ga *GroupAdapter) GetLastActivity() time.Time { return ga.group.GetLastActivity() } // EntityGroupAdapter adapts entity functionality for group systems type EntityGroupAdapter struct { entity entity.Entity } // NewEntityGroupAdapter creates a new entity group adapter func NewEntityGroupAdapter(entity entity.Entity) *EntityGroupAdapter { return &EntityGroupAdapter{entity: entity} } // GetEntity returns the wrapped entity func (ega *EntityGroupAdapter) GetEntity() entity.Entity { return ega.entity } // GetName returns the entity name func (ega *EntityGroupAdapter) GetName() string { return ega.entity.GetName() } // GetLevel returns the entity level func (ega *EntityGroupAdapter) GetLevel() int8 { return ega.entity.GetLevel() } // GetClass returns the entity class func (ega *EntityGroupAdapter) GetClass() int8 { return ega.entity.GetClass() } // GetRace returns the entity race func (ega *EntityGroupAdapter) GetRace() int8 { return ega.entity.GetRace() } // GetZoneID returns the current zone ID func (ega *EntityGroupAdapter) GetZoneID() int32 { if zone := ega.entity.GetZone(); zone != nil { return zone.GetZoneID() } return 0 } // GetInstanceID returns the current instance ID func (ega *EntityGroupAdapter) GetInstanceID() int32 { if zone := ega.entity.GetZone(); zone != nil { return zone.GetInstanceID() } return 0 } // GetZoneName returns the current zone name func (ega *EntityGroupAdapter) GetZoneName() string { if zone := ega.entity.GetZone(); zone != nil { return zone.GetZoneName() } return "" } // GetHP returns current HP func (ega *EntityGroupAdapter) GetHP() int32 { return ega.entity.GetHP() } // GetMaxHP returns maximum HP func (ega *EntityGroupAdapter) GetMaxHP() int32 { return ega.entity.GetTotalHP() } // GetPower returns current power func (ega *EntityGroupAdapter) GetPower() int32 { return ega.entity.GetPower() } // GetMaxPower returns maximum power func (ega *EntityGroupAdapter) GetMaxPower() int32 { return ega.entity.GetTotalPower() } // IsPlayer returns true if the entity is a player func (ega *EntityGroupAdapter) IsPlayer() bool { return ega.entity.IsPlayer() } // IsNPC returns true if the entity is an NPC func (ega *EntityGroupAdapter) IsNPC() bool { return ega.entity.IsNPC() } // IsBot returns true if the entity is a bot func (ega *EntityGroupAdapter) IsBot() bool { return ega.entity.IsBot() } // IsAlive returns true if the entity is alive func (ega *EntityGroupAdapter) IsAlive() bool { return !ega.entity.IsDead() } // IsDead returns true if the entity is dead func (ega *EntityGroupAdapter) IsDead() bool { return ega.entity.IsDead() } // GetDistance returns distance to another entity func (ega *EntityGroupAdapter) GetDistance(other entity.Entity) float32 { return ega.entity.GetDistance(&other.Spawn) }