mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-17 09:24:50 +01:00
Merge pull request #15 from Ellie42/improve-chat
Improve chat and additional small fixes for party interaction
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
www/tw/
|
www/tw/
|
||||||
www/jp/
|
www/jp/
|
||||||
|
|
||||||
|
vendor/
|
||||||
bin/*.bin
|
bin/*.bin
|
||||||
bin/quests/*.bin
|
bin/quests/*.bin
|
||||||
bin/questlists/*.bin
|
bin/questlists/*.bin
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type DevModeOptions struct {
|
|||||||
CleanDB bool // Automatically wipes the DB on server reset.
|
CleanDB bool // Automatically wipes the DB on server reset.
|
||||||
MaxLauncherHR bool // Sets the HR returned in the launcher to HR9 so that you can join non-beginner worlds.
|
MaxLauncherHR bool // Sets the HR returned in the launcher to HR9 so that you can join non-beginner worlds.
|
||||||
FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages
|
FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages
|
||||||
|
LogOutboundMessages bool // Log all messages sent to the clients
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database holds the postgres database config.
|
// Database holds the postgres database config.
|
||||||
|
|||||||
48
network/binpacket/msg_cast_bin_private_message.go
Normal file
48
network/binpacket/msg_cast_bin_private_message.go
Normal 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")
|
||||||
|
}
|
||||||
@@ -6,7 +6,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// MsgSysDeleteUser represents the MSG_SYS_DELETE_USER
|
// MsgSysDeleteUser represents the MSG_SYS_DELETE_USER
|
||||||
type MsgSysDeleteUser struct{}
|
type MsgSysDeleteUser struct {
|
||||||
|
CharID uint32
|
||||||
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
func (m *MsgSysDeleteUser) Opcode() network.PacketID {
|
func (m *MsgSysDeleteUser) Opcode() network.PacketID {
|
||||||
@@ -20,5 +22,7 @@ func (m *MsgSysDeleteUser) Parse(bf *byteframe.ByteFrame) error {
|
|||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
func (m *MsgSysDeleteUser) Build(bf *byteframe.ByteFrame) error {
|
func (m *MsgSysDeleteUser) Build(bf *byteframe.ByteFrame) error {
|
||||||
panic("Not implemented")
|
bf.WriteUint32(m.CharID)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,3 +167,20 @@ func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session)
|
|||||||
session.QueueSendNonBlocking(bf.Data())
|
session.QueueSendNonBlocking(bf.Data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) FindSessionByCharID(charID uint32) *Session {
|
||||||
|
s.stagesLock.RLock()
|
||||||
|
defer s.stagesLock.RUnlock()
|
||||||
|
for _, stage := range s.stages {
|
||||||
|
stage.RLock()
|
||||||
|
for client := range stage.clients {
|
||||||
|
if client.charID == charID {
|
||||||
|
stage.RUnlock()
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/Andoryuuta/Erupe/network/binpacket"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -177,7 +179,9 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.QueueAck(pkt.AckHandle, bf.Data())
|
s.QueueAck(pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
logoutPlayer(s)
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
@@ -190,21 +194,71 @@ func handleMsgSysPing(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.QueueAck(pkt.AckHandle, bf.Data())
|
s.QueueAck(pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
BINARY_MESSAGE_TYPE_CHAT = 1
|
||||||
|
BINARY_MESSAGE_TYPE_EMOTE = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CHAT_TYPE_WORLD = 0x0a
|
||||||
|
CHAT_TYPE_STAGE = 0x03
|
||||||
|
CHAT_TYPE_TARGETED = 0x01
|
||||||
|
)
|
||||||
|
|
||||||
func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysCastBinary)
|
pkt := p.(*mhfpacket.MsgSysCastBinary)
|
||||||
|
|
||||||
// Simply forward the packet to all the other clients.
|
|
||||||
// (The client never uses Type0 upon receiving)
|
|
||||||
// TODO(Andoryuuta): Does this broadcast need to be limited? (world, stage, guild, etc).
|
|
||||||
resp := &mhfpacket.MsgSysCastedBinary{
|
resp := &mhfpacket.MsgSysCastedBinary{
|
||||||
CharID: s.charID,
|
CharID: s.charID,
|
||||||
Type0: pkt.Type0,
|
Type0: pkt.Type0,
|
||||||
Type1: pkt.Type1,
|
Type1: pkt.Type1,
|
||||||
RawDataPayload: pkt.RawDataPayload,
|
RawDataPayload: pkt.RawDataPayload,
|
||||||
}
|
}
|
||||||
s.server.BroadcastMHF(resp, s)
|
|
||||||
|
|
||||||
if pkt.Type0 == 3 && pkt.Type1 == 1 {
|
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 pkt.Type0 {
|
||||||
|
case CHAT_TYPE_WORLD:
|
||||||
|
s.server.BroadcastMHF(resp, s)
|
||||||
|
case CHAT_TYPE_STAGE:
|
||||||
|
s.stage.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(chatMessage.TargetType)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Made the inside of the casted binary
|
// Made the inside of the casted binary
|
||||||
payload := byteframe.NewByteFrame()
|
payload := byteframe.NewByteFrame()
|
||||||
@@ -237,6 +291,11 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bfw.WriteUint16(uint16(len(payloadBytes)))
|
bfw.WriteUint16(uint16(len(payloadBytes)))
|
||||||
bfw.WriteBytes(payloadBytes)
|
bfw.WriteBytes(payloadBytes)
|
||||||
*/
|
*/
|
||||||
|
} else {
|
||||||
|
// Simply forward the packet to all the other clients.
|
||||||
|
// (The client never uses Type0 upon receiving)
|
||||||
|
// TODO(Andoryuuta): Does this broadcast need to be limited? (world, stage, guild, etc).
|
||||||
|
s.server.BroadcastMHF(resp, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,6 +407,7 @@ func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
s.server.stagesLock.Lock()
|
s.server.stagesLock.Lock()
|
||||||
stage := NewStage(stripNullTerminator(pkt.StageID))
|
stage := NewStage(stripNullTerminator(pkt.StageID))
|
||||||
|
stage.maxPlayers = uint16(pkt.PlayerCount)
|
||||||
s.server.stages[stage.id] = stage
|
s.server.stages[stage.id] = stage
|
||||||
s.server.stagesLock.Unlock()
|
s.server.stagesLock.Unlock()
|
||||||
|
|
||||||
@@ -364,27 +424,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
s.server.stagesLock.Unlock()
|
s.server.stagesLock.Unlock()
|
||||||
|
|
||||||
if s.stage != nil {
|
if s.stage != nil {
|
||||||
s.stage.Lock()
|
removeSessionFromStage(s)
|
||||||
|
|
||||||
// Remove client from old stage.
|
|
||||||
delete(s.stage.clients, s)
|
|
||||||
|
|
||||||
// Delete old stage objects owned by the client.
|
|
||||||
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
|
|
||||||
for objID, stageObject := range s.stage.objects {
|
|
||||||
if stageObject.ownerCharID == s.charID {
|
|
||||||
// Broadcast the deletion to clients in the stage.
|
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{
|
|
||||||
ObjID: stageObject.id,
|
|
||||||
}, s)
|
|
||||||
// TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't.
|
|
||||||
|
|
||||||
// Actually delete it form the objects map.
|
|
||||||
delete(s.stage.objects, objID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.stage.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new stage.
|
// Add the new stage.
|
||||||
@@ -407,23 +447,26 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
s.QueueAck(ackHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
s.QueueAck(ackHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
|
|
||||||
// Notify existing stage clients that this new client has entered.
|
// Notify existing stage clients that this new client has entered.
|
||||||
s.logger.Info("Sending MsgSysInsertUser & MsgSysNotifyUserBinary")
|
s.logger.Info("Sending MsgSysInsertUser")
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
|
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
|
||||||
CharID: s.charID,
|
CharID: s.charID,
|
||||||
}, s)
|
}, s)
|
||||||
|
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
// It seems to be acceptable to recast all MSG_SYS_SET_USER_BINARY messages so far,
|
||||||
CharID: s.charID,
|
// players are still notified when a new player has joined the stage.
|
||||||
BinaryType: 1,
|
// These extra messages may not be needed
|
||||||
}, s)
|
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
// CharID: s.charID,
|
||||||
CharID: s.charID,
|
// BinaryType: 1,
|
||||||
BinaryType: 2,
|
//}, s)
|
||||||
}, s)
|
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
// CharID: s.charID,
|
||||||
CharID: s.charID,
|
// BinaryType: 2,
|
||||||
BinaryType: 3,
|
//}, s)
|
||||||
}, s)
|
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
// CharID: s.charID,
|
||||||
|
// BinaryType: 3,
|
||||||
|
//}, s)
|
||||||
|
|
||||||
//Notify the entree client about all of the existing clients in the stage.
|
//Notify the entree client about all of the existing clients in the stage.
|
||||||
s.logger.Info("Notifying entree about existing stage clients")
|
s.logger.Info("Notifying entree about existing stage clients")
|
||||||
@@ -483,6 +526,54 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
s.QueueSend(clientDupObjNotif.Data())
|
s.QueueSend(clientDupObjNotif.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeSessionFromStage(s *Session) {
|
||||||
|
s.stage.Lock()
|
||||||
|
defer s.stage.Unlock()
|
||||||
|
|
||||||
|
// Remove client from old stage.
|
||||||
|
delete(s.stage.clients, s)
|
||||||
|
|
||||||
|
// Delete old stage objects owned by the client.
|
||||||
|
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
|
||||||
|
for objID, stageObject := range s.stage.objects {
|
||||||
|
if stageObject.ownerCharID == s.charID {
|
||||||
|
// Broadcast the deletion to clients in the stage.
|
||||||
|
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{
|
||||||
|
ObjID: stageObject.id,
|
||||||
|
}, s)
|
||||||
|
// TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't.
|
||||||
|
|
||||||
|
// Actually delete it form the objects map.
|
||||||
|
delete(s.stage.objects, objID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stageContainsSession(stage *Stage, s *Session) bool {
|
||||||
|
stage.RLock()
|
||||||
|
defer stage.RUnlock()
|
||||||
|
|
||||||
|
for session := range stage.clients {
|
||||||
|
if session == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func logoutPlayer(s *Session) {
|
||||||
|
s.stage.RLock()
|
||||||
|
for client := range s.stage.clients {
|
||||||
|
client.QueueSendMHF(&mhfpacket.MsgSysDeleteUser{
|
||||||
|
CharID: s.charID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.stage.RUnlock()
|
||||||
|
|
||||||
|
removeSessionFromStage(s)
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
||||||
|
|
||||||
@@ -540,7 +631,7 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysReserveStage)
|
pkt := p.(*mhfpacket.MsgSysReserveStage)
|
||||||
|
|
||||||
stageID := stripNullTerminator(pkt.StageID)
|
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
|
// Try to get the stage
|
||||||
s.server.stagesLock.Lock()
|
s.server.stagesLock.Lock()
|
||||||
@@ -568,6 +659,7 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
} else {
|
} else {
|
||||||
s.QueueAck(pkt.AckHandle, []byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
s.QueueAck(pkt.AckHandle, []byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysUnreserveStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysUnreserveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
@@ -691,6 +783,11 @@ func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
if gotBinary {
|
if gotBinary {
|
||||||
doSizedAckResp(s, pkt.AckHandle, stageBinary)
|
doSizedAckResp(s, pkt.AckHandle, stageBinary)
|
||||||
|
|
||||||
|
} else if pkt.BinaryType1 == 4 {
|
||||||
|
// This particular type seems to be expecting data that isn't set
|
||||||
|
// is it required before the party joining can be completed
|
||||||
|
s.QueueAck(pkt.AckHandle, []byte{0x01, 0x00, 0x00, 0x00, 0x10})
|
||||||
} else {
|
} else {
|
||||||
s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||||
s.logger.Warn("Sending blank stage binary")
|
s.logger.Warn("Sending blank stage binary")
|
||||||
@@ -846,7 +943,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
// Response to our requesting client.
|
// Response to our requesting client.
|
||||||
resp := byteframe.NewByteFrame()
|
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.
|
resp.WriteUint32(objID) // New local obj handle.
|
||||||
s.QueueAck(pkt.AckHandle, resp.Data())
|
s.QueueAck(pkt.AckHandle, resp.Data())
|
||||||
|
|
||||||
@@ -909,6 +1006,13 @@ func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.server.userBinaryPartsLock.Lock()
|
s.server.userBinaryPartsLock.Lock()
|
||||||
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
||||||
s.server.userBinaryPartsLock.Unlock()
|
s.server.userBinaryPartsLock.Unlock()
|
||||||
|
|
||||||
|
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: s.charID,
|
||||||
|
BinaryType: pkt.BinaryType,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.stage.BroadcastMHF(msg, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package channelserver
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -59,6 +60,11 @@ func (s *Session) Start() {
|
|||||||
|
|
||||||
// QueueSend queues a packet (raw []byte) to be sent.
|
// QueueSend queues a packet (raw []byte) to be sent.
|
||||||
func (s *Session) QueueSend(data []byte) {
|
func (s *Session) QueueSend(data []byte) {
|
||||||
|
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.LogOutboundMessages {
|
||||||
|
fmt.Printf("Sending To CharID: '%x'\n", s.charID)
|
||||||
|
fmt.Printf("Sent Data:\n%s\n", hex.Dump(data))
|
||||||
|
}
|
||||||
|
|
||||||
s.sendPackets <- data
|
s.sendPackets <- data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +125,13 @@ func (s *Session) sendLoop() {
|
|||||||
func (s *Session) recvLoop() {
|
func (s *Session) recvLoop() {
|
||||||
for {
|
for {
|
||||||
pkt, err := s.cryptConn.ReadPacket()
|
pkt, err := s.cryptConn.ReadPacket()
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
s.logger.Info(fmt.Sprintf("Character(%d) disconnected", s.charID))
|
||||||
|
logoutPlayer(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
|
s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
|
||||||
return
|
return
|
||||||
@@ -145,6 +158,7 @@ func (s *Session) handlePacketGroup(pktGroup []byte) {
|
|||||||
opcode != network.MSG_SYS_NOP &&
|
opcode != network.MSG_SYS_NOP &&
|
||||||
opcode != network.MSG_SYS_TIME &&
|
opcode != network.MSG_SYS_TIME &&
|
||||||
opcode != network.MSG_SYS_EXTEND_THRESHOLD {
|
opcode != network.MSG_SYS_EXTEND_THRESHOLD {
|
||||||
|
fmt.Printf("CharID: '%x'\n", s.charID)
|
||||||
fmt.Printf("Opcode: %s\n", opcode)
|
fmt.Printf("Opcode: %s\n", opcode)
|
||||||
fmt.Printf("Data:\n%s\n", hex.Dump(pktGroup))
|
fmt.Printf("Data:\n%s\n", hex.Dump(pktGroup))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user