diff --git a/network/mhfpacket/msg_sys_enumerate_stage.go b/network/mhfpacket/msg_sys_enumerate_stage.go index 65d60c02f..0c3362562 100644 --- a/network/mhfpacket/msg_sys_enumerate_stage.go +++ b/network/mhfpacket/msg_sys_enumerate_stage.go @@ -6,7 +6,12 @@ import ( ) // MsgSysEnumerateStage represents the MSG_SYS_ENUMERATE_STAGE -type MsgSysEnumerateStage struct{} +type MsgSysEnumerateStage struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 1 in the binary + StageIDLength uint8 + StageID string +} // Opcode returns the ID associated with this packet type. func (m *MsgSysEnumerateStage) Opcode() network.PacketID { @@ -15,10 +20,14 @@ func (m *MsgSysEnumerateStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysEnumerateStage) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.StageIDLength = bf.ReadUint8() + m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) + return nil } // Build builds a binary packet from the current data. func (m *MsgSysEnumerateStage) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/server/channelserver/channel_server.go b/server/channelserver/channel_server.go index 0d11080c8..2a36a06b7 100644 --- a/server/channelserver/channel_server.go +++ b/server/channelserver/channel_server.go @@ -32,8 +32,8 @@ type Server struct { isShuttingDown bool - gameObjectLock sync.Mutex - gameObjectCount uint32 + stagesLock sync.RWMutex + stages map[string]*Stage } // NewServer creates a new Server type. @@ -45,7 +45,12 @@ func NewServer(config *Config) *Server { acceptConns: make(chan net.Conn), deleteConns: make(chan net.Conn), sessions: make(map[net.Conn]*Session), + stages: make(map[string]*Stage), } + + // Default town stage that clients try to enter without creating. + s.stages["sl1Ns200p0a0u0"] = &Stage{} + return s } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 7c33400cd..21708db64 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -9,6 +9,7 @@ import ( "github.com/Andoryuuta/Erupe/network/mhfpacket" "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" "golang.org/x/text/encoding/japanese" "golang.org/x/text/transform" ) @@ -285,7 +286,25 @@ func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysEnumerateStage) + + // Read-lock the stages. + s.server.stagesLock.RLock() + defer s.server.stagesLock.RUnlock() + + // Build the response + resp := byteframe.NewByteFrame() + resp.WriteUint16(uint16(len(s.server.stages))) + for sid := range s.server.stages { + // Couldn't find the parsing code in the client, unk purpose & sizes: + resp.WriteBytes([]byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00}) + resp.WriteUint8(uint8(len(sid))) + resp.WriteBytes([]byte(sid)) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgSysCreateMutex(s *Session, p mhfpacket.MHFPacket) {} @@ -322,11 +341,21 @@ func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateObject) + // Get the current stage. + s.server.stagesLock.RLock() + defer s.server.stagesLock.RUnlock() + stage, ok := s.server.stages[s.stageID] + if !ok { + s.logger.Fatal("StageID not in the stages map!", zap.String("stageID", s.stageID)) + } + + // Lock the stage. + stage.Lock() + defer stage.Unlock() + // Make a new object ID. - s.server.gameObjectLock.Lock() - objID := s.server.gameObjectCount - s.server.gameObjectCount++ - s.server.gameObjectLock.Unlock() + objID := stage.gameObjectCount + stage.gameObjectCount++ resp := byteframe.NewByteFrame() resp.WriteUint32(0) // Unk, is this echoed back from pkt.Unk0? diff --git a/server/channelserver/stage.go b/server/channelserver/stage.go new file mode 100644 index 000000000..2056d5af2 --- /dev/null +++ b/server/channelserver/stage.go @@ -0,0 +1,9 @@ +package channelserver + +import "sync" + +// Stage holds stage-specific information +type Stage struct { + sync.RWMutex + gameObjectCount uint32 +}