multiserver/chat.go

216 lines
4.9 KiB
Go
Raw Normal View History

2021-01-14 04:40:31 -08:00
package multiserver
import (
"encoding/binary"
"log"
"strings"
"time"
"unicode/utf16"
)
type chatCommand struct {
privs map[string]bool
function func(*Peer, string)
}
var chatCommands map[string]chatCommand
2021-01-14 08:09:06 -08:00
var onChatMsg []func(*Peer, string) bool
2021-01-14 04:40:31 -08:00
2021-01-17 02:08:34 -08:00
var serverChatCommands map[string]func(*Peer, string)
var onServerChatMsg []func(*Peer, string) bool
2021-01-14 07:27:42 -08:00
func RegisterChatCommand(name string, privs map[string]bool, function func(*Peer, string)) {
2021-01-14 04:40:31 -08:00
chatCommands[name] = chatCommand{privs: privs, function: function}
}
2021-01-17 02:08:34 -08:00
func RegisterOnChatMessage(function func(*Peer, string) bool) {
2021-01-14 04:40:31 -08:00
onChatMsg = append(onChatMsg, function)
}
2021-01-17 02:08:34 -08:00
func RegisterServerChatCommand(name string, function func(*Peer, string)) {
serverChatCommands[name] = function
}
func RegisterOnServerChatMessage(function func(*Peer, string) bool) {
onServerChatMsg = append(onServerChatMsg, function)
}
2021-01-14 04:40:31 -08:00
func processChatMessage(p *Peer, pkt Pkt) bool {
s := string(narrow(pkt.Data[4:]))
if strings.HasPrefix(s, "#") {
// Chat command
s = strings.Replace(s, "#", "", 1)
params := strings.Split(s, " ")
// Priv check
2021-01-14 11:18:58 -08:00
allow, err := p.CheckPrivs(chatCommands[params[0]].privs)
2021-01-14 04:40:31 -08:00
if err != nil {
log.Print(err)
return true
}
if !allow {
str := "You do not have permission to run this command! Required privileges: " + strings.Replace(encodePrivs(chatCommands[params[0]].privs), "|", " ", -1)
wstr := wider([]byte(str))
data := make([]byte, 16+len(wstr))
data[0] = uint8(0x00)
data[1] = uint8(ToClientChatMessage)
data[2] = uint8(0x01)
data[3] = uint8(0x00)
data[4] = uint8(0x00)
data[5] = uint8(0x00)
binary.BigEndian.PutUint16(data[6:8], uint16(len(str)))
copy(data[8:8+len(wstr)], wstr)
data[8+len(wstr)] = uint8(0x00)
data[9+len(wstr)] = uint8(0x00)
data[10+len(wstr)] = uint8(0x00)
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(Pkt{Data: data})
if err != nil {
log.Print(err)
}
<-ack
return true
}
// Callback
2021-01-14 08:21:24 -08:00
// Existance check
if chatCommands[params[0]].function == nil {
str := "Unknown command " + params[0] + "."
wstr := wider([]byte(str))
data := make([]byte, 16+len(wstr))
data[0] = uint8(0x00)
data[1] = uint8(ToClientChatMessage)
data[2] = uint8(0x01)
data[3] = uint8(0x00)
data[4] = uint8(0x00)
data[5] = uint8(0x00)
binary.BigEndian.PutUint16(data[6:8], uint16(len(str)))
copy(data[8:8+len(wstr)], wstr)
data[8+len(wstr)] = uint8(0x00)
data[9+len(wstr)] = uint8(0x00)
data[10+len(wstr)] = uint8(0x00)
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(Pkt{Data: data})
if err != nil {
log.Print(err)
}
<-ack
return true
}
2021-01-14 04:40:31 -08:00
chatCommands[params[0]].function(p, strings.Join(params[1:], " "))
return true
} else {
// Regular message
2021-01-14 13:08:01 -08:00
noforward := false
2021-01-14 04:40:31 -08:00
for i := range onChatMsg {
if onChatMsg[i](p, s) {
2021-01-14 13:08:01 -08:00
noforward = true
2021-01-14 04:40:31 -08:00
}
}
2021-01-14 13:08:01 -08:00
return noforward
2021-01-14 04:40:31 -08:00
}
}
2021-01-17 02:08:34 -08:00
func processServerChatMessage(p *Peer, pkt Pkt) bool {
s := string(narrow(pkt.Data[4:]))
if strings.HasPrefix(s, ":") {
// Server chat command
s = strings.Replace(s, ":", "", 1)
params := strings.Split(s, " ")
// Callback
// Existance check
if serverChatCommands[params[0]] == nil {
return true
}
serverChatCommands[params[0]](p, strings.Join(params[1:], " "))
return true
} else {
// Regular message
noforward := false
for i := range onServerChatMsg {
if onServerChatMsg[i](p, s) {
noforward = true
}
}
return noforward
}
}
2021-01-14 07:27:42 -08:00
func (p *Peer) SendChatMsg(msg string) {
2021-01-14 04:40:31 -08:00
wstr := wider([]byte(msg))
data := make([]byte, 16+len(wstr))
data[0] = uint8(0x00)
data[1] = uint8(ToClientChatMessage)
data[2] = uint8(0x01)
data[3] = uint8(0x00)
data[4] = uint8(0x00)
data[5] = uint8(0x00)
binary.BigEndian.PutUint16(data[6:8], uint16(len(msg)))
copy(data[8:8+len(wstr)], wstr)
data[8+len(wstr)] = uint8(0x00)
data[9+len(wstr)] = uint8(0x00)
data[10+len(wstr)] = uint8(0x00)
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(Pkt{Data: data})
if err != nil {
log.Print(err)
}
<-ack
}
2021-01-14 07:27:42 -08:00
func ChatSendAll(msg string) {
2021-01-14 04:40:31 -08:00
l := GetListener()
l.mu.Lock()
defer l.mu.Unlock()
for i := range l.addr2peer {
2021-01-14 10:55:12 -08:00
go l.addr2peer[i].SendChatMsg(msg)
2021-01-14 04:40:31 -08:00
}
}
func narrow(b []byte) []byte {
if len(b)%2 != 0 {
return nil
}
e := make([]uint16, len(b)/2)
for i := 0; i < len(b); i += 2 {
e[i/2] = binary.BigEndian.Uint16(b[i : 2+i])
}
return []byte(string(utf16.Decode(e)))
}
func wider(b []byte) []byte {
r := make([]byte, len(b)*2)
e := utf16.Encode([]rune(string(b)))
for i := range e {
binary.BigEndian.PutUint16(r[i*2:2+i*2], e[i])
}
return r
}
2021-01-14 10:06:40 -08:00
func init() {
chatCommands = make(map[string]chatCommand)
2021-01-17 02:08:34 -08:00
serverChatCommands = make(map[string]func(*Peer, string))
2021-01-14 10:06:40 -08:00
}