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
type MsgSysDeleteUser struct{}
type MsgSysDeleteUser struct {
CharID uint32
}
// Opcode returns the ID associated with this packet type.
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.
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())
}
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
logoutPlayer(s)
}
func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {}
@@ -396,27 +398,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
s.server.stagesLock.Unlock()
if s.stage != nil {
s.stage.Lock()
// 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()
removeSessionFromStage(s)
}
// 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})
// 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{
CharID: s.charID,
}, s)
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID,
BinaryType: 1,
}, s)
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID,
BinaryType: 2,
}, s)
s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID,
BinaryType: 3,
}, s)
// It seems to be acceptable to recast all MSG_SYS_SET_USER_BINARY messages so far,
// players are still notified when a new player has joined the stage.
// These extra messages may not be needed
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
// CharID: s.charID,
// BinaryType: 1,
//}, s)
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
// CharID: s.charID,
// BinaryType: 2,
//}, 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.stage.RLock()
clientNotif := byteframe.NewByteFrame()
@@ -515,6 +500,54 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
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) {
pkt := p.(*mhfpacket.MsgSysEnterStage)

View File

@@ -3,6 +3,7 @@ package channelserver
import (
"encoding/hex"
"fmt"
"io"
"net"
"sync"
@@ -124,6 +125,13 @@ func (s *Session) sendLoop() {
func (s *Session) recvLoop() {
for {
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 {
s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
return