forked from External/grumble
Add VoiceTarget support (whispers and shouts)
This commit is contained in:
parent
b799eb2bda
commit
a42e4d07b4
7 changed files with 276 additions and 18 deletions
150
voicetarget.go
Normal file
150
voicetarget.go
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright (c) 2011 The Grumble Authors
|
||||
// The use of this source code is goverened by a BSD-style
|
||||
// license that can be found in the LICENSE-file.
|
||||
|
||||
package main
|
||||
|
||||
// A VoiceTarget holds information about a single
|
||||
// VoiceTarget entry of a Client.
|
||||
type VoiceTarget struct {
|
||||
sessions []uint32
|
||||
channels []voiceTargetChannel
|
||||
|
||||
directCache map[uint32]*Client
|
||||
fromChannelsCache map[uint32]*Client
|
||||
}
|
||||
|
||||
type voiceTargetChannel struct {
|
||||
id uint32
|
||||
subChannels bool
|
||||
links bool
|
||||
onlyGroup string
|
||||
}
|
||||
|
||||
// Add's a client's session to the VoiceTarget
|
||||
func (vt *VoiceTarget) AddSession(session uint32) {
|
||||
vt.sessions = append(vt.sessions, session)
|
||||
}
|
||||
|
||||
// Add a channel to the VoiceTarget.
|
||||
// If subchannels is true, any sent voice packets will also be sent to all subchannels.
|
||||
// If links is true, any sent voice packets will also be sent to all linked channels.
|
||||
// If group is a non-empty string, any sent voice packets will only be broadcast to members
|
||||
// of that group who reside in the channel (or its children or linked channels).
|
||||
func (vt *VoiceTarget) AddChannel(id uint32, subchannels bool, links bool, group string) {
|
||||
vt.channels = append(vt.channels, voiceTargetChannel{
|
||||
id: id,
|
||||
subChannels: subchannels,
|
||||
links: links,
|
||||
onlyGroup: group,
|
||||
})
|
||||
}
|
||||
|
||||
// Checks whether the VoiceTarget is empty (has no targets)
|
||||
func (vt *VoiceTarget) IsEmpty() bool {
|
||||
return len(vt.sessions) == 0 && len(vt.channels) == 0
|
||||
}
|
||||
|
||||
// Clear the VoiceTarget's cache.
|
||||
func (vt *VoiceTarget) ClearCache() {
|
||||
vt.directCache = nil
|
||||
vt.fromChannelsCache = nil
|
||||
}
|
||||
|
||||
// Send the contents of the VoiceBroadcast to all targets specified in the
|
||||
// VoiceTarget.
|
||||
func (vt *VoiceTarget) SendVoiceBroadcast(vb *VoiceBroadcast) {
|
||||
buf := vb.buf
|
||||
client := vb.client
|
||||
server := client.server
|
||||
|
||||
direct := vt.directCache
|
||||
fromChannels := vt.fromChannelsCache
|
||||
|
||||
if direct == nil || fromChannels == nil {
|
||||
direct = make(map[uint32]*Client)
|
||||
fromChannels = make(map[uint32]*Client)
|
||||
|
||||
for _, vtc := range vt.channels {
|
||||
channel := server.Channels[int(vtc.id)]
|
||||
if channel == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if !vtc.subChannels && !vtc.links && vtc.onlyGroup == "" {
|
||||
if server.HasPermission(client, channel, WhisperPermission) {
|
||||
for _, target := range channel.clients {
|
||||
fromChannels[target.Session] = target
|
||||
}
|
||||
}
|
||||
} else {
|
||||
server.Printf("%v", vtc)
|
||||
newchans := make(map[int]*Channel)
|
||||
if vtc.links {
|
||||
newchans = channel.AllLinks()
|
||||
} else {
|
||||
newchans[channel.Id] = channel
|
||||
}
|
||||
if vtc.subChannels {
|
||||
subchans := channel.AllSubChannels()
|
||||
for k, v := range subchans {
|
||||
newchans[k] = v
|
||||
}
|
||||
}
|
||||
for _, newchan := range newchans {
|
||||
if server.HasPermission(client, newchan, WhisperPermission) {
|
||||
for _, target := range newchan.clients {
|
||||
if vtc.onlyGroup == "" || GroupMemberCheck(newchan, newchan, vtc.onlyGroup, target) {
|
||||
fromChannels[target.Session] = target
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, session := range vt.sessions {
|
||||
target := server.clients[session]
|
||||
if target != nil {
|
||||
if _, alreadyInFromChannels := fromChannels[target.Session]; !alreadyInFromChannels {
|
||||
direct[target.Session] = target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we don't send to ourselves.
|
||||
delete(direct, client.Session)
|
||||
delete(fromChannels, client.Session)
|
||||
|
||||
if vt.directCache == nil {
|
||||
vt.directCache = direct
|
||||
}
|
||||
|
||||
if vt.fromChannelsCache == nil {
|
||||
vt.fromChannelsCache = fromChannels
|
||||
}
|
||||
}
|
||||
|
||||
kind := buf[0] & 0xe0
|
||||
|
||||
if len(fromChannels) > 0 {
|
||||
for _, target := range fromChannels {
|
||||
buf[0] = kind | 2
|
||||
err := target.SendUDP(buf)
|
||||
if err != nil {
|
||||
target.Panicf("Unable to send UDP packet: %v", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(direct) > 0 {
|
||||
for _, target := range direct {
|
||||
buf[0] = kind | 2
|
||||
target.SendUDP(buf)
|
||||
err := target.SendUDP(buf)
|
||||
if err != nil {
|
||||
target.Panicf("Unable to send UDP packet: %v", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue