2025-08-08 12:55:30 -05:00
..
2025-08-08 12:55:30 -05:00
2025-07-31 11:22:03 -05:00
2025-08-08 12:55:30 -05:00
2025-08-08 12:55:30 -05:00
2025-08-08 12:55:30 -05:00
2025-08-01 23:16:49 -05:00
2025-08-08 12:55:30 -05:00
2025-08-08 12:55:30 -05:00
2025-08-08 12:55:30 -05:00
2025-08-08 12:55:30 -05:00
2025-08-07 22:37:04 -05:00

Groups System

The groups system (internal/groups) provides comprehensive player group and raid management for the EQ2Go server emulator. This system is converted from the original C++ EQ2EMu PlayerGroups implementation with modern Go concurrency patterns and clean architecture principles.

Overview

The groups system manages all aspects of player groups and raids including:

  • Group Management: Creation, disbanding, member management
  • Raid Functionality: Multi-group coordination with up to 4 groups (24 players)
  • Cross-Server Groups: Peer-to-peer group coordination across server instances
  • Group Invitations: Invitation system with timeouts and validation
  • Group Communication: Chat, messaging, and broadcast systems
  • Group Options: Loot distribution, auto-split, leadership settings
  • Quest Sharing: Share quests with group members
  • Group Buffs: Coordinated buff management across group members
  • Statistics: Comprehensive group activity tracking

Architecture

Core Components

Group - Individual group with up to 6 members, options, and raid functionality
GroupManager - Global group management, invitations, and coordination
Service - High-level service interface with validation and configuration
GroupMemberInfo - Detailed member information and statistics
GroupOptions - Group behavior and loot configuration

Key Files

  • group.go - Core Group struct and member management
  • manager.go - GroupManager with global group coordination
  • service.go - High-level Service interface with validation
  • types.go - Data structures and type definitions
  • interfaces.go - System integration interfaces and adapters
  • constants.go - All group system constants and limits
  • README.md - This documentation

Group Creation and Management

// Create group service
config := groups.DefaultServiceConfig()
service := groups.NewService(config)
service.Start()

// Create a new group
leader := &entity.Player{...}
options := &groups.GroupOptions{
    LootMethod: groups.LOOT_METHOD_ROUND_ROBIN,
    AutoSplit:  groups.AUTO_SPLIT_ENABLED,
}
groupID, err := service.CreateGroup(leader, options)

// Get group information
groupInfo, err := service.GetGroupInfo(groupID)
fmt.Printf("Group %d has %d members\n", groupInfo.GroupID, groupInfo.Size)

Group Invitations

// Invite a player to the group
leader := &entity.Player{...}
member := &entity.Player{...}

// Send invitation
err := service.InviteToGroup(leader, member)
if err != nil {
    fmt.Printf("Invitation failed: %v\n", err)
}

// Accept invitation
err = service.AcceptGroupInvite(member)
if err != nil {
    fmt.Printf("Failed to accept: %v\n", err)
}

// Decline invitation
service.DeclineGroupInvite(member)

Group Member Management

// Get group manager directly
manager := service.GetManager()

// Add member to existing group
err := manager.AddGroupMember(groupID, member, false)

// Remove member from group
err := manager.RemoveGroupMember(groupID, member)

// Transfer leadership
err := service.TransferLeadership(groupID, newLeader)

// Check if entity is in group
isInGroup := manager.IsInGroup(groupID, member)

// Get group leader
leader := manager.GetGroupLeader(groupID)

Group Communication

// Send simple message to group
manager.SimpleGroupMessage(groupID, "Welcome to the group!")

// Send system message
manager.SendGroupMessage(groupID, groups.GROUP_MESSAGE_TYPE_SYSTEM, "Group is ready!")

// Send chat message from member
manager.GroupChatMessage(groupID, fromEntity, 0, "Hello everyone!", groups.CHANNEL_GROUP_SAY)

// Send formatted chat message
manager.SendGroupChatMessage(groupID, groups.CHANNEL_GROUP_CHAT, "Raid starting in 5 minutes")

Group Options Configuration

// Configure group options
options := groups.GroupOptions{
    LootMethod:        groups.LOOT_METHOD_NEED_BEFORE_GREED,
    LootItemsRarity:   groups.LOOT_RARITY_RARE,
    AutoSplit:         groups.AUTO_SPLIT_ENABLED,
    GroupLockMethod:   groups.LOCK_METHOD_INVITE_ONLY,
    GroupAutolock:     groups.AUTO_LOCK_ENABLED,
    AutoLootMethod:    groups.AUTO_LOOT_ENABLED,
}

