From 094855b98440a078fd8543c5d2dbe7452799c8e3 Mon Sep 17 00:00:00 2001 From: stratic-dev Date: Thu, 17 Oct 2024 20:22:53 +0100 Subject: [PATCH] stage as a /internal/system --- .../sys_stage.go => internal/system/stage.go | 60 +++++---- server/channelserver/chat_commands.go | 20 +-- server/channelserver/handlers.go | 47 +++---- server/channelserver/handlers_cast_binary.go | 2 +- server/channelserver/handlers_clients.go | 8 +- server/channelserver/handlers_object.go | 37 +++--- server/channelserver/handlers_stage.go | 122 +++++++++--------- server/channelserver/sys_channel_server.go | 16 ++- server/channelserver/sys_discord.go | 8 +- server/channelserver/sys_session.go | 15 ++- 10 files changed, 177 insertions(+), 158 deletions(-) rename server/channelserver/sys_stage.go => internal/system/stage.go (57%) diff --git a/server/channelserver/sys_stage.go b/internal/system/stage.go similarity index 57% rename from server/channelserver/sys_stage.go rename to internal/system/stage.go index b6435eed2..93e4e92ae 100644 --- a/server/channelserver/sys_stage.go +++ b/internal/system/stage.go @@ -1,4 +1,4 @@ -package channelserver +package system import ( "sync" @@ -6,18 +6,24 @@ import ( "erupe-ce/network/mhfpacket" ) +type SessionStage interface { + QueueSendMHF(packet mhfpacket.MHFPacket) + GetCharID() uint32 + GetName() string +} + // Object holds infomation about a specific object. type Object struct { sync.RWMutex - id uint32 - ownerCharID uint32 - x, y, z float32 + Id uint32 + OwnerCharID uint32 + X, Y, Z float32 } // stageBinaryKey is a struct used as a map key for identifying a stage binary part. -type stageBinaryKey struct { - id0 uint8 - id1 uint8 +type StageBinaryKey struct { + Id0 uint8 + Id1 uint8 } // Stage holds stage-specific information @@ -25,49 +31,49 @@ type Stage struct { sync.RWMutex // Stage ID string - id string + Id string // Objects - objects map[uint32]*Object + Objects map[uint32]*Object objectIndex uint8 // Map of session -> charID. // These are clients that are CURRENTLY in the stage - clients map[*Session]uint32 + Clients map[SessionStage]uint32 // Map of charID -> bool, key represents whether they are ready // These are clients that aren't in the stage, but have reserved a slot (for quests, etc). - reservedClientSlots map[uint32]bool + ReservedClientSlots map[uint32]bool // These are raw binary blobs that the stage owner sets, // other clients expect the server to echo them back in the exact same format. - rawBinaryData map[stageBinaryKey][]byte + RawBinaryData map[StageBinaryKey][]byte - host *Session - maxPlayers uint16 - password string - locked bool + Host SessionStage + MaxPlayers uint16 + Password string + Locked bool } // NewStage creates a new stage with intialized values. func NewStage(ID string) *Stage { s := &Stage{ - id: ID, - clients: make(map[*Session]uint32), - reservedClientSlots: make(map[uint32]bool), - objects: make(map[uint32]*Object), + Id: ID, + Clients: make(map[SessionStage]uint32), + ReservedClientSlots: make(map[uint32]bool), + Objects: make(map[uint32]*Object), objectIndex: 0, - rawBinaryData: make(map[stageBinaryKey][]byte), - maxPlayers: 127, + RawBinaryData: make(map[StageBinaryKey][]byte), + MaxPlayers: 127, } return s } // BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage. -func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { +func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession SessionStage) { s.Lock() defer s.Unlock() - for session := range s.clients { + for session := range s.Clients { if session == ignoredSession { continue } @@ -76,13 +82,13 @@ func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { } func (s *Stage) isCharInQuestByID(charID uint32) bool { - if _, exists := s.reservedClientSlots[charID]; exists { + if _, exists := s.ReservedClientSlots[charID]; exists { return exists } return false } -func (s *Stage) isQuest() bool { - return len(s.reservedClientSlots) > 0 +func (s *Stage) IsQuest() bool { + return len(s.ReservedClientSlots) > 0 } diff --git a/server/channelserver/chat_commands.go b/server/channelserver/chat_commands.go index e58a48e7e..b3be672f8 100644 --- a/server/channelserver/chat_commands.go +++ b/server/channelserver/chat_commands.go @@ -146,11 +146,11 @@ func psn(s *Session, args []string) error { func reload(s *Session, _ []string) error { s.sendMessage(t("commands.reload", v{})) var temp mhfpacket.MHFPacket - for _, object := range s.stage.objects { - if object.ownerCharID == s.CharID { + for _, object := range s.stage.Objects { + if object.OwnerCharID == s.CharID { continue } - temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id} + temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.Id} s.QueueSendMHF(temp) } for _, session := range s.Server.sessions { @@ -175,17 +175,17 @@ func reload(s *Session, _ []string) error { s.QueueSendMHF(temp) } } - for _, obj := range s.stage.objects { - if obj.ownerCharID == s.CharID { + for _, obj := range s.stage.Objects { + if obj.OwnerCharID == s.CharID { continue } temp = &mhfpacket.MsgSysDuplicateObject{ - ObjID: obj.id, - X: obj.x, - Y: obj.y, - Z: obj.z, + ObjID: obj.Id, + X: obj.X, + Y: obj.Y, + Z: obj.Z, Unk0: 0, - OwnerCharID: obj.ownerCharID, + OwnerCharID: obj.OwnerCharID, } s.QueueSendMHF(temp) } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 57a505be1..b149ae504 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "erupe-ce/config" "erupe-ce/internal/model" + "erupe-ce/internal/system" "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/mhfcourse" @@ -155,18 +156,18 @@ func logoutPlayer(s *Session) { for _, stage := range s.Server.stages { // Tell sessions registered to disconnecting players quest to unregister - if stage.host != nil && stage.host.CharID == s.CharID { + if stage.Host != nil && stage.Host.GetCharID() == s.CharID { for _, sess := range s.Server.sessions { - for rSlot := range stage.reservedClientSlots { - if sess.CharID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" { + for rSlot := range stage.ReservedClientSlots { + if sess.CharID == rSlot && sess.stage != nil && sess.stage.Id[3:5] != "Qs" { sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) } } } } - for session := range stage.clients { - if session.CharID == s.CharID { - delete(stage.clients, session) + for session := range stage.Clients { + if session.GetCharID() == s.CharID { + delete(stage.Clients, session) } } } @@ -211,8 +212,8 @@ func logoutPlayer(s *Session) { s.Server.Lock() for _, stage := range s.Server.stages { - if _, exists := stage.reservedClientSlots[s.CharID]; exists { - delete(stage.reservedClientSlots, s.CharID) + if _, exists := stage.ReservedClientSlots[s.CharID]; exists { + delete(stage.ReservedClientSlots, s.CharID) } } s.Server.Unlock() @@ -285,7 +286,7 @@ func handleMsgSysRecordLog(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { } } // remove a client returning to town from reserved slots to make sure the stage is hidden from board - delete(s.stage.reservedClientSlots, s.CharID) + delete(s.stage.ReservedClientSlots, s.CharID) s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4)) } @@ -377,12 +378,12 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) if pkt.SearchType == 2 && !strings.Contains(session.Name, term) { continue } - if pkt.SearchType == 3 && session.Server.IP != ip && session.Server.Port != port && session.stage.id != term { + if pkt.SearchType == 3 && session.Server.IP != ip && session.Server.Port != port && session.stage.Id != term { continue } count++ sessionName := stringsupport.UTF8ToSJIS(session.Name) - sessionStage := stringsupport.UTF8ToSJIS(session.stage.id) + sessionStage := stringsupport.UTF8ToSJIS(session.stage.Id) if !local { resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) } else { @@ -497,8 +498,8 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) if count == maxResults { break } - if strings.HasPrefix(stage.id, findPartyParams.StagePrefix) { - sb3 := byteframe.NewByteFrameFromBytes(stage.rawBinaryData[stageBinaryKey{1, 3}]) + if strings.HasPrefix(stage.Id, findPartyParams.StagePrefix) { + sb3 := byteframe.NewByteFrameFromBytes(stage.RawBinaryData[system.StageBinaryKey{1, 3}]) sb3.Seek(4, 0) stageDataParams := 7 @@ -546,17 +547,17 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) resp.WriteUint16(0) // Static? resp.WriteUint16(0) // Unk, [0 1 2] - resp.WriteUint16(uint16(len(stage.clients) + len(stage.reservedClientSlots))) - resp.WriteUint16(stage.maxPlayers) + resp.WriteUint16(uint16(len(stage.Clients) + len(stage.ReservedClientSlots))) + resp.WriteUint16(stage.MaxPlayers) // TODO: Retail returned the number of clients in quests, not workshop/my series - resp.WriteUint16(uint16(len(stage.reservedClientSlots))) + resp.WriteUint16(uint16(len(stage.ReservedClientSlots))) resp.WriteUint8(0) // Static? - resp.WriteUint8(uint8(stage.maxPlayers)) + resp.WriteUint8(uint8(stage.MaxPlayers)) resp.WriteUint8(1) // Static? - resp.WriteUint8(uint8(len(stage.id) + 1)) - resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 0}]))) - resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 1}]))) + resp.WriteUint8(uint8(len(stage.Id) + 1)) + resp.WriteUint8(uint8(len(stage.RawBinaryData[system.StageBinaryKey{1, 0}]))) + resp.WriteUint8(uint8(len(stage.RawBinaryData[system.StageBinaryKey{1, 1}]))) for i := range stageData { if config.GetConfig().ClientID >= config.Z1 { @@ -568,9 +569,9 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) resp.WriteUint8(0) // Unk resp.WriteUint8(0) // Unk - resp.WriteNullTerminatedBytes([]byte(stage.id)) - resp.WriteBytes(stage.rawBinaryData[stageBinaryKey{1, 0}]) - resp.WriteBytes(stage.rawBinaryData[stageBinaryKey{1, 1}]) + resp.WriteNullTerminatedBytes([]byte(stage.Id)) + resp.WriteBytes(stage.RawBinaryData[system.StageBinaryKey{1, 0}]) + resp.WriteBytes(stage.RawBinaryData[system.StageBinaryKey{1, 1}]) } } } diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index c190fa599..f61593429 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -147,7 +147,7 @@ func handleMsgSysCastBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { } return } - if (pkt.BroadcastType == constant.BroadcastTypeStage && s.stage.id == "sl1Ns200p0a0u0") || pkt.BroadcastType == constant.BroadcastTypeWorld { + if (pkt.BroadcastType == constant.BroadcastTypeStage && s.stage.Id == "sl1Ns200p0a0u0") || pkt.BroadcastType == constant.BroadcastTypeWorld { s.Server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) } } diff --git a/server/channelserver/handlers_clients.go b/server/channelserver/handlers_clients.go index 8d8871af6..c657ffc4d 100644 --- a/server/channelserver/handlers_clients.go +++ b/server/channelserver/handlers_clients.go @@ -28,20 +28,20 @@ func handleMsgSysEnumerateClient(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) var clients []uint32 switch pkt.Get { case 0: // All - for _, cid := range stage.clients { + for _, cid := range stage.Clients { clients = append(clients, cid) } - for cid := range stage.reservedClientSlots { + for cid := range stage.ReservedClientSlots { clients = append(clients, cid) } case 1: // Not ready - for cid, ready := range stage.reservedClientSlots { + for cid, ready := range stage.ReservedClientSlots { if !ready { clients = append(clients, cid) } } case 2: // Ready - for cid, ready := range stage.reservedClientSlots { + for cid, ready := range stage.ReservedClientSlots { if ready { clients = append(clients, cid) } diff --git a/server/channelserver/handlers_object.go b/server/channelserver/handlers_object.go index 2b03cc5c1..b1c68a668 100644 --- a/server/channelserver/handlers_object.go +++ b/server/channelserver/handlers_object.go @@ -4,6 +4,7 @@ import ( "fmt" "erupe-ce/config" + "erupe-ce/internal/system" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" @@ -14,30 +15,30 @@ func handleMsgSysCreateObject(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateObject) s.stage.Lock() - newObj := &Object{ - id: s.NextObjectID(), - ownerCharID: s.CharID, - x: pkt.X, - y: pkt.Y, - z: pkt.Z, + newObj := &system.Object{ + Id: s.NextObjectID(), + OwnerCharID: s.CharID, + X: pkt.X, + Y: pkt.Y, + Z: pkt.Z, } - s.stage.objects[s.CharID] = newObj + s.stage.Objects[s.CharID] = newObj s.stage.Unlock() // Response to our requesting client. resp := byteframe.NewByteFrame() - resp.WriteUint32(newObj.id) // New local obj handle. + resp.WriteUint32(newObj.Id) // New local obj handle. s.DoAckSimpleSucceed(pkt.AckHandle, resp.Data()) // Duplicate the object creation to all sessions in the same stage. dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{ - ObjID: newObj.id, - X: newObj.x, - Y: newObj.y, - Z: newObj.z, - OwnerCharID: newObj.ownerCharID, + ObjID: newObj.Id, + X: newObj.X, + Y: newObj.Y, + Z: newObj.Z, + OwnerCharID: newObj.OwnerCharID, } - s.Logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id)) + s.Logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.Id)) s.stage.BroadcastMHF(dupObjUpdate, s) } @@ -49,11 +50,11 @@ func handleMsgSysPositionObject(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) fmt.Printf("[%s] with objectID [%d] move to (%f,%f,%f)\n\n", s.Name, pkt.ObjID, pkt.X, pkt.Y, pkt.Z) } s.stage.Lock() - object, ok := s.stage.objects[s.CharID] + object, ok := s.stage.Objects[s.CharID] if ok { - object.x = pkt.X - object.y = pkt.Y - object.z = pkt.Z + object.X = pkt.X + object.Y = pkt.Y + object.Z = pkt.Z } s.stage.Unlock() // One of the few packets we can just re-broadcast directly. diff --git a/server/channelserver/handlers_stage.go b/server/channelserver/handlers_stage.go index 60bba23fa..81e8f66f4 100644 --- a/server/channelserver/handlers_stage.go +++ b/server/channelserver/handlers_stage.go @@ -5,8 +5,10 @@ import ( "strings" "time" + "erupe-ce/internal/system" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + ps "erupe-ce/utils/pascalstring" "github.com/jmoiron/sqlx" @@ -20,10 +22,10 @@ func handleMsgSysCreateStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { if _, exists := s.Server.stages[pkt.StageID]; exists { s.DoAckSimpleFail(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } else { - stage := NewStage(pkt.StageID) - stage.host = s - stage.maxPlayers = uint16(pkt.PlayerCount) - s.Server.stages[stage.id] = stage + stage := system.NewStage(pkt.StageID) + stage.Host = s + stage.MaxPlayers = uint16(pkt.PlayerCount) + s.Server.stages[stage.Id] = stage s.DoAckSimpleSucceed(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } } @@ -37,16 +39,16 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { if exists { stage.Lock() - stage.clients[s] = s.CharID + stage.Clients[s] = s.CharID stage.Unlock() } else { // Create new stage object s.Server.Lock() - s.Server.stages[stageID] = NewStage(stageID) + s.Server.stages[stageID] = system.NewStage(stageID) stage = s.Server.stages[stageID] s.Server.Unlock() stage.Lock() - stage.host = s - stage.clients[s] = s.CharID + stage.Host = s + stage.Clients[s] = s.CharID stage.Unlock() } @@ -92,17 +94,17 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { // Notify the client to duplicate the existing objects. s.Logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name)) s.stage.RLock() - for _, obj := range s.stage.objects { - if obj.ownerCharID == s.CharID { + for _, obj := range s.stage.Objects { + if obj.OwnerCharID == s.CharID { continue } temp = &mhfpacket.MsgSysDuplicateObject{ - ObjID: obj.id, - X: obj.x, - Y: obj.y, - Z: obj.z, + ObjID: obj.Id, + X: obj.X, + Y: obj.Y, + Z: obj.Z, Unk0: 0, - OwnerCharID: obj.ownerCharID, + OwnerCharID: obj.OwnerCharID, } s.QueueSendMHF(temp) } @@ -115,10 +117,10 @@ func destructEmptyStages(s *Session) { defer s.Server.Unlock() for _, stage := range s.Server.stages { // Destroy empty Quest/My series/Guild stages. - if stage.id[3:5] == "Qs" || stage.id[3:5] == "Ms" || stage.id[3:5] == "Gs" || stage.id[3:5] == "Ls" { - 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)) + if stage.Id[3:5] == "Qs" || stage.Id[3:5] == "Ms" || stage.Id[3:5] == "Gs" || stage.Id[3:5] == "Ls" { + 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)) } } } @@ -126,14 +128,14 @@ func destructEmptyStages(s *Session) { func removeSessionFromStage(s *Session) { // Remove client from old stage. - delete(s.stage.clients, s) + delete(s.stage.Clients, s) // Delete old stage objects owned by the client. s.Logger.Info("Sending notification to old stage clients") - for _, object := range s.stage.objects { - if object.ownerCharID == s.CharID { - s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s) - delete(s.stage.objects, object.ownerCharID) + for _, object := range s.stage.Objects { + if object.OwnerCharID == s.CharID { + s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.Id}, s) + delete(s.stage.Objects, object.OwnerCharID) } } destructEmptyStages(s) @@ -142,10 +144,10 @@ func removeSessionFromStage(s *Session) { func isStageFull(s *Session, StageID string) bool { if stage, exists := s.Server.stages[StageID]; exists { - if _, exists := stage.reservedClientSlots[s.CharID]; exists { + if _, exists := stage.ReservedClientSlots[s.CharID]; exists { return false } - return len(stage.reservedClientSlots)+len(stage.clients) >= int(stage.maxPlayers) + return len(stage.ReservedClientSlots)+len(stage.Clients) >= int(stage.MaxPlayers) } return false } @@ -161,9 +163,9 @@ func handleMsgSysEnterStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { // Push our current stage ID to the movement stack before entering another one. if s.stage != nil { s.stage.Lock() - s.stage.reservedClientSlots[s.CharID] = false + s.stage.ReservedClientSlots[s.CharID] = false s.stage.Unlock() - s.stageMoveStack.Push(s.stage.id) + s.stageMoveStack.Push(s.stage.Id) } if s.reservationStage != nil { @@ -188,12 +190,12 @@ func handleMsgSysBackStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { return } - if _, exists := s.stage.reservedClientSlots[s.CharID]; exists { - delete(s.stage.reservedClientSlots, s.CharID) + if _, exists := s.stage.ReservedClientSlots[s.CharID]; exists { + delete(s.stage.ReservedClientSlots, s.CharID) } - if _, exists := s.Server.stages[backStage].reservedClientSlots[s.CharID]; exists { - delete(s.Server.stages[backStage].reservedClientSlots, s.CharID) + if _, exists := s.Server.stages[backStage].ReservedClientSlots[s.CharID]; exists { + delete(s.Server.stages[backStage].ReservedClientSlots, s.CharID) } doStageTransfer(s, pkt.AckHandle, backStage) @@ -216,7 +218,7 @@ func handleMsgSysLockStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLockStage) if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() - stage.locked = true + stage.Locked = true stage.Unlock() } s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4)) @@ -227,14 +229,14 @@ func handleMsgSysUnlockStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { s.reservationStage.RLock() defer s.reservationStage.RUnlock() - for charID := range s.reservationStage.reservedClientSlots { + for charID := range s.reservationStage.ReservedClientSlots { session := s.Server.FindSessionByCharID(charID) if session != nil { session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) } } - delete(s.Server.stages, s.reservationStage.id) + delete(s.Server.stages, s.reservationStage.Id) } destructEmptyStages(s) @@ -245,26 +247,26 @@ func handleMsgSysReserveStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() defer stage.Unlock() - if _, exists := stage.reservedClientSlots[s.CharID]; exists { + if _, exists := stage.ReservedClientSlots[s.CharID]; exists { switch pkt.Ready { case 1: // 0x01 - stage.reservedClientSlots[s.CharID] = false + stage.ReservedClientSlots[s.CharID] = false case 17: // 0x11 - stage.reservedClientSlots[s.CharID] = true + stage.ReservedClientSlots[s.CharID] = true } s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4)) - } else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers { - if stage.locked { + } else if uint16(len(stage.ReservedClientSlots)) < stage.MaxPlayers { + if stage.Locked { s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4)) return } - if len(stage.password) > 0 { - if stage.password != s.stagePass { + if len(stage.Password) > 0 { + if stage.Password != s.stagePass { s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4)) return } } - stage.reservedClientSlots[s.CharID] = false + stage.ReservedClientSlots[s.CharID] = false // Save the reservation stage in the session for later use in MsgSysUnreserveStage. s.Lock() s.reservationStage = stage @@ -286,8 +288,8 @@ func handleMsgSysUnreserveStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) s.Unlock() if stage != nil { stage.Lock() - if _, exists := stage.reservedClientSlots[s.CharID]; exists { - delete(stage.reservedClientSlots, s.CharID) + if _, exists := stage.ReservedClientSlots[s.CharID]; exists { + delete(stage.ReservedClientSlots, s.CharID) } stage.Unlock() } @@ -301,8 +303,8 @@ func handleMsgSysSetStagePass(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) { if stage != nil { stage.Lock() // Will only exist if host. - if _, exists := stage.reservedClientSlots[s.CharID]; exists { - stage.password = pkt.Password + if _, exists := stage.ReservedClientSlots[s.CharID]; exists { + stage.Password = pkt.Password } stage.Unlock() } else { @@ -317,7 +319,7 @@ func handleMsgSysSetStageBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) pkt := p.(*mhfpacket.MsgSysSetStageBinary) if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() - stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload + stage.RawBinaryData[system.StageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload stage.Unlock() } else { s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) @@ -328,7 +330,7 @@ func handleMsgSysGetStageBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) pkt := p.(*mhfpacket.MsgSysGetStageBinary) if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() - if binaryData, exists := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]; exists { + if binaryData, exists := stage.RawBinaryData[system.StageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]; exists { s.DoAckBufSucceed(pkt.AckHandle, binaryData) } else if pkt.BinaryType1 == 4 { // Unknown binary type that is supposedly generated server side @@ -357,7 +359,7 @@ func handleMsgSysWaitStageBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) for { s.Logger.Debug("MsgSysWaitStageBinary before lock and get stage") stage.Lock() - stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] + stageBinary, gotBinary := stage.RawBinaryData[system.StageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] stage.Unlock() s.Logger.Debug("MsgSysWaitStageBinary after lock and get stage") if gotBinary { @@ -389,29 +391,29 @@ func handleMsgSysEnumerateStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) for sid, stage := range s.Server.stages { stage.RLock() - if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 { + if len(stage.ReservedClientSlots) == 0 && len(stage.Clients) == 0 { stage.RUnlock() continue } - if !strings.Contains(stage.id, pkt.StagePrefix) { + if !strings.Contains(stage.Id, pkt.StagePrefix) { stage.RUnlock() continue } joinable++ - bf.WriteUint16(uint16(len(stage.reservedClientSlots))) - bf.WriteUint16(uint16(len(stage.clients))) - if strings.HasPrefix(stage.id, "sl2Ls") { - bf.WriteUint16(uint16(len(stage.clients) + len(stage.reservedClientSlots))) + bf.WriteUint16(uint16(len(stage.ReservedClientSlots))) + bf.WriteUint16(uint16(len(stage.Clients))) + if strings.HasPrefix(stage.Id, "sl2Ls") { + bf.WriteUint16(uint16(len(stage.Clients) + len(stage.ReservedClientSlots))) } else { - bf.WriteUint16(uint16(len(stage.clients))) + bf.WriteUint16(uint16(len(stage.Clients))) } - bf.WriteUint16(stage.maxPlayers) + bf.WriteUint16(stage.MaxPlayers) var flags uint8 - if stage.locked { + if stage.Locked { flags |= 1 } - if len(stage.password) > 0 { + if len(stage.Password) > 0 { flags |= 2 } bf.WriteUint8(flags) diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index e019b9407..76f554d9a 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -7,8 +7,10 @@ import ( "time" "erupe-ce/config" + "erupe-ce/internal/system" "erupe-ce/server/discordbot" "erupe-ce/utils/db" + "erupe-ce/utils/gametime" "erupe-ce/utils/logger" @@ -47,7 +49,7 @@ type ChannelServer struct { isShuttingDown bool stagesLock sync.RWMutex - stages map[string]*Stage + stages map[string]*system.Stage // Used to map different languages i18n i18n @@ -82,9 +84,9 @@ func NewServer(config *Config) *ChannelServer { "sl2Ns379p0a0u0", // Diva fountain "sl1Ns462p0a0u0", // MezFes } - stages := make(map[string]*Stage) + stages := make(map[string]*system.Stage) for _, name := range stageNames { - stages[name] = NewStage(name) + stages[name] = system.NewStage(name) } server := &ChannelServer{ ID: config.ID, @@ -228,14 +230,14 @@ func (server *ChannelServer) DisconnectUser(uid uint32) { } } -func (server *ChannelServer) FindObjectByChar(charID uint32) *Object { +func (server *ChannelServer) FindObjectByChar(charID uint32) *system.Object { server.stagesLock.RLock() defer server.stagesLock.RUnlock() for _, stage := range server.stages { stage.RLock() - for objId := range stage.objects { - obj := stage.objects[objId] - if obj.ownerCharID == charID { + for objId := range stage.Objects { + obj := stage.Objects[objId] + if obj.OwnerCharID == charID { stage.RUnlock() return obj } diff --git a/server/channelserver/sys_discord.go b/server/channelserver/sys_discord.go index a5182b599..339b48951 100644 --- a/server/channelserver/sys_discord.go +++ b/server/channelserver/sys_discord.go @@ -22,17 +22,17 @@ func getPlayerSlice(server *ChannelServer) []Player { for _, channel := range server.Channels { for _, stage := range channel.stages { - if len(stage.clients) == 0 { + if len(stage.Clients) == 0 { continue } questID := 0 - if stage.isQuest() { + if stage.IsQuest() { questIndex++ questID = questIndex } - for client := range stage.clients { + for client := range stage.Clients { p = append(p, Player{ - CharName: client.Name, + CharName: client.GetName(), QuestID: questID, }) } diff --git a/server/channelserver/sys_session.go b/server/channelserver/sys_session.go index c00e3ad77..94685eaf6 100644 --- a/server/channelserver/sys_session.go +++ b/server/channelserver/sys_session.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "erupe-ce/config" "erupe-ce/internal/constant" + "erupe-ce/internal/system" "erupe-ce/network" "erupe-ce/network/binpacket" "erupe-ce/network/mhfpacket" @@ -36,10 +37,10 @@ type Session struct { objectIndex uint16 userEnteredStage bool // If the user has entered a stage before - stage *Stage - reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet. - stagePass string // Temporary storage - prevGuildID uint32 // Stores the last GuildID used in InfoGuild + stage *system.Stage + reservationStage *system.Stage // Required for the stateful MsgSysUnreserveStage packet. + stagePass string // Temporary storage + prevGuildID uint32 // Stores the last GuildID used in InfoGuild CharID uint32 logKey []byte sessionStart int64 @@ -371,3 +372,9 @@ func (s *Session) DoAckSimpleFail(ackHandle uint32, data []byte) { AckData: data, }) } +func (s *Session) GetCharID() uint32 { + return s.CharID // Assuming `Session` has a field `CharID` +} +func (s *Session) GetName() string { + return s.Name // Assuming `Session` has a field `CharID` +}