mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-16 17:05:03 +01:00
stage as a /internal/system
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
package channelserver
|
package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@@ -6,18 +6,24 @@ import (
|
|||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SessionStage interface {
|
||||||
|
QueueSendMHF(packet mhfpacket.MHFPacket)
|
||||||
|
GetCharID() uint32
|
||||||
|
GetName() string
|
||||||
|
}
|
||||||
|
|
||||||
// Object holds infomation about a specific object.
|
// Object holds infomation about a specific object.
|
||||||
type Object struct {
|
type Object struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
id uint32
|
Id uint32
|
||||||
ownerCharID uint32
|
OwnerCharID uint32
|
||||||
x, y, z float32
|
X, Y, Z float32
|
||||||
}
|
}
|
||||||
|
|
||||||
// stageBinaryKey is a struct used as a map key for identifying a stage binary part.
|
// stageBinaryKey is a struct used as a map key for identifying a stage binary part.
|
||||||
type stageBinaryKey struct {
|
type StageBinaryKey struct {
|
||||||
id0 uint8
|
Id0 uint8
|
||||||
id1 uint8
|
Id1 uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stage holds stage-specific information
|
// Stage holds stage-specific information
|
||||||
@@ -25,49 +31,49 @@ type Stage struct {
|
|||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
// Stage ID string
|
// Stage ID string
|
||||||
id string
|
Id string
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
objects map[uint32]*Object
|
Objects map[uint32]*Object
|
||||||
objectIndex uint8
|
objectIndex uint8
|
||||||
|
|
||||||
// Map of session -> charID.
|
// Map of session -> charID.
|
||||||
// These are clients that are CURRENTLY in the stage
|
// 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
|
// 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).
|
// 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,
|
// These are raw binary blobs that the stage owner sets,
|
||||||
// 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
|
||||||
|
|
||||||
host *Session
|
Host SessionStage
|
||||||
maxPlayers uint16
|
MaxPlayers uint16
|
||||||
password string
|
Password string
|
||||||
locked bool
|
Locked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStage creates a new stage with intialized values.
|
// NewStage creates a new stage with intialized values.
|
||||||
func NewStage(ID string) *Stage {
|
func NewStage(ID string) *Stage {
|
||||||
s := &Stage{
|
s := &Stage{
|
||||||
id: ID,
|
Id: ID,
|
||||||
clients: make(map[*Session]uint32),
|
Clients: make(map[SessionStage]uint32),
|
||||||
reservedClientSlots: make(map[uint32]bool),
|
ReservedClientSlots: make(map[uint32]bool),
|
||||||
objects: make(map[uint32]*Object),
|
Objects: make(map[uint32]*Object),
|
||||||
objectIndex: 0,
|
objectIndex: 0,
|
||||||
rawBinaryData: make(map[stageBinaryKey][]byte),
|
RawBinaryData: make(map[StageBinaryKey][]byte),
|
||||||
maxPlayers: 127,
|
MaxPlayers: 127,
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage.
|
// 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()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
for session := range s.clients {
|
for session := range s.Clients {
|
||||||
if session == ignoredSession {
|
if session == ignoredSession {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -76,13 +82,13 @@ func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stage) isCharInQuestByID(charID uint32) bool {
|
func (s *Stage) isCharInQuestByID(charID uint32) bool {
|
||||||
if _, exists := s.reservedClientSlots[charID]; exists {
|
if _, exists := s.ReservedClientSlots[charID]; exists {
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stage) isQuest() bool {
|
func (s *Stage) IsQuest() bool {
|
||||||
return len(s.reservedClientSlots) > 0
|
return len(s.ReservedClientSlots) > 0
|
||||||
}
|
}
|
||||||
@@ -146,11 +146,11 @@ func psn(s *Session, args []string) error {
|
|||||||
func reload(s *Session, _ []string) error {
|
func reload(s *Session, _ []string) error {
|
||||||
s.sendMessage(t("commands.reload", v{}))
|
s.sendMessage(t("commands.reload", v{}))
|
||||||
var temp mhfpacket.MHFPacket
|
var temp mhfpacket.MHFPacket
|
||||||
for _, object := range s.stage.objects {
|
for _, object := range s.stage.Objects {
|
||||||
if object.ownerCharID == s.CharID {
|
if object.OwnerCharID == s.CharID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id}
|
temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.Id}
|
||||||
s.QueueSendMHF(temp)
|
s.QueueSendMHF(temp)
|
||||||
}
|
}
|
||||||
for _, session := range s.Server.sessions {
|
for _, session := range s.Server.sessions {
|
||||||
@@ -175,17 +175,17 @@ func reload(s *Session, _ []string) error {
|
|||||||
s.QueueSendMHF(temp)
|
s.QueueSendMHF(temp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, obj := range s.stage.objects {
|
for _, obj := range s.stage.Objects {
|
||||||
if obj.ownerCharID == s.CharID {
|
if obj.OwnerCharID == s.CharID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
temp = &mhfpacket.MsgSysDuplicateObject{
|
temp = &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,
|
||||||
}
|
}
|
||||||
s.QueueSendMHF(temp)
|
s.QueueSendMHF(temp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"erupe-ce/config"
|
"erupe-ce/config"
|
||||||
"erupe-ce/internal/model"
|
"erupe-ce/internal/model"
|
||||||
|
"erupe-ce/internal/system"
|
||||||
"erupe-ce/utils/db"
|
"erupe-ce/utils/db"
|
||||||
"erupe-ce/utils/gametime"
|
"erupe-ce/utils/gametime"
|
||||||
"erupe-ce/utils/mhfcourse"
|
"erupe-ce/utils/mhfcourse"
|
||||||
@@ -155,18 +156,18 @@ func logoutPlayer(s *Session) {
|
|||||||
|
|
||||||
for _, stage := range s.Server.stages {
|
for _, stage := range s.Server.stages {
|
||||||
// Tell sessions registered to disconnecting players quest to unregister
|
// 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 _, sess := range s.Server.sessions {
|
||||||
for rSlot := range stage.reservedClientSlots {
|
for rSlot := range stage.ReservedClientSlots {
|
||||||
if sess.CharID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" {
|
if sess.CharID == rSlot && sess.stage != nil && sess.stage.Id[3:5] != "Qs" {
|
||||||
sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for session := range stage.clients {
|
for session := range stage.Clients {
|
||||||
if session.CharID == s.CharID {
|
if session.GetCharID() == s.CharID {
|
||||||
delete(stage.clients, session)
|
delete(stage.Clients, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,8 +212,8 @@ func logoutPlayer(s *Session) {
|
|||||||
|
|
||||||
s.Server.Lock()
|
s.Server.Lock()
|
||||||
for _, stage := range s.Server.stages {
|
for _, stage := range s.Server.stages {
|
||||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
if _, exists := stage.ReservedClientSlots[s.CharID]; exists {
|
||||||
delete(stage.reservedClientSlots, s.CharID)
|
delete(stage.ReservedClientSlots, s.CharID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Server.Unlock()
|
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
|
// 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))
|
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) {
|
if pkt.SearchType == 2 && !strings.Contains(session.Name, term) {
|
||||||
continue
|
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
|
continue
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
sessionName := stringsupport.UTF8ToSJIS(session.Name)
|
sessionName := stringsupport.UTF8ToSJIS(session.Name)
|
||||||
sessionStage := stringsupport.UTF8ToSJIS(session.stage.id)
|
sessionStage := stringsupport.UTF8ToSJIS(session.stage.Id)
|
||||||
if !local {
|
if !local {
|
||||||
resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4()))
|
resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4()))
|
||||||
} else {
|
} else {
|
||||||
@@ -497,8 +498,8 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
if count == maxResults {
|
if count == maxResults {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(stage.id, findPartyParams.StagePrefix) {
|
if strings.HasPrefix(stage.Id, findPartyParams.StagePrefix) {
|
||||||
sb3 := byteframe.NewByteFrameFromBytes(stage.rawBinaryData[stageBinaryKey{1, 3}])
|
sb3 := byteframe.NewByteFrameFromBytes(stage.RawBinaryData[system.StageBinaryKey{1, 3}])
|
||||||
sb3.Seek(4, 0)
|
sb3.Seek(4, 0)
|
||||||
|
|
||||||
stageDataParams := 7
|
stageDataParams := 7
|
||||||
@@ -546,17 +547,17 @@ func handleMsgMhfTransitMessage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
|
|
||||||
resp.WriteUint16(0) // Static?
|
resp.WriteUint16(0) // Static?
|
||||||
resp.WriteUint16(0) // Unk, [0 1 2]
|
resp.WriteUint16(0) // Unk, [0 1 2]
|
||||||
resp.WriteUint16(uint16(len(stage.clients) + len(stage.reservedClientSlots)))
|
resp.WriteUint16(uint16(len(stage.Clients) + len(stage.ReservedClientSlots)))
|
||||||
resp.WriteUint16(stage.maxPlayers)
|
resp.WriteUint16(stage.MaxPlayers)
|
||||||
// TODO: Retail returned the number of clients in quests, not workshop/my series
|
// 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(0) // Static?
|
||||||
resp.WriteUint8(uint8(stage.maxPlayers))
|
resp.WriteUint8(uint8(stage.MaxPlayers))
|
||||||
resp.WriteUint8(1) // Static?
|
resp.WriteUint8(1) // Static?
|
||||||
resp.WriteUint8(uint8(len(stage.id) + 1))
|
resp.WriteUint8(uint8(len(stage.Id) + 1))
|
||||||
resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 0}])))
|
resp.WriteUint8(uint8(len(stage.RawBinaryData[system.StageBinaryKey{1, 0}])))
|
||||||
resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 1}])))
|
resp.WriteUint8(uint8(len(stage.RawBinaryData[system.StageBinaryKey{1, 1}])))
|
||||||
|
|
||||||
for i := range stageData {
|
for i := range stageData {
|
||||||
if config.GetConfig().ClientID >= config.Z1 {
|
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.WriteUint8(0) // Unk
|
resp.WriteUint8(0) // Unk
|
||||||
|
|
||||||
resp.WriteNullTerminatedBytes([]byte(stage.id))
|
resp.WriteNullTerminatedBytes([]byte(stage.Id))
|
||||||
resp.WriteBytes(stage.rawBinaryData[stageBinaryKey{1, 0}])
|
resp.WriteBytes(stage.RawBinaryData[system.StageBinaryKey{1, 0}])
|
||||||
resp.WriteBytes(stage.rawBinaryData[stageBinaryKey{1, 1}])
|
resp.WriteBytes(stage.RawBinaryData[system.StageBinaryKey{1, 1}])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ func handleMsgSysCastBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
return
|
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)
|
s.Server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,20 +28,20 @@ func handleMsgSysEnumerateClient(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
var clients []uint32
|
var clients []uint32
|
||||||
switch pkt.Get {
|
switch pkt.Get {
|
||||||
case 0: // All
|
case 0: // All
|
||||||
for _, cid := range stage.clients {
|
for _, cid := range stage.Clients {
|
||||||
clients = append(clients, cid)
|
clients = append(clients, cid)
|
||||||
}
|
}
|
||||||
for cid := range stage.reservedClientSlots {
|
for cid := range stage.ReservedClientSlots {
|
||||||
clients = append(clients, cid)
|
clients = append(clients, cid)
|
||||||
}
|
}
|
||||||
case 1: // Not ready
|
case 1: // Not ready
|
||||||
for cid, ready := range stage.reservedClientSlots {
|
for cid, ready := range stage.ReservedClientSlots {
|
||||||
if !ready {
|
if !ready {
|
||||||
clients = append(clients, cid)
|
clients = append(clients, cid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 2: // Ready
|
case 2: // Ready
|
||||||
for cid, ready := range stage.reservedClientSlots {
|
for cid, ready := range stage.ReservedClientSlots {
|
||||||
if ready {
|
if ready {
|
||||||
clients = append(clients, cid)
|
clients = append(clients, cid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"erupe-ce/config"
|
"erupe-ce/config"
|
||||||
|
"erupe-ce/internal/system"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
"erupe-ce/utils/byteframe"
|
"erupe-ce/utils/byteframe"
|
||||||
|
|
||||||
@@ -14,30 +15,30 @@ func handleMsgSysCreateObject(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysCreateObject)
|
pkt := p.(*mhfpacket.MsgSysCreateObject)
|
||||||
|
|
||||||
s.stage.Lock()
|
s.stage.Lock()
|
||||||
newObj := &Object{
|
newObj := &system.Object{
|
||||||
id: s.NextObjectID(),
|
Id: s.NextObjectID(),
|
||||||
ownerCharID: s.CharID,
|
OwnerCharID: s.CharID,
|
||||||
x: pkt.X,
|
X: pkt.X,
|
||||||
y: pkt.Y,
|
Y: pkt.Y,
|
||||||
z: pkt.Z,
|
Z: pkt.Z,
|
||||||
}
|
}
|
||||||
s.stage.objects[s.CharID] = newObj
|
s.stage.Objects[s.CharID] = newObj
|
||||||
s.stage.Unlock()
|
s.stage.Unlock()
|
||||||
|
|
||||||
// Response to our requesting client.
|
// Response to our requesting client.
|
||||||
resp := byteframe.NewByteFrame()
|
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())
|
s.DoAckSimpleSucceed(pkt.AckHandle, resp.Data())
|
||||||
// Duplicate the object creation to all sessions in the same stage.
|
// Duplicate the object creation to all sessions in the same stage.
|
||||||
dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{
|
dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{
|
||||||
ObjID: newObj.id,
|
ObjID: newObj.Id,
|
||||||
X: newObj.x,
|
X: newObj.X,
|
||||||
Y: newObj.y,
|
Y: newObj.Y,
|
||||||
Z: newObj.z,
|
Z: newObj.Z,
|
||||||
OwnerCharID: newObj.ownerCharID,
|
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)
|
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)
|
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()
|
s.stage.Lock()
|
||||||
object, ok := s.stage.objects[s.CharID]
|
object, ok := s.stage.Objects[s.CharID]
|
||||||
if ok {
|
if ok {
|
||||||
object.x = pkt.X
|
object.X = pkt.X
|
||||||
object.y = pkt.Y
|
object.Y = pkt.Y
|
||||||
object.z = pkt.Z
|
object.Z = pkt.Z
|
||||||
}
|
}
|
||||||
s.stage.Unlock()
|
s.stage.Unlock()
|
||||||
// One of the few packets we can just re-broadcast directly.
|
// One of the few packets we can just re-broadcast directly.
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"erupe-ce/internal/system"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
"erupe-ce/utils/byteframe"
|
"erupe-ce/utils/byteframe"
|
||||||
|
|
||||||
ps "erupe-ce/utils/pascalstring"
|
ps "erupe-ce/utils/pascalstring"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"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 {
|
if _, exists := s.Server.stages[pkt.StageID]; exists {
|
||||||
s.DoAckSimpleFail(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
s.DoAckSimpleFail(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
} else {
|
} else {
|
||||||
stage := NewStage(pkt.StageID)
|
stage := system.NewStage(pkt.StageID)
|
||||||
stage.host = s
|
stage.Host = s
|
||||||
stage.maxPlayers = uint16(pkt.PlayerCount)
|
stage.MaxPlayers = uint16(pkt.PlayerCount)
|
||||||
s.Server.stages[stage.id] = stage
|
s.Server.stages[stage.Id] = stage
|
||||||
s.DoAckSimpleSucceed(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
s.DoAckSimpleSucceed(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,16 +39,16 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stage.clients[s] = s.CharID
|
stage.Clients[s] = s.CharID
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
} else { // Create new stage object
|
} else { // Create new stage object
|
||||||
s.Server.Lock()
|
s.Server.Lock()
|
||||||
s.Server.stages[stageID] = NewStage(stageID)
|
s.Server.stages[stageID] = system.NewStage(stageID)
|
||||||
stage = s.Server.stages[stageID]
|
stage = s.Server.stages[stageID]
|
||||||
s.Server.Unlock()
|
s.Server.Unlock()
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stage.host = s
|
stage.Host = s
|
||||||
stage.clients[s] = s.CharID
|
stage.Clients[s] = s.CharID
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,17 +94,17 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
// Notify the client to duplicate the existing objects.
|
// Notify the client to duplicate the existing objects.
|
||||||
s.Logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
|
s.Logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
|
||||||
s.stage.RLock()
|
s.stage.RLock()
|
||||||
for _, obj := range s.stage.objects {
|
for _, obj := range s.stage.Objects {
|
||||||
if obj.ownerCharID == s.CharID {
|
if obj.OwnerCharID == s.CharID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
temp = &mhfpacket.MsgSysDuplicateObject{
|
temp = &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,
|
||||||
}
|
}
|
||||||
s.QueueSendMHF(temp)
|
s.QueueSendMHF(temp)
|
||||||
}
|
}
|
||||||
@@ -115,10 +117,10 @@ func destructEmptyStages(s *Session) {
|
|||||||
defer s.Server.Unlock()
|
defer s.Server.Unlock()
|
||||||
for _, stage := range s.Server.stages {
|
for _, stage := range s.Server.stages {
|
||||||
// Destroy empty Quest/My series/Guild 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 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 {
|
if len(stage.ReservedClientSlots) == 0 && len(stage.Clients) == 0 {
|
||||||
delete(s.Server.stages, stage.id)
|
delete(s.Server.stages, stage.Id)
|
||||||
s.Logger.Debug("Destructed stage", zap.String("stage.id", 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) {
|
func removeSessionFromStage(s *Session) {
|
||||||
// Remove client from old stage.
|
// Remove client from old stage.
|
||||||
delete(s.stage.clients, s)
|
delete(s.stage.Clients, s)
|
||||||
|
|
||||||
// Delete old stage objects owned by the client.
|
// Delete old stage objects owned by the client.
|
||||||
s.Logger.Info("Sending notification to old stage clients")
|
s.Logger.Info("Sending notification to old stage clients")
|
||||||
for _, object := range s.stage.objects {
|
for _, object := range s.stage.Objects {
|
||||||
if object.ownerCharID == s.CharID {
|
if object.OwnerCharID == s.CharID {
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s)
|
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.Id}, s)
|
||||||
delete(s.stage.objects, object.ownerCharID)
|
delete(s.stage.Objects, object.OwnerCharID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destructEmptyStages(s)
|
destructEmptyStages(s)
|
||||||
@@ -142,10 +144,10 @@ func removeSessionFromStage(s *Session) {
|
|||||||
|
|
||||||
func isStageFull(s *Session, StageID string) bool {
|
func isStageFull(s *Session, StageID string) bool {
|
||||||
if stage, exists := s.Server.stages[StageID]; exists {
|
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 false
|
||||||
}
|
}
|
||||||
return len(stage.reservedClientSlots)+len(stage.clients) >= int(stage.maxPlayers)
|
return len(stage.ReservedClientSlots)+len(stage.Clients) >= int(stage.MaxPlayers)
|
||||||
}
|
}
|
||||||
return false
|
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.
|
// Push our current stage ID to the movement stack before entering another one.
|
||||||
if s.stage != nil {
|
if s.stage != nil {
|
||||||
s.stage.Lock()
|
s.stage.Lock()
|
||||||
s.stage.reservedClientSlots[s.CharID] = false
|
s.stage.ReservedClientSlots[s.CharID] = false
|
||||||
s.stage.Unlock()
|
s.stage.Unlock()
|
||||||
s.stageMoveStack.Push(s.stage.id)
|
s.stageMoveStack.Push(s.stage.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.reservationStage != nil {
|
if s.reservationStage != nil {
|
||||||
@@ -188,12 +190,12 @@ func handleMsgSysBackStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := s.stage.reservedClientSlots[s.CharID]; exists {
|
if _, exists := s.stage.ReservedClientSlots[s.CharID]; exists {
|
||||||
delete(s.stage.reservedClientSlots, s.CharID)
|
delete(s.stage.ReservedClientSlots, s.CharID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := s.Server.stages[backStage].reservedClientSlots[s.CharID]; exists {
|
if _, exists := s.Server.stages[backStage].ReservedClientSlots[s.CharID]; exists {
|
||||||
delete(s.Server.stages[backStage].reservedClientSlots, s.CharID)
|
delete(s.Server.stages[backStage].ReservedClientSlots, s.CharID)
|
||||||
}
|
}
|
||||||
|
|
||||||
doStageTransfer(s, pkt.AckHandle, backStage)
|
doStageTransfer(s, pkt.AckHandle, backStage)
|
||||||
@@ -216,7 +218,7 @@ func handleMsgSysLockStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysLockStage)
|
pkt := p.(*mhfpacket.MsgSysLockStage)
|
||||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stage.locked = true
|
stage.Locked = true
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
}
|
}
|
||||||
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
||||||
@@ -227,14 +229,14 @@ func handleMsgSysUnlockStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
s.reservationStage.RLock()
|
s.reservationStage.RLock()
|
||||||
defer s.reservationStage.RUnlock()
|
defer s.reservationStage.RUnlock()
|
||||||
|
|
||||||
for charID := range s.reservationStage.reservedClientSlots {
|
for charID := range s.reservationStage.ReservedClientSlots {
|
||||||
session := s.Server.FindSessionByCharID(charID)
|
session := s.Server.FindSessionByCharID(charID)
|
||||||
if session != nil {
|
if session != nil {
|
||||||
session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(s.Server.stages, s.reservationStage.id)
|
delete(s.Server.stages, s.reservationStage.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
destructEmptyStages(s)
|
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 {
|
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
defer stage.Unlock()
|
defer stage.Unlock()
|
||||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
if _, exists := stage.ReservedClientSlots[s.CharID]; exists {
|
||||||
switch pkt.Ready {
|
switch pkt.Ready {
|
||||||
case 1: // 0x01
|
case 1: // 0x01
|
||||||
stage.reservedClientSlots[s.CharID] = false
|
stage.ReservedClientSlots[s.CharID] = false
|
||||||
case 17: // 0x11
|
case 17: // 0x11
|
||||||
stage.reservedClientSlots[s.CharID] = true
|
stage.ReservedClientSlots[s.CharID] = true
|
||||||
}
|
}
|
||||||
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
||||||
} else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers {
|
} else if uint16(len(stage.ReservedClientSlots)) < stage.MaxPlayers {
|
||||||
if stage.locked {
|
if stage.Locked {
|
||||||
s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4))
|
s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(stage.password) > 0 {
|
if len(stage.Password) > 0 {
|
||||||
if stage.password != s.stagePass {
|
if stage.Password != s.stagePass {
|
||||||
s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4))
|
s.DoAckSimpleFail(pkt.AckHandle, make([]byte, 4))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage.reservedClientSlots[s.CharID] = false
|
stage.ReservedClientSlots[s.CharID] = false
|
||||||
// Save the reservation stage in the session for later use in MsgSysUnreserveStage.
|
// Save the reservation stage in the session for later use in MsgSysUnreserveStage.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.reservationStage = stage
|
s.reservationStage = stage
|
||||||
@@ -286,8 +288,8 @@ func handleMsgSysUnreserveStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
s.Unlock()
|
s.Unlock()
|
||||||
if stage != nil {
|
if stage != nil {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
if _, exists := stage.ReservedClientSlots[s.CharID]; exists {
|
||||||
delete(stage.reservedClientSlots, s.CharID)
|
delete(stage.ReservedClientSlots, s.CharID)
|
||||||
}
|
}
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
}
|
}
|
||||||
@@ -301,8 +303,8 @@ func handleMsgSysSetStagePass(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
|||||||
if stage != nil {
|
if stage != nil {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
// Will only exist if host.
|
// 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 {
|
||||||
@@ -317,7 +319,7 @@ func handleMsgSysSetStageBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
|
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
|
||||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
|
stage.RawBinaryData[system.StageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
} else {
|
} else {
|
||||||
s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
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)
|
pkt := p.(*mhfpacket.MsgSysGetStageBinary)
|
||||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||||
stage.Lock()
|
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)
|
s.DoAckBufSucceed(pkt.AckHandle, binaryData)
|
||||||
} else if pkt.BinaryType1 == 4 {
|
} else if pkt.BinaryType1 == 4 {
|
||||||
// Unknown binary type that is supposedly generated server side
|
// Unknown binary type that is supposedly generated server side
|
||||||
@@ -357,7 +359,7 @@ func handleMsgSysWaitStageBinary(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
for {
|
for {
|
||||||
s.Logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
s.Logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
||||||
stage.Lock()
|
stage.Lock()
|
||||||
stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
stageBinary, gotBinary := stage.RawBinaryData[system.StageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
||||||
stage.Unlock()
|
stage.Unlock()
|
||||||
s.Logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
s.Logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
||||||
if gotBinary {
|
if gotBinary {
|
||||||
@@ -389,29 +391,29 @@ func handleMsgSysEnumerateStage(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
|||||||
for sid, stage := range s.Server.stages {
|
for sid, stage := range s.Server.stages {
|
||||||
stage.RLock()
|
stage.RLock()
|
||||||
|
|
||||||
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
if len(stage.ReservedClientSlots) == 0 && len(stage.Clients) == 0 {
|
||||||
stage.RUnlock()
|
stage.RUnlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !strings.Contains(stage.id, pkt.StagePrefix) {
|
if !strings.Contains(stage.Id, pkt.StagePrefix) {
|
||||||
stage.RUnlock()
|
stage.RUnlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
joinable++
|
joinable++
|
||||||
|
|
||||||
bf.WriteUint16(uint16(len(stage.reservedClientSlots)))
|
bf.WriteUint16(uint16(len(stage.ReservedClientSlots)))
|
||||||
bf.WriteUint16(uint16(len(stage.clients)))
|
bf.WriteUint16(uint16(len(stage.Clients)))
|
||||||
if strings.HasPrefix(stage.id, "sl2Ls") {
|
if strings.HasPrefix(stage.Id, "sl2Ls") {
|
||||||
bf.WriteUint16(uint16(len(stage.clients) + len(stage.reservedClientSlots)))
|
bf.WriteUint16(uint16(len(stage.Clients) + len(stage.ReservedClientSlots)))
|
||||||
} else {
|
} else {
|
||||||
bf.WriteUint16(uint16(len(stage.clients)))
|
bf.WriteUint16(uint16(len(stage.Clients)))
|
||||||
}
|
}
|
||||||
bf.WriteUint16(stage.maxPlayers)
|
bf.WriteUint16(stage.MaxPlayers)
|
||||||
var flags uint8
|
var flags uint8
|
||||||
if stage.locked {
|
if stage.Locked {
|
||||||
flags |= 1
|
flags |= 1
|
||||||
}
|
}
|
||||||
if len(stage.password) > 0 {
|
if len(stage.Password) > 0 {
|
||||||
flags |= 2
|
flags |= 2
|
||||||
}
|
}
|
||||||
bf.WriteUint8(flags)
|
bf.WriteUint8(flags)
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"erupe-ce/config"
|
"erupe-ce/config"
|
||||||
|
"erupe-ce/internal/system"
|
||||||
"erupe-ce/server/discordbot"
|
"erupe-ce/server/discordbot"
|
||||||
"erupe-ce/utils/db"
|
"erupe-ce/utils/db"
|
||||||
|
|
||||||
"erupe-ce/utils/gametime"
|
"erupe-ce/utils/gametime"
|
||||||
"erupe-ce/utils/logger"
|
"erupe-ce/utils/logger"
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ type ChannelServer struct {
|
|||||||
isShuttingDown bool
|
isShuttingDown bool
|
||||||
|
|
||||||
stagesLock sync.RWMutex
|
stagesLock sync.RWMutex
|
||||||
stages map[string]*Stage
|
stages map[string]*system.Stage
|
||||||
|
|
||||||
// Used to map different languages
|
// Used to map different languages
|
||||||
i18n i18n
|
i18n i18n
|
||||||
@@ -82,9 +84,9 @@ func NewServer(config *Config) *ChannelServer {
|
|||||||
"sl2Ns379p0a0u0", // Diva fountain
|
"sl2Ns379p0a0u0", // Diva fountain
|
||||||
"sl1Ns462p0a0u0", // MezFes
|
"sl1Ns462p0a0u0", // MezFes
|
||||||
}
|
}
|
||||||
stages := make(map[string]*Stage)
|
stages := make(map[string]*system.Stage)
|
||||||
for _, name := range stageNames {
|
for _, name := range stageNames {
|
||||||
stages[name] = NewStage(name)
|
stages[name] = system.NewStage(name)
|
||||||
}
|
}
|
||||||
server := &ChannelServer{
|
server := &ChannelServer{
|
||||||
ID: config.ID,
|
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()
|
server.stagesLock.RLock()
|
||||||
defer server.stagesLock.RUnlock()
|
defer server.stagesLock.RUnlock()
|
||||||
for _, stage := range server.stages {
|
for _, stage := range server.stages {
|
||||||
stage.RLock()
|
stage.RLock()
|
||||||
for objId := range stage.objects {
|
for objId := range stage.Objects {
|
||||||
obj := stage.objects[objId]
|
obj := stage.Objects[objId]
|
||||||
if obj.ownerCharID == charID {
|
if obj.OwnerCharID == charID {
|
||||||
stage.RUnlock()
|
stage.RUnlock()
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,17 +22,17 @@ func getPlayerSlice(server *ChannelServer) []Player {
|
|||||||
|
|
||||||
for _, channel := range server.Channels {
|
for _, channel := range server.Channels {
|
||||||
for _, stage := range channel.stages {
|
for _, stage := range channel.stages {
|
||||||
if len(stage.clients) == 0 {
|
if len(stage.Clients) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
questID := 0
|
questID := 0
|
||||||
if stage.isQuest() {
|
if stage.IsQuest() {
|
||||||
questIndex++
|
questIndex++
|
||||||
questID = questIndex
|
questID = questIndex
|
||||||
}
|
}
|
||||||
for client := range stage.clients {
|
for client := range stage.Clients {
|
||||||
p = append(p, Player{
|
p = append(p, Player{
|
||||||
CharName: client.Name,
|
CharName: client.GetName(),
|
||||||
QuestID: questID,
|
QuestID: questID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"erupe-ce/config"
|
"erupe-ce/config"
|
||||||
"erupe-ce/internal/constant"
|
"erupe-ce/internal/constant"
|
||||||
|
"erupe-ce/internal/system"
|
||||||
"erupe-ce/network"
|
"erupe-ce/network"
|
||||||
"erupe-ce/network/binpacket"
|
"erupe-ce/network/binpacket"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
@@ -36,10 +37,10 @@ type Session struct {
|
|||||||
|
|
||||||
objectIndex uint16
|
objectIndex uint16
|
||||||
userEnteredStage bool // If the user has entered a stage before
|
userEnteredStage bool // If the user has entered a stage before
|
||||||
stage *Stage
|
stage *system.Stage
|
||||||
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
|
reservationStage *system.Stage // Required for the stateful MsgSysUnreserveStage packet.
|
||||||
stagePass string // Temporary storage
|
stagePass string // Temporary storage
|
||||||
prevGuildID uint32 // Stores the last GuildID used in InfoGuild
|
prevGuildID uint32 // Stores the last GuildID used in InfoGuild
|
||||||
CharID uint32
|
CharID uint32
|
||||||
logKey []byte
|
logKey []byte
|
||||||
sessionStart int64
|
sessionStart int64
|
||||||
@@ -371,3 +372,9 @@ func (s *Session) DoAckSimpleFail(ackHandle uint32, data []byte) {
|
|||||||
AckData: data,
|
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`
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user