Add support for party chat in town

This commit is contained in:
Sophie
2020-03-10 07:56:01 +00:00
parent 78fe5c85ef
commit 892f89eba9
3 changed files with 103 additions and 16 deletions

View File

@@ -0,0 +1,48 @@
package binpacket
import (
"github.com/Andoryuuta/Erupe/network"
"github.com/Andoryuuta/byteframe"
)
type ChatTargetType uint16
const (
CHAT_TARGET_PRIVATE = 0x05
CHAT_TARGET_PARTY = 0x04
)
type MsgBinTargetedChatMessage struct {
// I can't see a reason if this is indeed the number of targets, that
// it should use 2 bytes
TargetCount uint16
TargetCharIDs []uint32
TargetType uint16
RawDataPayload []byte
}
// Opcode returns the ID associated with this packet type.
func (m *MsgBinTargetedChatMessage) Opcode() network.PacketID {
return network.MSG_SYS_CAST_BINARY
}
func (m *MsgBinTargetedChatMessage) Parse(bf *byteframe.ByteFrame) error {
m.TargetCount = bf.ReadUint16()
i := uint16(0)
m.TargetCharIDs = make([]uint32, m.TargetCount)
for ; i < m.TargetCount; i++ {
m.TargetCharIDs[i] = bf.ReadUint32()
}
m.TargetType = bf.ReadUint16()
m.RawDataPayload = bf.DataFromCurrent()
return nil
}
// Build builds a binary packet from the current data.
func (m *MsgBinTargetedChatMessage) Build(bf *byteframe.ByteFrame) error {
panic("Not implemented")
}

View File

@@ -167,3 +167,15 @@ func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session)
session.QueueSendNonBlocking(bf.Data())
}
}
func (s *Server) FindSessionByCharID(charID uint32) *Session {
for _, stage := range s.stages {
for client := range stage.clients {
if client.charID == charID {
return client
}
}
}
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/Andoryuuta/Erupe/network/binpacket"
"io"
"io/ioutil"
"os"
"path/filepath"
@@ -198,12 +200,9 @@ const (
)
const (
CHAT_TYPE_WORLD uint8 = iota
CHAT_TYPE_LOCAL
CHAT_TYPE_GUILD
CHAT_TYPE_ALLIANCE
CHAT_TYPE_PARTY
CHAT_TYPE_WHISPER
CHAT_TYPE_WORLD = 0x0a
CHAT_TYPE_STAGE = 0x03
CHAT_TYPE_TARGETED = 0x01
)
func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
@@ -217,20 +216,48 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
}
if pkt.Type1 == BINARY_MESSAGE_TYPE_CHAT {
bf := byteframe.NewByteFrame()
bf.WriteBytes(pkt.RawDataPayload)
bf.Seek(0, io.SeekStart)
fmt.Println("Got chat message!")
switch chatType := pkt.RawDataPayload[2]; chatType {
switch pkt.Type0 {
case CHAT_TYPE_WORLD:
s.server.BroadcastMHF(resp, s)
case CHAT_TYPE_LOCAL:
case CHAT_TYPE_STAGE:
s.stage.BroadcastMHF(resp, s)
case CHAT_TYPE_PARTY:
if s.reservationStage != nil {
// Party messages seem to work partially when a party member starts the quest
// In town it is not working yet, the client now sends the chat packets
// however the other member does not accept it.
s.reservationStage.BroadcastMHF(resp, s)
case CHAT_TYPE_TARGETED:
chatMessage := &binpacket.MsgBinTargetedChatMessage{}
err := chatMessage.Parse(bf)
if err != nil {
s.logger.Warn("failed to parse chat message")
break
}
chatBf := byteframe.NewByteFrame()
chatBf.WriteUint16(0x04)
chatBf.WriteBytes(chatMessage.RawDataPayload)
resp = &mhfpacket.MsgSysCastedBinary{
CharID: s.charID,
Type0: pkt.Type0,
Type1: pkt.Type1,
RawDataPayload: chatBf.Data(),
}
for _, targetID := range chatMessage.TargetCharIDs {
char := s.server.FindSessionByCharID(targetID)
if char != nil {
char.QueueSendMHF(resp)
}
}
default:
s.stage.BroadcastMHF(resp, s)
}
/*
@@ -605,7 +632,7 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysReserveStage)
stageID := stripNullTerminator(pkt.StageID)
fmt.Printf("Got reserve stage req, Unk0:%v, StageID:%v\n", pkt.Unk0, stageID)
fmt.Printf("Got reserve stage req, TargetCount:%v, StageID:%v\n", pkt.Unk0, stageID)
// Try to get the stage
s.server.stagesLock.Lock()
@@ -910,7 +937,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
// Response to our requesting client.
resp := byteframe.NewByteFrame()
resp.WriteUint32(0) // Unk, is this echoed back from pkt.Unk0?
resp.WriteUint32(0) // Unk, is this echoed back from pkt.TargetCount?
resp.WriteUint32(objID) // New local obj handle.
s.QueueAck(pkt.AckHandle, resp.Data())