mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-27 18:12:50 +01:00
rework stages
This commit is contained in:
@@ -183,10 +183,6 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser {
|
|
||||||
CharID: s.charID,
|
|
||||||
}, s)
|
|
||||||
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"erupe-ce/network/mhfpacket"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
ps "erupe-ce/common/pascalstring"
|
||||||
|
"erupe-ce/network/mhfpacket"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.server.Lock()
|
s.server.Lock()
|
||||||
defer s.server.Unlock()
|
defer s.server.Unlock()
|
||||||
if _, exists := s.server.stages[pkt.StageID]; exists {
|
if _, exists := s.server.stages[pkt.StageID]; exists {
|
||||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
} else {
|
} else {
|
||||||
stage := NewStage(pkt.StageID)
|
stage := NewStage(pkt.StageID)
|
||||||
stage.maxPlayers = uint16(pkt.PlayerCount)
|
stage.maxPlayers = uint16(pkt.PlayerCount)
|
||||||
@@ -27,36 +26,33 @@ func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||||
// Remove this session from old stage clients list and put myself in the new one.
|
s.server.Lock()
|
||||||
s.server.stagesLock.Lock()
|
stage, exists := s.server.stages[stageID]
|
||||||
newStage, gotNewStage := s.server.stages[stageID]
|
s.server.Unlock()
|
||||||
s.server.stagesLock.Unlock()
|
|
||||||
|
|
||||||
if s.stage != nil {
|
if exists {
|
||||||
removeSessionFromStage(s)
|
stage.Lock()
|
||||||
|
stage.clients[s] = s.charID
|
||||||
|
stage.Unlock()
|
||||||
|
} else { // Create new stage object
|
||||||
|
s.server.Lock()
|
||||||
|
s.server.stages[stageID] = NewStage(stageID)
|
||||||
|
stage = s.server.stages[stageID]
|
||||||
|
s.server.Unlock()
|
||||||
|
stage.Lock()
|
||||||
|
stage.clients[s] = s.charID
|
||||||
|
stage.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new stage.
|
// Ensure this session no longer belongs to reservations.
|
||||||
if gotNewStage {
|
if s.stage != nil {
|
||||||
newStage.Lock()
|
removeSessionFromStage(s)
|
||||||
newStage.clients[s] = s.charID
|
|
||||||
newStage.Unlock()
|
|
||||||
} else {
|
|
||||||
// Fix stages
|
|
||||||
s.logger.Info("Fix Map Appliqued")
|
|
||||||
s.server.stagesLock.Lock()
|
|
||||||
s.server.stages[stageID] = NewStage(stageID)
|
|
||||||
newStage = s.server.stages[stageID]
|
|
||||||
s.server.stagesLock.Unlock()
|
|
||||||
newStage.Lock()
|
|
||||||
newStage.clients[s] = s.charID
|
|
||||||
newStage.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save our new stage ID and pointer to the new stage itself.
|
// Save our new stage ID and pointer to the new stage itself.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.stageID = string(stageID)
|
s.stageID = string(stageID)
|
||||||
s.stage = newStage
|
s.stage = s.server.stages[stageID]
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
// Tell the client to cleanup its current stage objects.
|
// Tell the client to cleanup its current stage objects.
|
||||||
@@ -65,138 +61,133 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
// Confirm the stage entry.
|
// Confirm the stage entry.
|
||||||
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
|
||||||
// Notify existing stage clients that this new client has entered.
|
|
||||||
if s.stage != nil { // avoids lock up when using bed for dream quests
|
if s.stage != nil { // avoids lock up when using bed for dream quests
|
||||||
var pkt mhfpacket.MHFPacket
|
|
||||||
|
|
||||||
// Notify the entree client about all of the existing clients in the stage.
|
|
||||||
s.logger.Info("Notifying entree about existing stage clients")
|
|
||||||
|
|
||||||
clientNotif := byteframe.NewByteFrame()
|
|
||||||
s.server.Lock()
|
|
||||||
s.server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser{
|
|
||||||
CharID: s.charID,
|
|
||||||
}, s)
|
|
||||||
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser {
|
|
||||||
CharID: s.charID,
|
|
||||||
}, s)
|
|
||||||
|
|
||||||
for session := range s.server.sessions {
|
|
||||||
session := s.server.sessions[session]
|
|
||||||
|
|
||||||
// Send existing players back to the client
|
|
||||||
pkt = &mhfpacket.MsgSysInsertUser{
|
|
||||||
CharID: session.charID,
|
|
||||||
}
|
|
||||||
clientNotif.WriteUint16(uint16(pkt.Opcode()))
|
|
||||||
pkt.Build(clientNotif, session.clientContext)
|
|
||||||
for i := 1; i <= 3; i++ {
|
|
||||||
pkt = &mhfpacket.MsgSysNotifyUserBinary{
|
|
||||||
CharID: session.charID,
|
|
||||||
BinaryType: uint8(i),
|
|
||||||
}
|
|
||||||
clientNotif.WriteUint16(uint16(pkt.Opcode()))
|
|
||||||
pkt.Build(clientNotif, session.clientContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.server.Unlock()
|
|
||||||
clientNotif.WriteUint16(0x0010) // End it.
|
|
||||||
s.QueueSend(clientNotif.Data())
|
|
||||||
|
|
||||||
// Notify the client to duplicate the existing objects.
|
// Notify the client to duplicate the existing objects.
|
||||||
s.logger.Info("Notifying entree about existing stage objects")
|
s.logger.Info("Sending existing stage objects")
|
||||||
clientDupObjNotif := byteframe.NewByteFrame()
|
clientDupObjNotif := byteframe.NewByteFrame()
|
||||||
s.stage.RLock()
|
s.stage.RLock()
|
||||||
for _, obj := range s.stage.objects {
|
for _, obj := range s.stage.objects {
|
||||||
cur := &mhfpacket.MsgSysDuplicateObject{
|
cur := &mhfpacket.MsgSysDuplicateObject{
|
||||||
ObjID: obj.id,
|
ObjID: obj.id,
|
||||||
X: obj.x,
|
X: obj.x,
|
||||||
Y: obj.y,
|
Y: obj.y,
|
||||||
Z: obj.z,
|
Z: obj.z,
|
||||||
Unk0: 0,
|
Unk0: 0,
|
||||||
OwnerCharID: obj.ownerCharID,
|
OwnerCharID: obj.ownerCharID,
|
||||||
}
|
}
|
||||||
clientDupObjNotif.WriteUint16(uint16(cur.Opcode()))
|
clientDupObjNotif.WriteUint16(uint16(cur.Opcode()))
|
||||||
cur.Build(clientDupObjNotif, s.clientContext)
|
cur.Build(clientDupObjNotif, s.clientContext)
|
||||||
}
|
}
|
||||||
s.stage.RUnlock()
|
s.stage.RUnlock()
|
||||||
clientDupObjNotif.WriteUint16(0x0010) // End it.
|
clientDupObjNotif.WriteUint16(0x0010) // End it.
|
||||||
s.QueueSend(clientDupObjNotif.Data())
|
if len(clientDupObjNotif.Data()) > 2 {
|
||||||
|
s.QueueSend(clientDupObjNotif.Data())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeEmptyStages(s *Session) {
|
func removeEmptyStages(s *Session) {
|
||||||
s.server.Lock()
|
s.server.Lock()
|
||||||
for sid, stage := range s.server.stages {
|
defer s.server.Unlock()
|
||||||
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
for _, stage := range s.server.stages {
|
||||||
if strings.HasPrefix(sid, "sl1Qs") || strings.HasPrefix(sid, "sl2Qs") || strings.HasPrefix(sid, "sl3Qs") {
|
// Destroy empty Quest/My series/Guild stages.
|
||||||
delete(s.server.stages, sid)
|
if stage.id[3:5] == "Qs" || stage.id[3:5] == "Ms" || stage.id[3:5] == "Gs" {
|
||||||
|
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
||||||
|
delete(s.server.stages, stage.id)
|
||||||
|
s.logger.Debug("Destructed stage", zap.String("stage.id", stage.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.server.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeSessionFromStage(s *Session) {
|
func removeSessionFromStage(s *Session) {
|
||||||
s.stage.Lock()
|
|
||||||
defer s.stage.Unlock()
|
|
||||||
|
|
||||||
// Remove client from old stage.
|
// Remove client from old stage.
|
||||||
|
s.stage.Lock()
|
||||||
delete(s.stage.clients, s)
|
delete(s.stage.clients, s)
|
||||||
delete(s.stage.reservedClientSlots, s.charID)
|
delete(s.stage.reservedClientSlots, s.charID)
|
||||||
|
|
||||||
// Remove client from all reservations
|
|
||||||
s.server.Lock()
|
|
||||||
for _, stage := range s.server.stages {
|
|
||||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
|
||||||
delete(stage.reservedClientSlots, s.charID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.server.Unlock()
|
|
||||||
|
|
||||||
// Delete old stage objects owned by the client.
|
// Delete old stage objects owned by the client.
|
||||||
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
|
s.logger.Info("Sending notification to old stage clients")
|
||||||
for objID, stageObject := range s.stage.objects {
|
for objID, stageObject := range s.stage.objects {
|
||||||
if stageObject.ownerCharID == s.charID {
|
if stageObject.ownerCharID == s.charID {
|
||||||
// Broadcast the deletion to clients in the stage.
|
clientNotif := byteframe.NewByteFrame()
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{
|
var pkt mhfpacket.MHFPacket
|
||||||
|
pkt = &mhfpacket.MsgSysDeleteObject{
|
||||||
ObjID: stageObject.id,
|
ObjID: stageObject.id,
|
||||||
}, s)
|
}
|
||||||
|
clientNotif.WriteUint16(uint16(pkt.Opcode()))
|
||||||
|
pkt.Build(clientNotif, s.clientContext)
|
||||||
|
clientNotif.WriteUint16(0x0010)
|
||||||
|
for client, _ := range s.stage.clients {
|
||||||
|
client.QueueSend(clientNotif.Data())
|
||||||
|
}
|
||||||
// TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't.
|
// TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't.
|
||||||
// Actually delete it form the objects map.
|
// Actually delete it from the objects map.
|
||||||
delete(s.stage.objects, objID)
|
delete(s.stage.objects, objID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for objListID, stageObjectList := range s.stage.objectList {
|
for objListID, stageObjectList := range s.stage.objectList {
|
||||||
if stageObjectList.charid == s.charID {
|
if stageObjectList.charid == s.charID {
|
||||||
//Added to prevent duplicates from flooding ObjectMap and causing server hangs
|
// Added to prevent duplicates from flooding ObjectMap and causing server hangs
|
||||||
s.stage.objectList[objListID].status=false
|
s.stage.objectList[objListID].status = false
|
||||||
s.stage.objectList[objListID].charid=0
|
s.stage.objectList[objListID].charid = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.stage.Unlock()
|
||||||
removeEmptyStages(s)
|
removeEmptyStages(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
||||||
fmt.Printf("The Stage is %s\n",pkt.StageID)
|
|
||||||
// Push our current stage ID to the movement stack before entering another one.
|
// Push our current stage ID to the movement stack before entering another one.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.stageMoveStack.Push(s.stageID)
|
s.stageMoveStack.Push(s.stageID)
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
|
s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{})
|
||||||
|
if s.reservationStage != nil {
|
||||||
|
s.reservationStage = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkt.StageID == "sl1Ns200p0a0u0" { // First entry
|
||||||
|
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
|
||||||
|
CharID: s.charID,
|
||||||
|
}, s)
|
||||||
|
|
||||||
|
var temp mhfpacket.MHFPacket
|
||||||
|
loginNotif := byteframe.NewByteFrame()
|
||||||
|
s.server.Lock()
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if s == session {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
temp = &mhfpacket.MsgSysInsertUser{
|
||||||
|
CharID: session.charID,
|
||||||
|
}
|
||||||
|
loginNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(loginNotif, s.clientContext)
|
||||||
|
for i := 1; i <= 3; i++ {
|
||||||
|
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: session.charID,
|
||||||
|
BinaryType: uint8(i),
|
||||||
|
}
|
||||||
|
loginNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(loginNotif, s.clientContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.server.Unlock()
|
||||||
|
loginNotif.WriteUint16(0x0010) // End it.
|
||||||
|
if len(loginNotif.Data()) > 2 {
|
||||||
|
s.QueueSend(loginNotif.Data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysBackStage)
|
pkt := p.(*mhfpacket.MsgSysBackStage)
|
||||||
|
|
||||||
if s.stage != nil {
|
|
||||||
removeSessionFromStage(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer back to the saved stage ID before the previous move or enter.
|
// Transfer back to the saved stage ID before the previous move or enter.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
backStage, err := s.stageMoveStack.Pop()
|
backStage, err := s.stageMoveStack.Pop()
|
||||||
@@ -260,24 +251,17 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
} else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers {
|
} else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers {
|
||||||
if len(stage.password) > 0 {
|
if len(stage.password) > 0 {
|
||||||
// s.logger.Debug("", zap.String("stgpw", stage.password), zap.String("usrpw", s.stagePass))
|
if stage.password != s.stagePass {
|
||||||
if stage.password == s.stagePass {
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
stage.reservedClientSlots[s.charID] = false
|
|
||||||
s.Lock()
|
|
||||||
s.reservationStage = stage
|
|
||||||
s.Unlock()
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
||||||
} else {
|
|
||||||
stage.reservedClientSlots[s.charID] = false
|
|
||||||
// Save the reservation stage in the session for later use in MsgSysUnreserveStage.
|
|
||||||
s.Lock()
|
|
||||||
s.reservationStage = stage
|
|
||||||
s.Unlock()
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
||||||
}
|
}
|
||||||
|
stage.reservedClientSlots[s.charID] = false
|
||||||
|
// Save the reservation stage in the session for later use in MsgSysUnreserveStage.
|
||||||
|
s.Lock()
|
||||||
|
s.reservationStage = stage
|
||||||
|
s.Unlock()
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
} else {
|
} else {
|
||||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
@@ -308,12 +292,13 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.Unlock()
|
s.Unlock()
|
||||||
if stage != nil {
|
if stage != nil {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
|
// Will only exist if host.
|
||||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||||
stage.password = pkt.Password
|
stage.password = pkt.Password
|
||||||
}
|
}
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
} else {
|
} else {
|
||||||
// Store for use on next ReserveStage
|
// Store for use on next ReserveStage.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.stagePass = pkt.Password
|
s.stagePass = pkt.Password
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
@@ -322,66 +307,66 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
|
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
|
||||||
|
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||||
// Try to get the stage
|
|
||||||
stageID := pkt.StageID
|
|
||||||
s.server.stagesLock.Lock()
|
|
||||||
stage, gotStage := s.server.stages[stageID]
|
|
||||||
s.server.stagesLock.Unlock()
|
|
||||||
|
|
||||||
// If we got the stage, lock and set the data.
|
|
||||||
if gotStage {
|
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
|
stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
} else {
|
} else {
|
||||||
s.logger.Warn("Failed to get stage", zap.String("StageID", stageID))
|
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||||
}
|
}
|
||||||
s.logger.Debug("handleMsgSysSetStageBinary Done!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysGetStageBinary)
|
pkt := p.(*mhfpacket.MsgSysGetStageBinary)
|
||||||
|
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||||
// Try to get the stage
|
|
||||||
stageID := pkt.StageID
|
|
||||||
s.server.stagesLock.Lock()
|
|
||||||
stage, gotStage := s.server.stages[stageID]
|
|
||||||
s.server.stagesLock.Unlock()
|
|
||||||
|
|
||||||
// If we got the stage, lock and try to get the data.
|
|
||||||
var stageBinary []byte
|
|
||||||
var gotBinary bool
|
|
||||||
if gotStage {
|
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stageBinary, gotBinary = stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
if binaryData, exists := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]; exists {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, binaryData)
|
||||||
|
} else if pkt.BinaryType1 == 4 {
|
||||||
|
// Unknown binary type that is supposedly generated server side
|
||||||
|
// Temporary response
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||||
|
} else {
|
||||||
|
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")
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||||
|
}
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
} else {
|
} else {
|
||||||
s.logger.Warn("Failed to get stage", zap.String("StageID", stageID))
|
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||||
}
|
}
|
||||||
|
|
||||||
if gotBinary {
|
|
||||||
doAckBufSucceed(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})
|
|
||||||
|
|
||||||
// TODO(Andoryuuta): This doesn't fit a normal ack packet? where is this from?
|
|
||||||
// This would be a buffered(0x01), non-error(0x00), with no data payload (size 0x00, 0x00) packet.
|
|
||||||
// but for some reason has a 0x10 on the end that the client shouldn't parse?
|
|
||||||
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{}) // Without the previous 0x10 suffix
|
|
||||||
} else {
|
|
||||||
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")
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.Debug("MsgSysGetStageBinary Done!")
|
s.logger.Debug("MsgSysGetStageBinary Done!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgSysWaitStageBinary)
|
||||||
|
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||||
|
if pkt.BinaryType0 == 1 && pkt.BinaryType1 == 12 {
|
||||||
|
// This might contain the hunter count, or max player count?
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
s.logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
||||||
|
stage.Lock()
|
||||||
|
stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
||||||
|
stage.Unlock()
|
||||||
|
s.logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
||||||
|
if gotBinary {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, stageBinary)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
s.logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||||
|
}
|
||||||
|
s.logger.Debug("MsgSysWaitStageBinary Done!")
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysEnumerateStage)
|
pkt := p.(*mhfpacket.MsgSysEnumerateStage)
|
||||||
|
|
||||||
@@ -409,14 +394,10 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
joinable++
|
joinable++
|
||||||
|
|
||||||
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Reserved players.
|
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Reserved players.
|
||||||
resp.WriteUint16(0) // Unknown value
|
resp.WriteUint16(0) // Unk
|
||||||
|
resp.WriteUint8(0) // Unk
|
||||||
var hasDeparted uint16
|
resp.WriteBool(len(stage.clients) > 0) // Has departed.
|
||||||
if stage.hasDeparted {
|
resp.WriteUint16(stage.maxPlayers) // Max players.
|
||||||
hasDeparted = 1
|
|
||||||
}
|
|
||||||
resp.WriteUint16(hasDeparted) // HasDeparted.
|
|
||||||
resp.WriteUint16(stage.maxPlayers) // Max players.
|
|
||||||
if len(stage.password) > 0 {
|
if len(stage.password) > 0 {
|
||||||
// This byte has also been seen as 1
|
// This byte has also been seen as 1
|
||||||
// The quest is also recognised as locked when this is 2
|
// The quest is also recognised as locked when this is 2
|
||||||
|
|||||||
@@ -55,10 +55,9 @@ type Stage struct {
|
|||||||
// other clients expect the server to echo them back in the exact same format.
|
// other clients expect the server to echo them back in the exact same format.
|
||||||
rawBinaryData map[stageBinaryKey][]byte
|
rawBinaryData map[stageBinaryKey][]byte
|
||||||
|
|
||||||
maxPlayers uint16
|
maxPlayers uint16
|
||||||
hasDeparted bool
|
password string
|
||||||
password string
|
createdAt string
|
||||||
createdAt string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStage creates a new stage with intialized values.
|
// NewStage creates a new stage with intialized values.
|
||||||
@@ -71,7 +70,7 @@ func NewStage(ID string) *Stage {
|
|||||||
rawBinaryData: make(map[stageBinaryKey][]byte),
|
rawBinaryData: make(map[stageBinaryKey][]byte),
|
||||||
maxPlayers: 4,
|
maxPlayers: 4,
|
||||||
gameObjectCount: 1,
|
gameObjectCount: 1,
|
||||||
objectList: make(map[uint8]*ObjectMap),
|
objectList: make(map[uint8]*ObjectMap),
|
||||||
createdAt: time.Now().Format("01-02-2006 15:04:05"),
|
createdAt: time.Now().Format("01-02-2006 15:04:05"),
|
||||||
}
|
}
|
||||||
s.InitObjectList()
|
s.InitObjectList()
|
||||||
|
|||||||
Reference in New Issue
Block a user