Allow regiserting multiple callbacks (closed #4)

This commit is contained in:
ChillerDragon 2024-06-25 09:22:25 +08:00
parent 141865538f
commit 3ecb2a32aa
8 changed files with 198 additions and 274 deletions

View file

@ -60,8 +60,12 @@ func main() {
}) })
// if you do not implement OnError it will throw on error // if you do not implement OnError it will throw on error
client.OnError(func(err error) { client.OnError(func(err error) bool {
fmt.Print(err) fmt.Print(err)
// return false to consume the error
// return true to pass it on to the next error handler (likely throws in the end)
return false
}) })
go func() { go func() {

View file

@ -11,91 +11,117 @@ import (
// It might send a response packet // It might send a response packet
type DefaultAction func() type DefaultAction func()
// Internal method to call user hooks and register default behavior for a given message
// Example:
//
// userMsgCallback(
//
// client.Callbacks.GameSvMotd,
// &messages7.SvMotd{},
// func() { fmt.Println("default action") },
//
// )
func userMsgCallback[T any](userCallbacks []func(T, DefaultAction), msg T, defaultAction DefaultAction) {
if len(userCallbacks) == 0 {
defaultAction()
return
}
for _, callback := range userCallbacks {
callback(msg, defaultAction)
}
}
// TODO: this should be a map but the type checker broke me // TODO: this should be a map but the type checker broke me
// //
// // key is the network7.MessageId // // key is the network7.MessageId
// UserMsgCallbacks map[int]UserMsgCallback // UserMsgCallbacks map[int]UserMsgCallback
type UserMsgCallbacks struct { type UserMsgCallbacks struct {
PacketIn func(*protocol7.Packet) bool // return false to drop the packet
PacketOut func(*protocol7.Packet) bool PacketIn []func(*protocol7.Packet) bool
MsgUnknown func(*messages7.Unknown, DefaultAction) // return false to drop the packet
InternalError func(error) PacketOut []func(*protocol7.Packet) bool
Snapshot func(*snapshot7.Snapshot, DefaultAction) // return false to drop the error (ignore it)
//
// return true to pass the error on and finally throw
InternalError []func(error) bool
MsgUnknown []func(*messages7.Unknown, DefaultAction)
Snapshot []func(*snapshot7.Snapshot, DefaultAction)
CtrlKeepAlive func(*messages7.CtrlKeepAlive, DefaultAction) CtrlKeepAlive []func(*messages7.CtrlKeepAlive, DefaultAction)
CtrlConnect func(*messages7.CtrlConnect, DefaultAction) CtrlConnect []func(*messages7.CtrlConnect, DefaultAction)
CtrlAccept func(*messages7.CtrlAccept, DefaultAction) CtrlAccept []func(*messages7.CtrlAccept, DefaultAction)
CtrlToken func(*messages7.CtrlToken, DefaultAction) CtrlToken []func(*messages7.CtrlToken, DefaultAction)
CtrlClose func(*messages7.CtrlClose, DefaultAction) CtrlClose []func(*messages7.CtrlClose, DefaultAction)
SysInfo func(*messages7.Info, DefaultAction) SysInfo []func(*messages7.Info, DefaultAction)
SysMapChange func(*messages7.MapChange, DefaultAction) SysMapChange []func(*messages7.MapChange, DefaultAction)
SysMapData func(*messages7.MapData, DefaultAction) SysMapData []func(*messages7.MapData, DefaultAction)
SysServerInfo func(*messages7.ServerInfo, DefaultAction) SysServerInfo []func(*messages7.ServerInfo, DefaultAction)
SysConReady func(*messages7.ConReady, DefaultAction) SysConReady []func(*messages7.ConReady, DefaultAction)
SysSnap func(*messages7.Snap, DefaultAction) SysSnap []func(*messages7.Snap, DefaultAction)
SysSnapEmpty func(*messages7.SnapEmpty, DefaultAction) SysSnapEmpty []func(*messages7.SnapEmpty, DefaultAction)
SysSnapSingle func(*messages7.SnapSingle, DefaultAction) SysSnapSingle []func(*messages7.SnapSingle, DefaultAction)
SysSnapSmall func(*messages7.SnapSmall, DefaultAction) SysSnapSmall []func(*messages7.SnapSmall, DefaultAction)
SysInputTiming func(*messages7.InputTiming, DefaultAction) SysInputTiming []func(*messages7.InputTiming, DefaultAction)
SysRconAuthOn func(*messages7.RconAuthOn, DefaultAction) SysRconAuthOn []func(*messages7.RconAuthOn, DefaultAction)
SysRconAuthOff func(*messages7.RconAuthOff, DefaultAction) SysRconAuthOff []func(*messages7.RconAuthOff, DefaultAction)
SysRconLine func(*messages7.RconLine, DefaultAction) SysRconLine []func(*messages7.RconLine, DefaultAction)
SysRconCmdAdd func(*messages7.RconCmdAdd, DefaultAction) SysRconCmdAdd []func(*messages7.RconCmdAdd, DefaultAction)
SysRconCmdRem func(*messages7.RconCmdRem, DefaultAction) SysRconCmdRem []func(*messages7.RconCmdRem, DefaultAction)
SysAuthChallenge func(*messages7.AuthChallenge, DefaultAction) SysAuthChallenge []func(*messages7.AuthChallenge, DefaultAction)
SysAuthResult func(*messages7.AuthResult, DefaultAction) SysAuthResult []func(*messages7.AuthResult, DefaultAction)
SysReady func(*messages7.Ready, DefaultAction) SysReady []func(*messages7.Ready, DefaultAction)
SysEnterGame func(*messages7.EnterGame, DefaultAction) SysEnterGame []func(*messages7.EnterGame, DefaultAction)
SysInput func(*messages7.Input, DefaultAction) SysInput []func(*messages7.Input, DefaultAction)
SysRconCmd func(*messages7.RconCmd, DefaultAction) SysRconCmd []func(*messages7.RconCmd, DefaultAction)
SysRconAuth func(*messages7.RconAuth, DefaultAction) SysRconAuth []func(*messages7.RconAuth, DefaultAction)
SysRequestMapData func(*messages7.RequestMapData, DefaultAction) SysRequestMapData []func(*messages7.RequestMapData, DefaultAction)
SysAuthStart func(*messages7.AuthStart, DefaultAction) SysAuthStart []func(*messages7.AuthStart, DefaultAction)
SysAuthResponse func(*messages7.AuthResponse, DefaultAction) SysAuthResponse []func(*messages7.AuthResponse, DefaultAction)
SysPing func(*messages7.Ping, DefaultAction) SysPing []func(*messages7.Ping, DefaultAction)
SysPingReply func(*messages7.PingReply, DefaultAction) SysPingReply []func(*messages7.PingReply, DefaultAction)
SysError func(*messages7.Error, DefaultAction) SysError []func(*messages7.Error, DefaultAction)
SysMaplistEntryAdd func(*messages7.MaplistEntryAdd, DefaultAction) SysMaplistEntryAdd []func(*messages7.MaplistEntryAdd, DefaultAction)
SysMaplistEntryRem func(*messages7.MaplistEntryRem, DefaultAction) SysMaplistEntryRem []func(*messages7.MaplistEntryRem, DefaultAction)
GameSvMotd func(*messages7.SvMotd, DefaultAction) GameSvMotd []func(*messages7.SvMotd, DefaultAction)
GameSvBroadcast func(*messages7.SvBroadcast, DefaultAction) GameSvBroadcast []func(*messages7.SvBroadcast, DefaultAction)
GameSvChat func(*messages7.SvChat, DefaultAction) GameSvChat []func(*messages7.SvChat, DefaultAction)
GameSvTeam func(*messages7.SvTeam, DefaultAction) GameSvTeam []func(*messages7.SvTeam, DefaultAction)
// GameSvKillMsg func(*messages7.SvKillMsg, DefaultAction) // GameSvKillMsg []func(*messages7.SvKillMsg, DefaultAction)
// GameSvTuneParams func(*messages7.SvTuneParams, DefaultAction) // GameSvTuneParams []func(*messages7.SvTuneParams, DefaultAction)
// GameSvExtraProjectile func(*messages7.SvExtraProjectile, DefaultAction) // GameSvExtraProjectile []func(*messages7.SvExtraProjectile, DefaultAction)
GameReadyToEnter func(*messages7.SvReadyToEnter, DefaultAction) GameSvReadyToEnter []func(*messages7.SvReadyToEnter, DefaultAction)
// GameWeaponPickup func(*messages7.SvWeaponPickup, DefaultAction) // GameWeaponPickup []func(*messages7.SvWeaponPickup, DefaultAction)
// GameEmoticon func(*messages7.SvEmoticon, DefaultAction) // GameEmoticon []func(*messages7.SvEmoticon, DefaultAction)
// GameSvVoteClearoptions func(*messages7.SvVoteClearoptions, DefaultAction) // GameSvVoteClearoptions []func(*messages7.SvVoteClearoptions, DefaultAction)
// GameSvVoteOptionlistadd func(*messages7.SvVoteOptionlistadd, DefaultAction) // GameSvVoteOptionlistadd []func(*messages7.SvVoteOptionlistadd, DefaultAction)
// GameSvVotePptionadd func(*messages7.SvVotePptionadd, DefaultAction) // GameSvVotePptionadd []func(*messages7.SvVotePptionadd, DefaultAction)
// GameSvVoteOptionremove func(*messages7.SvVoteOptionremove, DefaultAction) // GameSvVoteOptionremove []func(*messages7.SvVoteOptionremove, DefaultAction)
// GameSvVoteSet func(*messages7.SvVoteSet, DefaultAction) // GameSvVoteSet []func(*messages7.SvVoteSet, DefaultAction)
// GameSvVoteStatus func(*messages7.SvVoteStatus, DefaultAction) // GameSvVoteStatus []func(*messages7.SvVoteStatus, DefaultAction)
// GameSvServerSettings func(*messages7.SvServerSettings, DefaultAction) // GameSvServerSettings []func(*messages7.SvServerSettings, DefaultAction)
GameSvClientInfo func(*messages7.SvClientInfo, DefaultAction) GameSvClientInfo []func(*messages7.SvClientInfo, DefaultAction)
// GameSvGameInfo func(*messages7.SvGameInfo, DefaultAction) // GameSvGameInfo []func(*messages7.SvGameInfo, DefaultAction)
// GameSvClientDrop func(*messages7.SvClientDrop, DefaultAction) // GameSvClientDrop []func(*messages7.SvClientDrop, DefaultAction)
// GameSvGameMsg func(*messages7.SvGameMsg, DefaultAction) // GameSvGameMsg []func(*messages7.SvGameMsg, DefaultAction)
// GameDeClientEnter func(*messages7.DeClientEnter, DefaultAction) // GameDeClientEnter []func(*messages7.DeClientEnter, DefaultAction)
// GameDeClientLeave func(*messages7.DeClientLeave, DefaultAction) // GameDeClientLeave []func(*messages7.DeClientLeave, DefaultAction)
// GameClSay func(*messages7.ClSay, DefaultAction) // GameClSay []func(*messages7.ClSay, DefaultAction)
// GameClSetTeam func(*messages7.ClSetTeam, DefaultAction) // GameClSetTeam []func(*messages7.ClSetTeam, DefaultAction)
// GameClSetSpectatorMode func(*messages7.ClSetSpectatorMode, DefaultAction) // GameClSetSpectatorMode []func(*messages7.ClSetSpectatorMode, DefaultAction)
GameClStartInfo func(*messages7.ClStartInfo, DefaultAction) GameClStartInfo []func(*messages7.ClStartInfo, DefaultAction)
// GameClKill func(*messages7.ClKill, DefaultAction) // GameClKill []func(*messages7.ClKill, DefaultAction)
// GameClReadyChange func(*messages7.ClReadyChange, DefaultAction) // GameClReadyChange []func(*messages7.ClReadyChange, DefaultAction)
// GameClEmoticon func(*messages7.ClEmoticon, DefaultAction) // GameClEmoticon []func(*messages7.ClEmoticon, DefaultAction)
// GameClVote func(*messages7.ClVote, DefaultAction) // GameClVote []func(*messages7.ClVote, DefaultAction)
// GameClCallVote func(*messages7.ClCallVote, DefaultAction) // GameClCallVote []func(*messages7.ClCallVote, DefaultAction)
// GameSvSkinChange func(*messages7.SvSkinChange, DefaultAction) // GameSvSkinChange []func(*messages7.SvSkinChange, DefaultAction)
// GameClSkinChange func(*messages7.ClSkinChange, DefaultAction) // GameClSkinChange []func(*messages7.ClSkinChange, DefaultAction)
// GameSvRaceFinish func(*messages7.SvRaceFinish, DefaultAction) // GameSvRaceFinish []func(*messages7.SvRaceFinish, DefaultAction)
// GameSvCheckpoint func(*messages7.SvCheckpoint, DefaultAction) // GameSvCheckpoint []func(*messages7.SvCheckpoint, DefaultAction)
// GameSvCommandInfo func(*messages7.SvCommandInfo, DefaultAction) // GameSvCommandInfo []func(*messages7.SvCommandInfo, DefaultAction)
// GameSvCommandInfoRemove func(*messages7.SvCommandInfoRemove, DefaultAction) // GameSvCommandInfoRemove []func(*messages7.SvCommandInfoRemove, DefaultAction)
// GameClCommand func(*messages7.ClCommand, DefaultAction) // GameClCommand []func(*messages7.ClCommand, DefaultAction)
} }

View file

@ -39,9 +39,11 @@ type Client struct {
} }
func (client *Client) throwError(err error) { func (client *Client) throwError(err error) {
if client.Callbacks.InternalError != nil { for _, callback := range client.Callbacks.InternalError {
client.Callbacks.InternalError(err) if callback(err) == false {
return return
} }
}
log.Fatal(err) log.Fatal(err)
} }

View file

@ -11,70 +11,40 @@ import (
func (client *Client) processGame(netMsg messages7.NetMessage, response *protocol7.Packet) bool { func (client *Client) processGame(netMsg messages7.NetMessage, response *protocol7.Packet) bool {
switch msg := netMsg.(type) { switch msg := netMsg.(type) {
case *messages7.SvMotd: case *messages7.SvMotd:
defaultAction := func() { userMsgCallback(client.Callbacks.GameSvMotd, msg, func() {
if msg.Message != "" { if msg.Message != "" {
fmt.Printf("[motd] %s\n", msg.Message) fmt.Printf("[motd] %s\n", msg.Message)
} }
} })
if client.Callbacks.GameSvMotd == nil {
defaultAction()
} else {
client.Callbacks.GameSvMotd(msg, defaultAction)
}
case *messages7.SvBroadcast: case *messages7.SvBroadcast:
defaultAction := func() { userMsgCallback(client.Callbacks.GameSvBroadcast, msg, func() {
fmt.Printf("[broadcast] %s\n", msg.Message) fmt.Printf("[broadcast] %s\n", msg.Message)
} })
if client.Callbacks.GameSvBroadcast == nil {
defaultAction()
} else {
client.Callbacks.GameSvBroadcast(msg, defaultAction)
}
case *messages7.SvChat: case *messages7.SvChat:
defaultAction := func() { userMsgCallback(client.Callbacks.GameSvChat, msg, func() {
if msg.ClientId < 0 || msg.ClientId > network7.MaxClients { if msg.ClientId < 0 || msg.ClientId > network7.MaxClients {
fmt.Printf("[chat] *** %s\n", msg.Message) fmt.Printf("[chat] *** %s\n", msg.Message)
return return
} }
name := client.Game.Players[msg.ClientId].Info.Name name := client.Game.Players[msg.ClientId].Info.Name
fmt.Printf("[chat] <%s> %s\n", name, msg.Message) fmt.Printf("[chat] <%s> %s\n", name, msg.Message)
} })
if client.Callbacks.GameSvChat == nil {
defaultAction()
} else {
client.Callbacks.GameSvChat(msg, defaultAction)
}
case *messages7.SvClientInfo: case *messages7.SvClientInfo:
defaultAction := func() { userMsgCallback(client.Callbacks.GameSvClientInfo, msg, func() {
client.Game.Players[msg.ClientId].Info = *msg client.Game.Players[msg.ClientId].Info = *msg
fmt.Printf("got client info id=%d name=%s\n", msg.ClientId, msg.Name) fmt.Printf("got client info id=%d name=%s\n", msg.ClientId, msg.Name)
} })
if client.Callbacks.GameSvClientInfo == nil {
defaultAction()
} else {
client.Callbacks.GameSvClientInfo(msg, defaultAction)
}
case *messages7.SvReadyToEnter: case *messages7.SvReadyToEnter:
defaultAction := func() { userMsgCallback(client.Callbacks.GameSvReadyToEnter, msg, func() {
fmt.Println("got ready to enter") fmt.Println("got ready to enter")
response.Messages = append(response.Messages, &messages7.EnterGame{}) response.Messages = append(response.Messages, &messages7.EnterGame{})
} })
if client.Callbacks.GameReadyToEnter == nil {
defaultAction()
} else {
client.Callbacks.GameReadyToEnter(msg, defaultAction)
}
case *messages7.Unknown: case *messages7.Unknown:
defaultAction := func() { userMsgCallback(client.Callbacks.MsgUnknown, msg, func() {
// TODO: msg id of unknown messages should not be -1 // TODO: msg id of unknown messages should not be -1
fmt.Println("TODO: why is the msg id -1???") fmt.Println("TODO: why is the msg id -1???")
printUnknownMessage(msg, "unknown game") printUnknownMessage(msg, "unknown game")
} })
if client.Callbacks.MsgUnknown == nil {
defaultAction()
} else {
client.Callbacks.MsgUnknown(msg, defaultAction)
}
default: default:
printUnknownMessage(netMsg, "unprocessed game") printUnknownMessage(netMsg, "unprocessed game")
return false return false

View file

@ -38,8 +38,8 @@ func (client *Client) processMessage(msg messages7.NetMessage, response *protoco
} }
func (client *Client) processPacket(packet *protocol7.Packet) error { func (client *Client) processPacket(packet *protocol7.Packet) error {
if client.Callbacks.PacketIn != nil { for _, callback := range client.Callbacks.PacketIn {
if client.Callbacks.PacketIn(packet) == false { if callback(packet) == false {
return nil return nil
} }
} }
@ -55,26 +55,16 @@ func (client *Client) processPacket(packet *protocol7.Packet) error {
// TODO: is this shadow nasty? // TODO: is this shadow nasty?
switch msg := msg.(type) { switch msg := msg.(type) {
case *messages7.CtrlKeepAlive: case *messages7.CtrlKeepAlive:
defaultAction := func() { userMsgCallback(client.Callbacks.CtrlKeepAlive, msg, func() {
fmt.Println("got keep alive") fmt.Println("got keep alive")
} })
if client.Callbacks.CtrlKeepAlive == nil {
defaultAction()
} else {
client.Callbacks.CtrlKeepAlive(msg, defaultAction)
}
case *messages7.CtrlConnect: case *messages7.CtrlConnect:
defaultAction := func() { userMsgCallback(client.Callbacks.CtrlConnect, msg, func() {
fmt.Println("we got connect as a client. this should never happen lol.") fmt.Println("we got connect as a client. this should never happen lol.")
fmt.Println("who is tryint to connect to us? We are not a server!") fmt.Println("who is tryint to connect to us? We are not a server!")
} })
if client.Callbacks.CtrlConnect == nil {
defaultAction()
} else {
client.Callbacks.CtrlConnect(msg, defaultAction)
}
case *messages7.CtrlAccept: case *messages7.CtrlAccept:
defaultAction := func() { userMsgCallback(client.Callbacks.CtrlAccept, msg, func() {
fmt.Println("got accept") fmt.Println("got accept")
response.Messages = append( response.Messages = append(
response.Messages, response.Messages,
@ -85,23 +75,13 @@ func (client *Client) processPacket(packet *protocol7.Packet) error {
}, },
) )
client.SendPacket(response) client.SendPacket(response)
} })
if client.Callbacks.CtrlAccept == nil {
defaultAction()
} else {
client.Callbacks.CtrlAccept(msg, defaultAction)
}
case *messages7.CtrlClose: case *messages7.CtrlClose:
defaultAction := func() { userMsgCallback(client.Callbacks.CtrlClose, msg, func() {
fmt.Printf("disconnected (%s)\n", msg.Reason) fmt.Printf("disconnected (%s)\n", msg.Reason)
} })
if client.Callbacks.CtrlClose == nil {
defaultAction()
} else {
client.Callbacks.CtrlClose(msg, defaultAction)
}
case *messages7.CtrlToken: case *messages7.CtrlToken:
defaultAction := func() { userMsgCallback(client.Callbacks.CtrlToken, msg, func() {
fmt.Printf("got server token %x\n", msg.Token) fmt.Printf("got server token %x\n", msg.Token)
client.Session.ServerToken = msg.Token client.Session.ServerToken = msg.Token
response.Header.Token = msg.Token response.Header.Token = msg.Token
@ -112,21 +92,11 @@ func (client *Client) processPacket(packet *protocol7.Packet) error {
}, },
) )
client.SendPacket(response) client.SendPacket(response)
} })
if client.Callbacks.CtrlToken == nil {
defaultAction()
} else {
client.Callbacks.CtrlToken(msg, defaultAction)
}
case *messages7.Unknown: case *messages7.Unknown:
defaultAction := func() { userMsgCallback(client.Callbacks.MsgUnknown, msg, func() {
printUnknownMessage(msg, "unknown control") printUnknownMessage(msg, "unknown control")
} })
if client.Callbacks.MsgUnknown == nil {
defaultAction()
} else {
client.Callbacks.MsgUnknown(msg, defaultAction)
}
return fmt.Errorf("unknown control message: %d\n", msg.MsgId()) return fmt.Errorf("unknown control message: %d\n", msg.MsgId())
default: default:
return fmt.Errorf("unprocessed control message: %d\n", msg.MsgId()) return fmt.Errorf("unprocessed control message: %d\n", msg.MsgId())

View file

@ -10,35 +10,20 @@ import (
func (client *Client) processSystem(netMsg messages7.NetMessage, response *protocol7.Packet) bool { func (client *Client) processSystem(netMsg messages7.NetMessage, response *protocol7.Packet) bool {
switch msg := netMsg.(type) { switch msg := netMsg.(type) {
case *messages7.MapChange: case *messages7.MapChange:
defaultAction := func() { userMsgCallback(client.Callbacks.SysMapChange, msg, func() {
fmt.Println("got map change") fmt.Println("got map change")
response.Messages = append(response.Messages, &messages7.Ready{}) response.Messages = append(response.Messages, &messages7.Ready{})
} })
if client.Callbacks.SysMapChange == nil {
defaultAction()
} else {
client.Callbacks.SysMapChange(msg, defaultAction)
}
case *messages7.MapData: case *messages7.MapData:
defaultAction := func() { userMsgCallback(client.Callbacks.SysMapData, msg, func() {
fmt.Printf("got map chunk %x\n", msg.Data) fmt.Printf("got map chunk %x\n", msg.Data)
} })
if client.Callbacks.SysMapData == nil {
defaultAction()
} else {
client.Callbacks.SysMapData(msg, defaultAction)
}
case *messages7.ServerInfo: case *messages7.ServerInfo:
defaultAction := func() { userMsgCallback(client.Callbacks.SysServerInfo, msg, func() {
fmt.Printf("connected to server with name '%s'\n", msg.Name) fmt.Printf("connected to server with name '%s'\n", msg.Name)
} })
if client.Callbacks.SysServerInfo == nil {
defaultAction()
} else {
client.Callbacks.SysServerInfo(msg, defaultAction)
}
case *messages7.ConReady: case *messages7.ConReady:
defaultAction := func() { userMsgCallback(client.Callbacks.SysConReady, msg, func() {
fmt.Println("connected, sending info") fmt.Println("connected, sending info")
info := &messages7.ClStartInfo{ info := &messages7.ClStartInfo{
Name: client.Name, Name: client.Name,
@ -64,86 +49,49 @@ func (client *Client) processSystem(netMsg messages7.NetMessage, response *proto
ColorEyes: 0, ColorEyes: 0,
} }
response.Messages = append(response.Messages, info) response.Messages = append(response.Messages, info)
} })
if client.Callbacks.SysConReady == nil {
defaultAction()
} else {
client.Callbacks.SysConReady(msg, defaultAction)
}
case *messages7.Snap: case *messages7.Snap:
// fmt.Printf("got snap tick=%d\n", msg.GameTick) userMsgCallback(client.Callbacks.SysSnap, msg, func() {
response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{}) response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{})
})
case *messages7.SnapSingle: case *messages7.SnapSingle:
// fmt.Printf("got snap single tick=%d\n", msg.GameTick) userMsgCallback(client.Callbacks.SysSnapSingle, msg, func() {
response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{}) response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{})
})
case *messages7.SnapEmpty: case *messages7.SnapEmpty:
// fmt.Printf("got snap empty tick=%d\n", msg.GameTick) userMsgCallback(client.Callbacks.SysSnapEmpty, msg, func() {
response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{}) response.Messages = append(response.Messages, &messages7.CtrlKeepAlive{})
})
case *messages7.InputTiming: case *messages7.InputTiming:
defaultAction := func() { userMsgCallback(client.Callbacks.SysInputTiming, msg, func() {
fmt.Printf("timing time left=%d\n", msg.TimeLeft) fmt.Printf("timing time left=%d\n", msg.TimeLeft)
} })
if client.Callbacks.SysInputTiming == nil {
defaultAction()
} else {
client.Callbacks.SysInputTiming(msg, defaultAction)
}
case *messages7.RconAuthOn: case *messages7.RconAuthOn:
defaultAction := func() { userMsgCallback(client.Callbacks.SysRconAuthOn, msg, func() {
fmt.Println("you are now authenticated in rcon") fmt.Println("you are now authenticated in rcon")
} })
if client.Callbacks.SysRconAuthOn == nil {
defaultAction()
} else {
client.Callbacks.SysRconAuthOn(msg, defaultAction)
}
case *messages7.RconAuthOff: case *messages7.RconAuthOff:
defaultAction := func() { userMsgCallback(client.Callbacks.SysRconAuthOff, msg, func() {
fmt.Println("you are no longer authenticated in rcon") fmt.Println("you are no longer authenticated in rcon")
} })
if client.Callbacks.SysRconAuthOff == nil {
defaultAction()
} else {
client.Callbacks.SysRconAuthOff(msg, defaultAction)
}
case *messages7.RconLine: case *messages7.RconLine:
defaultAction := func() { userMsgCallback(client.Callbacks.SysRconLine, msg, func() {
fmt.Printf("[rcon] %s\n", msg.Line) fmt.Printf("[rcon] %s\n", msg.Line)
} })
if client.Callbacks.SysRconLine == nil {
defaultAction()
} else {
client.Callbacks.SysRconLine(msg, defaultAction)
}
case *messages7.RconCmdAdd: case *messages7.RconCmdAdd:
defaultAction := func() { userMsgCallback(client.Callbacks.SysRconCmdAdd, msg, func() {
fmt.Printf("got rcon cmd=%s %s %s\n", msg.Name, msg.Params, msg.Help) fmt.Printf("got rcon cmd=%s %s %s\n", msg.Name, msg.Params, msg.Help)
} })
if client.Callbacks.SysRconCmdAdd == nil {
defaultAction()
} else {
client.Callbacks.SysRconCmdAdd(msg, defaultAction)
}
case *messages7.RconCmdRem: case *messages7.RconCmdRem:
defaultAction := func() { userMsgCallback(client.Callbacks.SysRconCmdRem, msg, func() {
fmt.Printf("removed cmd=%s\n", msg.Name) fmt.Printf("removed cmd=%s\n", msg.Name)
} })
if client.Callbacks.SysRconCmdRem == nil {
defaultAction()
} else {
client.Callbacks.SysRconCmdRem(msg, defaultAction)
}
case *messages7.Unknown: case *messages7.Unknown:
defaultAction := func() { userMsgCallback(client.Callbacks.MsgUnknown, msg, func() {
// TODO: msg id of unknown messages should not be -1 // TODO: msg id of unknown messages should not be -1
fmt.Println("TODO: why is the msg id -1???") fmt.Println("TODO: why is the msg id -1???")
printUnknownMessage(msg, "unknown system") printUnknownMessage(msg, "unknown system")
} })
if client.Callbacks.MsgUnknown == nil {
defaultAction()
} else {
client.Callbacks.MsgUnknown(msg, defaultAction)
}
default: default:
printUnknownMessage(netMsg, "unprocessed system") printUnknownMessage(netMsg, "unprocessed system")
return false return false

View file

@ -62,11 +62,12 @@ func (client *Client) SendPacket(packet *protocol7.Packet) error {
} }
client.QueuedMessages = nil client.QueuedMessages = nil
if client.Callbacks.PacketOut != nil { for _, callback := range client.Callbacks.PacketOut {
if client.Callbacks.PacketOut(packet) == false { if callback(packet) == false {
return nil return nil
} }
} }
client.Conn.Write(packet.Pack(&client.Session)) client.Conn.Write(packet.Pack(&client.Session))
return nil return nil
} }

