322 lines
9.0 KiB
Go
322 lines
9.0 KiB
Go
package serverCommunication
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/gofiber/websocket/v2"
|
|
"krakatoa.net/backend/modules/cache"
|
|
"krakatoa.net/backend/modules/kraProtocol"
|
|
"krakatoa.net/backend/modules/logger"
|
|
"krakatoa.net/backend/modules/structs"
|
|
)
|
|
|
|
func HandleMinecraftMessage(conn *websocket.Conn, msg []byte) {
|
|
status, cmdID, dest, playerUuid, cmdNumber, args := kraProtocol.DecodeJavaMessage(msg)
|
|
|
|
mcClient := GetMinecraftClientByConn(conn)
|
|
|
|
if mcClient == nil {
|
|
logger.Minecraft.Warnln("mcClient is nil")
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusErrTryAgain {
|
|
logger.Minecraft.Warnln("err StatusErrTryAgain cmdID", cmdID, "cmdNumber", cmdNumber)
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusErrNoPerms {
|
|
logger.Minecraft.Warnln("err StatusErrNoPerms cmdID", cmdID, "cmdNumber", cmdNumber)
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusErrArgLenTooBig {
|
|
logger.Minecraft.Warnln("err StatusErrArgLenTooBig cmdID", cmdID, "cmdNumber", cmdNumber)
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusMessageAlreadyInQueue {
|
|
logger.Minecraft.Warnln("rec StatusMessageAlreadyInQueue cmdID", cmdID, "cmdNumber", cmdNumber)
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusReply {
|
|
if isCmdIDInList(mcClient.CmdIDs, cmdID) {
|
|
mcClient.RemoveCmdID(cmdID)
|
|
}
|
|
|
|
logger.Minecraft.Debugln(mcClient.IsCmdIDInSendMessagesQueue(cmdID))
|
|
|
|
if mcClient.IsCmdIDInSendMessagesQueue(cmdID) {
|
|
queueMsg, err := mcClient.GetMessageFromSendQueueByCmdID(cmdID)
|
|
|
|
logger.Minecraft.Debugln("IsCmdIDInSendMessagesQueue queueMsg", queueMsg.OriginDest, queueMsg.OriginCmdID)
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if queueMsg.OriginDest == kraProtocol.DestVoice || queueMsg.OriginDest == kraProtocol.DestMobile {
|
|
webClient := GetWebClientByUuid(playerUuid)
|
|
|
|
if webClient == nil {
|
|
logger.Minecraft.Warn("webClient is nil")
|
|
return
|
|
}
|
|
|
|
raw := kraProtocol.EncodeWebMessage(kraProtocol.StatusReply, queueMsg.OriginCmdID, cmdNumber, args)
|
|
|
|
var err error
|
|
|
|
if queueMsg.OriginDest == kraProtocol.DestVoice {
|
|
err = webClient.SendBinaryMessage(webClient.VoiceConn, raw)
|
|
} else {
|
|
err = webClient.SendBinaryMessage(webClient.MobileConn, raw)
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Println("failed to send message")
|
|
}
|
|
}
|
|
|
|
mcClient.RemoveMessageFromSendQueueByCmdID(cmdID)
|
|
|
|
// TODO: handle ack answer (send answer to mobile or handle her)
|
|
}
|
|
return
|
|
}
|
|
|
|
var raw []byte
|
|
var err error
|
|
|
|
// queue handling when message already in process
|
|
if status == kraProtocol.StatusGet {
|
|
// cmdID already in queue
|
|
logger.Minecraft.Debugln("cmdIDList", mcClient.CmdIDs)
|
|
if isCmdIDInList(mcClient.CmdIDs, cmdID) {
|
|
raw := kraProtocol.EncodeJavaMessage(kraProtocol.StatusMessageAlreadyInQueue, cmdID, dest, playerUuid, cmdNumber, args)
|
|
|
|
err = mcClient.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("write err", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// not in queue, add to queue
|
|
mcClient.CmdIDs = append(mcClient.CmdIDs, cmdID)
|
|
}
|
|
|
|
// dest handling
|
|
if dest == kraProtocol.DestBackend {
|
|
resArgs := minecraftCommandHandler(cmdNumber, playerUuid)
|
|
|
|
if status == kraProtocol.StatusGet {
|
|
raw = kraProtocol.EncodeJavaMessage(kraProtocol.StatusReply, cmdID, 0, playerUuid, cmdNumber, resArgs)
|
|
|
|
err = mcClient.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("write:", err)
|
|
}
|
|
}
|
|
} else if dest == kraProtocol.DestVoice || dest == kraProtocol.DestMobile { // forwarding messsage to voice or mobile
|
|
webClient := GetWebClientByUuid(playerUuid)
|
|
|
|
if webClient == nil || dest == kraProtocol.DestVoice && webClient.VoiceConn == nil || dest == kraProtocol.DestMobile && webClient.MobileConn == nil {
|
|
raw = kraProtocol.EncodeJavaMessage(kraProtocol.StatusErrTryAgain, cmdID, 0, playerUuid, cmdNumber, args)
|
|
|
|
err = mcClient.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("write:", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusGet {
|
|
webClient := GetWebClientByUuid(playerUuid)
|
|
|
|
var webCmdID int
|
|
|
|
if dest == kraProtocol.DestVoice {
|
|
webCmdID = structs.GenerateWebCmdID(webClient.CurrentVoiceCmdIDIndexByBackend)
|
|
|
|
webClient.CurrentVoiceCmdIDIndexByBackend = webCmdID
|
|
|
|
logger.Minecraft.Debugln("webCmdID", webCmdID)
|
|
|
|
// TODO: Get minecraft server dest from func
|
|
a := &structs.A{WebCmdID: webCmdID, CmdIDFromMinecraftServer: cmdID, DestFromMinecraftServer: 10}
|
|
|
|
webClient.VoiceCmdIDsByBackend = append(webClient.VoiceCmdIDsByBackend, a)
|
|
|
|
logger.Minecraft.Debugln("VoiceCMDIDsByBackend", webClient.VoiceCmdIDsByBackend)
|
|
} else { // dest mobile
|
|
webCmdID = structs.GenerateWebCmdID(webClient.CurrentMobileVoiceCmdIDIndexByBackend)
|
|
|
|
webClient.CurrentMobileVoiceCmdIDIndexByBackend = webCmdID
|
|
|
|
logger.Minecraft.Debugln("webCmdID", webCmdID)
|
|
|
|
// TODO: Get minecraft server dest from func
|
|
a := &structs.A{WebCmdID: webCmdID, CmdIDFromMinecraftServer: cmdID, DestFromMinecraftServer: 10}
|
|
|
|
webClient.MobileCmdIDsByBackend = append(webClient.MobileCmdIDsByBackend, a)
|
|
|
|
logger.Minecraft.Debugln("MobileCMDIDsByBackend", webClient.MobileCmdIDsByBackend)
|
|
}
|
|
|
|
raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusGet, webCmdID, cmdNumber, args)
|
|
|
|
if dest == kraProtocol.DestVoice { // TODO: correct dest
|
|
webClient.SendVoiceQueueMessages = append(webClient.SendVoiceQueueMessages, &structs.SendQueueMessage{MessageRaw: raw, CmdID: webCmdID, TrySendCount: 0, OriginDest: 111111, OriginCmdID: cmdID, Time: time.Now()})
|
|
} else {
|
|
webClient.SendMobileQueueMessages = append(webClient.SendMobileQueueMessages, &structs.SendQueueMessage{MessageRaw: raw, CmdID: webCmdID, TrySendCount: 0, Time: time.Now()})
|
|
}
|
|
} else {
|
|
raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusSend, 0, cmdNumber, args)
|
|
}
|
|
|
|
if dest == kraProtocol.DestVoice {
|
|
webClient.SendBinaryMessage(webClient.VoiceConn, raw)
|
|
} else {
|
|
webClient.SendBinaryMessage(webClient.MobileConn, raw)
|
|
}
|
|
} else if dest == kraProtocol.DestProxy {
|
|
client := GetMinecraftClientByName("proxy-1")
|
|
|
|
if client == nil {
|
|
raw = kraProtocol.EncodeJavaMessage(kraProtocol.StatusErrTryAgain, cmdID, 0, playerUuid, cmdNumber, "")
|
|
|
|
err = mcClient.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("write:", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
if status == kraProtocol.StatusGet {
|
|
raw = kraProtocol.EncodeJavaMessage(kraProtocol.StatusReply, cmdID, dest, playerUuid, cmdNumber, args)
|
|
} else {
|
|
raw = kraProtocol.EncodeJavaMessage(kraProtocol.StatusSend, 0, dest, playerUuid, cmdNumber, args)
|
|
}
|
|
|
|
err = client.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("write:", err)
|
|
}
|
|
} else { // TODO: handle messages -> GameServer-1 to GameServer-2
|
|
logger.Minecraft.Debugln("dest not found", dest)
|
|
}
|
|
}
|
|
|
|
func GetMinecraftClientByName(Name string) *structs.MinecraftClient {
|
|
for name, client := range cache.MinecraftClients {
|
|
if name == Name {
|
|
logger.Minecraft.Debugln("return mc client", client.Name)
|
|
return client
|
|
}
|
|
}
|
|
|
|
logger.Minecraft.Warnln("mc client nil")
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetMinecraftClientByConn(conn *websocket.Conn) *structs.MinecraftClient {
|
|
for _, client := range cache.MinecraftClients {
|
|
if client.Conn == conn {
|
|
return client
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getMinecraftServerNameByDest(dest int) string {
|
|
if dest == kraProtocol.DestProxy {
|
|
return "proxy-1"
|
|
} else { // get players current server from db if dest is 11
|
|
return "lobby-1"
|
|
}
|
|
}
|
|
|
|
func minecraftCommandHandler(cmdNumber int, playerUuid string) (args string) {
|
|
switch cmdNumber {
|
|
case 10: // testing
|
|
return IsVoiceAndMobileSocketConnected(playerUuid)
|
|
default:
|
|
return "default"
|
|
}
|
|
}
|
|
|
|
// Deprecated: only for testing, use SendMessageToMinecraftServer instead
|
|
func SendMessageToServer(dest int, playerUuid string, args string) {
|
|
mcClient := GetMinecraftClientByName(getMinecraftServerNameByDest(dest))
|
|
|
|
raw := kraProtocol.EncodeJavaMessage(10, 1, 2, playerUuid, 15, args)
|
|
|
|
if mcClient != nil {
|
|
mcClient.SendBinaryMessage(raw)
|
|
}
|
|
}
|
|
|
|
func SendMessageToMinecraftServer(originDest int, originCmdID int, status int, dest int, playerUuid string, cmdNumber int, args string) error {
|
|
cmdID := kraProtocol.DefaultCmdID
|
|
|
|
serverName := getMinecraftServerNameByDest(dest)
|
|
|
|
mcClient := GetMinecraftClientByName(serverName)
|
|
|
|
if mcClient == nil {
|
|
return errors.New("mcClient nil")
|
|
}
|
|
|
|
if status == kraProtocol.StatusGet {
|
|
cmdID = mcClient.GenerateMinecraftCmdID()
|
|
}
|
|
|
|
raw := kraProtocol.EncodeJavaMessage(status, cmdID, dest, playerUuid, cmdNumber, args)
|
|
|
|
err := mcClient.SendBinaryMessage(raw)
|
|
|
|
if err != nil {
|
|
logger.Minecraft.Warnln("err", err)
|
|
return errors.New("write err: " + err.Error())
|
|
}
|
|
|
|
if status == kraProtocol.StatusGet {
|
|
mcClient.AddMessageToSendQueue(originDest, originCmdID, raw, cmdID)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GenerateDestForNewMinecraftClient() int {
|
|
newDest := 10
|
|
|
|
for {
|
|
if isDestInUsageFromOneMinecraftClient(newDest) {
|
|
break
|
|
} else {
|
|
newDest++
|
|
}
|
|
}
|
|
|
|
return newDest
|
|
}
|
|
|
|
func isDestInUsageFromOneMinecraftClient(dest int) bool {
|
|
for _, mcClient := range cache.MinecraftClients {
|
|
if mcClient.Dest == dest {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|