// Apply options to group
err := manager.SetGroupOptions(groupID, &options)

// Get current options
currentOptions, exists := manager.GetDefaultGroupOptions(groupID)
if exists {
    fmt.Printf("Loot method: %d\n", currentOptions.LootMethod)
}

Raid Management

// Form a raid from multiple groups
leaderGroupID := int32(1)
targetGroups := []int32{2, 3, 4}

err := service.FormRaid(leaderGroupID, targetGroups)
if err != nil {
    fmt.Printf("Failed to form raid: %v\n", err)
}

// Check if groups are in same raid
isInRaid := manager.IsInRaidGroup(groupID1, groupID2, false)

// Get all raid groups for a group
raidGroups := manager.GetRaidGroups(groupID)
fmt.Printf("Raid has %d groups\n", len(raidGroups))

// Disband raid
err := service.DisbandRaid(leaderGroupID)

Cross-Server Group Management

// Add member from peer server
memberInfo := &groups.GroupMemberInfo{
    Name:                "RemotePlayer",
    Leader:              false,
    IsClient:            true,
    ClassID:             1,
    HPCurrent:           1500,
    HPMax:               1500,
    PowerCurrent:        800,
    PowerMax:            800,
    LevelCurrent:        50,
    LevelMax:            50,
    RaceID:              0,
    Zone:                "commonlands",
    ZoneID:              220,
    InstanceID:          0,
    ClientPeerAddress:   "192.168.1.10",
    ClientPeerPort:      9000,
    IsRaidLooter:        false,
}

err := manager.AddGroupMemberFromPeer(groupID, memberInfo)

// Remove peer member by name
err = manager.RemoveGroupMemberByName(groupID, "RemotePlayer", true, 12345)

Group Statistics and Information

// Get service statistics
stats := service.GetServiceStats()
fmt.Printf("Active groups: %d\n", stats.ManagerStats.ActiveGroups)
fmt.Printf("Total invites: %d\n", stats.ManagerStats.TotalInvites)
fmt.Printf("Average group size: %.1f\n", stats.ManagerStats.AverageGroupSize)

// Get all groups in a zone
zoneGroups := service.GetGroupsByZone(zoneID)
for _, group := range zoneGroups {
    fmt.Printf("Group %d has %d members in zone\n", group.GroupID, group.Size)
}

// Get groups containing specific members
members := []entity.Entity{player1, player2}
memberGroups := service.GetMemberGroups(members)

Event Handling

// Create custom event handler
type MyGroupEventHandler struct{}

func (h *MyGroupEventHandler) OnGroupCreated(group *groups.Group, leader entity.Entity) error {
    fmt.Printf("Group %d created by %s\n", group.GetID(), leader.GetName())
    return nil
}

func (h *MyGroupEventHandler) OnGroupMemberJoined(group *groups.Group, member entity.Entity) error {
    fmt.Printf("%s joined group %d\n", member.GetName(), group.GetID())
    return nil
}

func (h *MyGroupEventHandler) OnGroupDisbanded(group *groups.Group) error {
    fmt.Printf("Group %d disbanded\n", group.GetID())
    return nil
}

// ... implement other required methods

// Register event handler
handler := &MyGroupEventHandler{}
service.AddEventHandler(handler)

Database Integration

// Implement database interface
type MyGroupDatabase struct {
    // database connection
}

func (db *MyGroupDatabase) SaveGroup(group *groups.Group) error {
    // Save group to database
    return nil
}

func (db *MyGroupDatabase) LoadGroup(groupID int32) (*groups.Group, error) {
    // Load group from database
    return nil, nil
}

// ... implement other required methods

// Set database interface
database := &MyGroupDatabase{}
service.SetDatabase(database)

Packet Handling Integration

// Implement packet handler interface
type MyGroupPacketHandler struct {
    // client connection management
}

func (ph *MyGroupPacketHandler) SendGroupUpdate(members []*groups.GroupMemberInfo, excludeClient any) error {
    // Send group update packets to clients
    return nil
}

func (ph *MyGroupPacketHandler) SendGroupInvite(inviter, invitee entity.Entity) error {
    // Send invitation packet to client
    return nil
}

// ... implement other required methods

// Set packet handler
packetHandler := &MyGroupPacketHandler{}
service.SetPacketHandler(packetHandler)

Validation and Security

// Implement custom validator
type MyGroupValidator struct{}

