package channel import ( "fmt" "slices" "sync" "time" ) // Channel type constants const ( TypeNone = 0 TypeWorld = 1 // Persistent, loaded from database TypeCustom = 2 // Temporary, deleted when empty ) // Channel actions for client communication const ( ActionJoin = 0 // Player joins channel ActionLeave = 1 // Player leaves channel ActionOtherJoin = 2 // Another player joins ActionOtherLeave = 3 // Another player leaves ) // Channel name and password limits const ( MaxNameLength = 100 MaxPasswordLength = 100 ) // Channel restrictions const ( NoLevelRestriction = 0 NoRaceRestriction = 0 NoClassRestriction = 0 ) // Channel represents a chat channel with membership and message routing capabilities type Channel struct { mu sync.RWMutex name string password string channelType int levelRestriction int32 raceRestriction int32 classRestriction int32 members []int32 // Character IDs discordEnabled bool created time.Time } // ChannelInfo provides basic channel information for client lists type ChannelInfo struct { Name string HasPassword bool MemberCount int LevelRestriction int32 RaceRestriction int32 ClassRestriction int32 ChannelType int } // ChannelMember represents a member in a channel type ChannelMember struct { CharacterID int32 CharacterName string Level int32 Race int32 Class int32 JoinedAt time.Time } // NewChannel creates a new channel instance func NewChannel(name string) *Channel { return &Channel{ name: name, members: make([]int32, 0), created: time.Now(), } } // SetName sets the channel name func (c *Channel) SetName(name string) { c.mu.Lock() defer c.mu.Unlock() c.name = name } // SetPassword sets the channel password func (c *Channel) SetPassword(password string) { c.mu.Lock() defer c.mu.Unlock() c.password = password } // SetType sets the channel type func (c *Channel) SetType(channelType int) { c.mu.Lock() defer c.mu.Unlock() c.channelType = channelType } // SetLevelRestriction sets the minimum level required to join func (c *Channel) SetLevelRestriction(level int32) { c.mu.Lock() defer c.mu.Unlock() c.levelRestriction = level } // SetRacesAllowed sets the race bitmask for allowed races func (c *Channel) SetRacesAllowed(races int32) { c.mu.Lock() defer c.mu.Unlock() c.raceRestriction = races } // SetClassesAllowed sets the class bitmask for allowed classes func (c *Channel) SetClassesAllowed(classes int32) { c.mu.Lock() defer c.mu.Unlock() c.classRestriction = classes } // SetDiscordEnabled enables or disables Discord integration for this channel func (c *Channel) SetDiscordEnabled(enabled bool) { c.mu.Lock() defer c.mu.Unlock() c.discordEnabled = enabled } // GetName returns the channel name func (c *Channel) GetName() string { c.mu.RLock() defer c.mu.RUnlock() return c.name } // GetType returns the channel type func (c *Channel) GetType() int { c.mu.RLock() defer c.mu.RUnlock() return c.channelType } // GetNumClients returns the number of clients in the channel func (c *Channel) GetNumClients() int { c.mu.RLock() defer c.mu.RUnlock() return len(c.members) } // GetCreatedTime returns when the channel was created func (c *Channel) GetCreatedTime() time.Time { c.mu.RLock() defer c.mu.RUnlock() return c.created } // HasPassword returns true if the channel has a password func (c *Channel) HasPassword() bool { c.mu.RLock() defer c.mu.RUnlock() return c.password != "" } // PasswordMatches checks if the provided password matches the channel password func (c *Channel) PasswordMatches(password string) bool { c.mu.RLock() defer c.mu.RUnlock() return c.password == password } // CanJoinChannelByLevel checks if a player's level meets the channel requirements func (c *Channel) CanJoinChannelByLevel(level int32) bool { c.mu.RLock() defer c.mu.RUnlock() return level >= c.levelRestriction } // CanJoinChannelByRace checks if a player's race is allowed in the channel func (c *Channel) CanJoinChannelByRace(raceID int32) bool { c.mu.RLock() defer c.mu.RUnlock() return c.raceRestriction == NoRaceRestriction || (c.raceRestriction&(1<