This commit is contained in:
xl3lackout
2022-02-25 19:44:26 -05:00
commit a92897404a
690 changed files with 70775 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
package channelserver
import (
"fmt"
"strings"
"github.com/Andoryuuta/byteframe"
"github.com/Solenataris/Erupe/network/binpacket"
"github.com/Solenataris/Erupe/network/mhfpacket"
)
// MSG_SYS_CAST[ED]_BINARY types enum
const (
BinaryMessageTypeState = 0
BinaryMessageTypeChat = 1
BinaryMessageTypeMailNotify = 4
BinaryMessageTypeEmote = 6
)
// MSG_SYS_CAST[ED]_BINARY broadcast types enum
const (
BroadcastTypeTargeted = 0x01
BroadcastTypeStage = 0x03
BroadcastTypeWorld = 0x0a
)
func sendServerChatMessage(s *Session, message string) {
// Make the inside of the casted binary
bf := byteframe.NewByteFrame()
bf.SetLE()
msgBinChat := &binpacket.MsgBinChat{
Unk0: 0,
Type: 5,
Flags: 0x80,
Message: message,
SenderName: "Erupe",
}
msgBinChat.Build(bf)
castedBin := &mhfpacket.MsgSysCastedBinary{
CharID: s.charID,
MessageType: BinaryMessageTypeChat,
RawDataPayload: bf.Data(),
}
s.QueueSendMHF(castedBin)
}
func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysCastBinary)
// Parse out the real casted binary payload
var realPayload []byte
var msgBinTargeted *binpacket.MsgBinTargeted
if pkt.BroadcastType == BroadcastTypeTargeted {
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
msgBinTargeted = &binpacket.MsgBinTargeted{}
err := msgBinTargeted.Parse(bf)
if err != nil {
s.logger.Warn("Failed to parse targeted cast binary")
return
}
realPayload = msgBinTargeted.RawDataPayload
} else {
realPayload = pkt.RawDataPayload
}
// Make the response to forward to the other client(s).
resp := &mhfpacket.MsgSysCastedBinary{
CharID: s.charID,
BroadcastType: pkt.BroadcastType, // (The client never uses Type0 upon receiving)
MessageType: pkt.MessageType,
RawDataPayload: realPayload,
}
// Send to the proper recipients.
switch pkt.BroadcastType {
case BroadcastTypeWorld:
s.server.BroadcastMHF(resp, s)
case BroadcastTypeStage:
s.stage.BroadcastMHF(resp, s)
case BroadcastTypeTargeted:
for _, targetID := range (*msgBinTargeted).TargetCharIDs {
char := s.server.FindSessionByCharID(targetID)
if char != nil {
char.QueueSendMHF(resp)
}
}
default:
s.Lock()
haveStage := s.stage != nil
if haveStage {
s.stage.BroadcastMHF(resp, s)
}
s.Unlock()
}
// Handle chat
if pkt.MessageType == BinaryMessageTypeChat {
bf := byteframe.NewByteFrameFromBytes(realPayload)
// IMPORTANT! Casted binary objects are sent _as they are in memory_,
// this means little endian for LE CPUs, might be different for PS3/PS4/PSP/XBOX.
bf.SetLE()
chatMessage := &binpacket.MsgBinChat{}
chatMessage.Parse(bf)
fmt.Printf("Got chat message: %+v\n", chatMessage)
// Discord integration
if s.server.erupeConfig.Discord.Enabled {
message := fmt.Sprintf("%s: %s", chatMessage.SenderName, chatMessage.Message)
s.server.discordSession.ChannelMessageSend(s.server.erupeConfig.Discord.ChannelID, message)
}
if strings.HasPrefix(chatMessage.Message, "!tele ") {
var x, y int16
n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y)
if err != nil || n != 2 {
sendServerChatMessage(s, "Invalid command. Usage:\"!tele 500 500\"")
} else {
sendServerChatMessage(s, fmt.Sprintf("Teleporting to %d %d", x, y))
// Make the inside of the casted binary
payload := byteframe.NewByteFrame()
payload.SetLE()
payload.WriteUint8(2) // SetState type(position == 2)
payload.WriteInt16(x) // X
payload.WriteInt16(y) // Y
payloadBytes := payload.Data()
s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{
CharID: s.charID,
MessageType: BinaryMessageTypeState,
RawDataPayload: payloadBytes,
})
}
}
}
}
func handleMsgSysCastedBinary(s *Session, p mhfpacket.MHFPacket) {}