func (v *MyGroupValidator) ValidateGroupCreation(leader entity.Entity, options *groups.GroupOptions) error {
    // Custom validation logic
    if leader.GetLevel() < 10 {
        return fmt.Errorf("must be level 10+ to create groups")
    }
    return nil
}

func (v *MyGroupValidator) ValidateGroupInvite(leader, member entity.Entity) error {
    // Custom invitation validation
    if leader.GetZone() != member.GetZone() {
        return fmt.Errorf("cross-zone invites not allowed")
    }
    return nil
}

// ... implement other required methods

// Set validator
validator := &MyGroupValidator{}
service.SetValidator(validator)

Configuration

Service Configuration

config := groups.ServiceConfig{
    ManagerConfig: groups.GroupManagerConfig{
        MaxGroups:          1000,
        MaxRaidGroups:      4,
        InviteTimeout:      30 * time.Second,
        UpdateInterval:     1 * time.Second,
        BuffUpdateInterval: 5 * time.Second,
        EnableCrossServer:  true,
        EnableRaids:        true,
        EnableQuestSharing: true,
        EnableStatistics:   true,
    },
    AutoCreateGroups:     true,
    AllowCrossZoneGroups: true,
    AllowBotMembers:      true,
    AllowNPCMembers:      false,
    MaxInviteDistance:    100.0,
    GroupLevelRange:      10,
    EnableGroupPvP:       false,
    EnableGroupBuffs:     true,
    DatabaseEnabled:      true,
    EventsEnabled:        true,
    StatisticsEnabled:    true,
    ValidationEnabled:    true,
}

service := groups.NewService(config)

Group Options

Available group options for loot and behavior management:

  • Loot Methods: Leader only, round robin, need before greed, lotto
  • Loot Rarity: Common, uncommon, rare, legendary, fabled
  • Auto Split: Enable/disable automatic coin splitting
  • Group Lock: Open, invite only, closed
  • Auto Lock: Automatic group locking settings
  • Auto Loot: Automatic loot distribution

Constants and Limits

Group Limits

  • MAX_GROUP_SIZE: 6 members per group
  • MAX_RAID_GROUPS: 4 groups per raid
  • MAX_RAID_SIZE: 24 total raid members

Invitation System

  • Default invite timeout: 30 seconds
  • Invitation error codes: Success, already in group, group full, declined, etc.

Communication Channels

  • CHANNEL_GROUP_SAY: Group say channel (11)
  • CHANNEL_GROUP_CHAT: Group chat channel (31)
  • CHANNEL_RAID_SAY: Raid say channel (35)

Thread Safety

All group operations are thread-safe using appropriate synchronization:

  • RWMutex for read-heavy operations (member lists, group lookups)
  • Atomic operations for simple counters and flags
  • Channel-based communication for message and update processing
  • Proper lock ordering to prevent deadlocks
  • Background goroutines for periodic processing

Integration with Other Systems

The groups system integrates with:

  • Entity System - Groups work with any entity (players, NPCs, bots)
  • Player System - Player-specific group functionality and client handling
  • Quest System - Quest sharing within groups
  • Spell System - Group buffs and spell coordination
  • Zone System - Cross-zone group management
  • Chat System - Group communication channels
  • Database System - Group persistence and recovery
  • Network System - Cross-server group coordination

Performance Considerations

  • Efficient member tracking with hash maps for O(1) lookups
  • Batched message processing to reduce overhead
  • Background processing for periodic updates and cleanup
  • Memory-efficient data structures with proper cleanup
  • Statistics collection with minimal performance impact
  • Channel buffering to prevent blocking on message queues

Migration from C++

This Go implementation maintains compatibility with the original C++ EQ2EMu groups system while providing:

  • Modern concurrency with goroutines and channels
  • Better error handling with Go's error interface
  • Cleaner architecture with interface-based design
  • Improved maintainability with package organization
  • Enhanced testing capabilities
  • Type safety with Go's type system

TODO Items

The conversion includes TODO comments marking areas for future implementation:

  • Quest sharing integration with the quest system
  • Complete spell/buff integration for group buffs
  • Advanced packet handling for all client communication
  • Complete database schema implementation
  • Cross-server peer management completion
  • Bot and NPC integration improvements
  • Advanced raid mechanics (raid loot, raid targeting)
  • Group PvP functionality implementation
  • Performance optimizations for large-scale deployments

Usage Examples

See the code examples throughout this documentation for detailed usage patterns. The system is designed to be used alongside the existing EQ2Go server infrastructure with proper initialization and configuration.

The groups system provides a solid foundation for MMO group mechanics while maintaining the flexibility to extend and customize behavior through the comprehensive interface system.