Add support for players logging out and closing client

Removed seemingly unnecessary castedBinary messages on character login
This commit is contained in:
Sophie
2020-03-09 19:15:16 +00:00
parent ba3df8d4d1
commit 78fe5c85ef
3 changed files with 83 additions and 38 deletions

View File

@@ -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
} }

View File

@@ -177,7 +177,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) {}
@@ -396,27 +398,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.
@@ -439,25 +421,28 @@ 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")
s.stage.RLock() s.stage.RLock()
clientNotif := byteframe.NewByteFrame() clientNotif := byteframe.NewByteFrame()
@@ -515,6 +500,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)

View File

@@ -3,6 +3,7 @@ package channelserver
import ( import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io"
"net" "net"
"sync" "sync"
@@ -124,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