90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
|
|
package chat
|
||
|
|
|
||
|
|
import (
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"sync"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Global represents a global chat. Players will write in this chat by default
|
||
|
|
// when they send any message in the chat.
|
||
|
|
var Global = New()
|
||
|
|
|
||
|
|
// Chat represents the in-game chat. Messages may be written to it to send a
|
||
|
|
// message to all subscribers.
|
||
|
|
// Methods on Chat may be called from multiple goroutines concurrently. Chat
|
||
|
|
// implements the io.Writer and io.StringWriter interfaces. fmt.Fprintf and
|
||
|
|
// fmt.Fprint may be used to write formatted messages to the chat.
|
||
|
|
type Chat struct {
|
||
|
|
m sync.Mutex
|
||
|
|
subscribers map[uuid.UUID]Subscriber
|
||
|
|
}
|
||
|
|
|
||
|
|
// New returns a new chat.
|
||
|
|
func New() *Chat {
|
||
|
|
return &Chat{subscribers: map[uuid.UUID]Subscriber{}}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Write writes the byte slice p as a string to the chat. It is equivalent to
|
||
|
|
// calling Chat.WriteString(string(p)).
|
||
|
|
func (chat *Chat) Write(p []byte) (n int, err error) {
|
||
|
|
return chat.WriteString(string(p))
|
||
|
|
}
|
||
|
|
|
||
|
|
// WriteString writes a string s to the chat.
|
||
|
|
func (chat *Chat) WriteString(s string) (n int, err error) {
|
||
|
|
chat.m.Lock()
|
||
|
|
defer chat.m.Unlock()
|
||
|
|
for _, subscriber := range chat.subscribers {
|
||
|
|
subscriber.Message(s)
|
||
|
|
}
|
||
|
|
return len(s), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Writet writes a Translation message to a Chat, parameterising the message
|
||
|
|
// using the arguments passed. Messages are translated according to the locale
|
||
|
|
// of subscribers if they implement Translator. Subscribers that do not
|
||
|
|
// implement Translator have the fallback message sent.
|
||
|
|
func (chat *Chat) Writet(t Translation, a ...any) {
|
||
|
|
chat.m.Lock()
|
||
|
|
defer chat.m.Unlock()
|
||
|
|
for _, subscriber := range chat.subscribers {
|
||
|
|
if translator, ok := subscriber.(Translator); ok {
|
||
|
|
translator.Messaget(t, a...)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
subscriber.Message(t.F(a...).String())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Subscribe adds a subscriber to the chat, sending it every message written to
|
||
|
|
// the chat. In order to remove it again, use Chat.Unsubscribe().
|
||
|
|
func (chat *Chat) Subscribe(s Subscriber) {
|
||
|
|
chat.m.Lock()
|
||
|
|
defer chat.m.Unlock()
|
||
|
|
chat.subscribers[s.UUID()] = s
|
||
|
|
}
|
||
|
|
|
||
|
|
// Subscribed checks if a subscriber is currently subscribed to the chat.
|
||
|
|
func (chat *Chat) Subscribed(s Subscriber) bool {
|
||
|
|
chat.m.Lock()
|
||
|
|
defer chat.m.Unlock()
|
||
|
|
_, ok := chat.subscribers[s.UUID()]
|
||
|
|
return ok
|
||
|
|
}
|
||
|
|
|
||
|
|
// Unsubscribe removes a subscriber from the chat, so that messages written to
|
||
|
|
// the chat will no longer be sent to it.
|
||
|
|
func (chat *Chat) Unsubscribe(s Subscriber) {
|
||
|
|
chat.m.Lock()
|
||
|
|
defer chat.m.Unlock()
|
||
|
|
delete(chat.subscribers, s.UUID())
|
||
|
|
}
|
||
|
|
|
||
|
|
// Close closes the chat, removing all subscribers from it.
|
||
|
|
func (chat *Chat) Close() error {
|
||
|
|
chat.m.Lock()
|
||
|
|
chat.subscribers = nil
|
||
|
|
chat.m.Unlock()
|
||
|
|
return nil
|
||
|
|
}
|