View file

@ -11,8 +11,11 @@ import (
// -------------------------------- // --------------------------------
// if not implemented by the user the application might throw and exit // if not implemented by the user the application might throw and exit
func (client *Client) OnError(callback func(err error)) { //
client.Callbacks.InternalError = callback // return false to drop the error
// return true if you did not handle the error and it should be passed on (will crash unless someone else catches it)
func (client *Client) OnError(callback func(err error) bool) {
client.Callbacks.InternalError = append(client.Callbacks.InternalError, callback)
} }
// inspect outgoing traffic // inspect outgoing traffic
@ -20,7 +23,7 @@ func (client *Client) OnError(callback func(err error)) {
// //
// return false to drop the packet // return false to drop the packet
func (client *Client) OnSend(callback func(packet *protocol7.Packet) bool) { func (client *Client) OnSend(callback func(packet *protocol7.Packet) bool) {
client.Callbacks.PacketOut = callback client.Callbacks.PacketOut = append(client.Callbacks.PacketOut, callback)
} }
// read incoming traffic // read incoming traffic
@ -28,17 +31,17 @@ func (client *Client) OnSend(callback func(packet *protocol7.Packet) bool) {
// //
// return false to drop the packet // return false to drop the packet
func (client *Client) OnPacket(callback func(packet *protocol7.Packet) bool) { func (client *Client) OnPacket(callback func(packet *protocol7.Packet) bool) {
client.Callbacks.PacketIn = callback client.Callbacks.PacketIn = append(client.Callbacks.PacketIn, callback)
} }
func (client *Client) OnUnknown(callback func(msg *messages7.Unknown, defaultAction DefaultAction)) { func (client *Client) OnUnknown(callback func(msg *messages7.Unknown, defaultAction DefaultAction)) {
client.Callbacks.MsgUnknown = callback client.Callbacks.MsgUnknown = append(client.Callbacks.MsgUnknown, callback)
} }
// will be called when a snap, snap single or empty snapshot is received // will be called when a snap, snap single or empty snapshot is received
// if you want to know which type of snapshot was received look at OnMsgSnap(), OnMsgSnapEmpty(), OnMsgSnapSingle(), OnMsgSnapSmall() // if you want to know which type of snapshot was received look at OnMsgSnap(), OnMsgSnapEmpty(), OnMsgSnapSingle(), OnMsgSnapSmall()
func (client *Client) OnSnapshot(callback func(snap *snapshot7.Snapshot, defaultAction DefaultAction)) { func (client *Client) OnSnapshot(callback func(snap *snapshot7.Snapshot, defaultAction DefaultAction)) {
client.Callbacks.Snapshot = callback client.Callbacks.Snapshot = append(client.Callbacks.Snapshot, callback)
} }
// -------------------------------- // --------------------------------
@ -46,24 +49,24 @@ func (client *Client) OnSnapshot(callback func(snap *snapshot7.Snapshot, default
// -------------------------------- // --------------------------------
func (client *Client) OnKeepAlive(callback func(msg *messages7.CtrlKeepAlive, defaultAction DefaultAction)) { func (client *Client) OnKeepAlive(callback func(msg *messages7.CtrlKeepAlive, defaultAction DefaultAction)) {
client.Callbacks.CtrlKeepAlive = callback client.Callbacks.CtrlKeepAlive = append(client.Callbacks.CtrlKeepAlive, callback)
} }
// This is just misleading. It should never be called. This message is only received by the server. // This is just misleading. It should never be called. This message is only received by the server.
// func (client *Client) OnCtrlConnect(callback func(msg *messages7.CtrlConnect, defaultAction DefaultAction)) { // func (client *Client) OnCtrlConnect(callback func(msg *messages7.CtrlConnect, defaultAction DefaultAction)) {
// client.Callbacks.CtrlConnect = callback // client.Callbacks.CtrlConnect = append(// client.Callbacks, callback)
// } // }
func (client *Client) OnAccept(callback func(msg *messages7.CtrlAccept, defaultAction DefaultAction)) { func (client *Client) OnAccept(callback func(msg *messages7.CtrlAccept, defaultAction DefaultAction)) {
client.Callbacks.CtrlAccept = callback client.Callbacks.CtrlAccept = append(client.Callbacks.CtrlAccept, callback)
} }
func (client *Client) OnDisconnect(callback func(msg *messages7.CtrlClose, defaultAction DefaultAction)) { func (client *Client) OnDisconnect(callback func(msg *messages7.CtrlClose, defaultAction DefaultAction)) {
client.Callbacks.CtrlClose = callback client.Callbacks.CtrlClose = append(client.Callbacks.CtrlClose, callback)
} }
func (client *Client) OnToken(callback func(msg *messages7.CtrlToken, defaultAction DefaultAction)) { func (client *Client) OnToken(callback func(msg *messages7.CtrlToken, defaultAction DefaultAction)) {
client.Callbacks.CtrlToken = callback client.Callbacks.CtrlToken = append(client.Callbacks.CtrlToken, callback)
} }
// -------------------------------- // --------------------------------
@ -71,19 +74,19 @@ func (client *Client) OnToken(callback func(msg *messages7.CtrlToken, defaultAct
// -------------------------------- // --------------------------------
func (client *Client) OnMotd(callback func(msg *messages7.SvMotd, defaultAction DefaultAction)) { func (client *Client) OnMotd(callback func(msg *messages7.SvMotd, defaultAction DefaultAction)) {
client.Callbacks.GameSvMotd = callback client.Callbacks.GameSvMotd = append(client.Callbacks.GameSvMotd, callback)
} }
func (client *Client) OnBroadcast(callback func(msg *messages7.SvBroadcast, defaultAction DefaultAction)) { func (client *Client) OnBroadcast(callback func(msg *messages7.SvBroadcast, defaultAction DefaultAction)) {
client.Callbacks.GameSvBroadcast = callback client.Callbacks.GameSvBroadcast = append(client.Callbacks.GameSvBroadcast, callback)
} }
func (client *Client) OnChat(callback func(msg *messages7.SvChat, defaultAction DefaultAction)) { func (client *Client) OnChat(callback func(msg *messages7.SvChat, defaultAction DefaultAction)) {
client.Callbacks.GameSvChat = callback client.Callbacks.GameSvChat = append(client.Callbacks.GameSvChat, callback)
} }
func (client *Client) OnTeam(callback func(msg *messages7.SvTeam, defaultAction DefaultAction)) { func (client *Client) OnTeam(callback func(msg *messages7.SvTeam, defaultAction DefaultAction)) {
client.Callbacks.GameSvTeam = callback client.Callbacks.GameSvTeam = append(client.Callbacks.GameSvTeam, callback)
} }
// -------------------------------- // --------------------------------
@ -91,25 +94,25 @@ func (client *Client) OnTeam(callback func(msg *messages7.SvTeam, defaultAction
// -------------------------------- // --------------------------------
func (client *Client) OnMapChange(callback func(msg *messages7.MapChange, defaultAction DefaultAction)) { func (client *Client) OnMapChange(callback func(msg *messages7.MapChange, defaultAction DefaultAction)) {
client.Callbacks.SysMapChange = callback client.Callbacks.SysMapChange = append(client.Callbacks.SysMapChange, callback)
} }
// You probably want to use OnSnapshot() instead // You probably want to use OnSnapshot() instead
func (client *Client) OnMsgSnap(callback func(msg *messages7.Snap, defaultAction DefaultAction)) { func (client *Client) OnMsgSnap(callback func(msg *messages7.Snap, defaultAction DefaultAction)) {
client.Callbacks.SysSnap = callback client.Callbacks.SysSnap = append(client.Callbacks.SysSnap, callback)
} }
// You probably want to use OnSnapshot() instead // You probably want to use OnSnapshot() instead
func (client *Client) OnMsgSnapEmpty(callback func(msg *messages7.SnapEmpty, defaultAction DefaultAction)) { func (client *Client) OnMsgSnapEmpty(callback func(msg *messages7.SnapEmpty, defaultAction DefaultAction)) {
client.Callbacks.SysSnapEmpty = callback client.Callbacks.SysSnapEmpty = append(client.Callbacks.SysSnapEmpty, callback)
} }
// You probably want to use OnSnapshot() instead // You probably want to use OnSnapshot() instead
func (client *Client) OnMsgSnapSingle(callback func(msg *messages7.SnapSingle, defaultAction DefaultAction)) { func (client *Client) OnMsgSnapSingle(callback func(msg *messages7.SnapSingle, defaultAction DefaultAction)) {
client.Callbacks.SysSnapSingle = callback client.Callbacks.SysSnapSingle = append(client.Callbacks.SysSnapSingle, callback)
} }
// You probably want to use OnSnapshot() instead // You probably want to use OnSnapshot() instead
func (client *Client) OnMsgSnapSmall(callback func(msg *messages7.SnapSmall, defaultAction DefaultAction)) { func (client *Client) OnMsgSnapSmall(callback func(msg *messages7.SnapSmall, defaultAction DefaultAction)) {
client.Callbacks.SysSnapSmall = callback client.Callbacks.SysSnapSmall = append(client.Callbacks.SysSnapSmall, callback)
} }