diff --git a/network/mhfpacket/msg_sys_get_stage_binary.go b/network/mhfpacket/msg_sys_get_stage_binary.go index fa21aab36..a6368567c 100644 --- a/network/mhfpacket/msg_sys_get_stage_binary.go +++ b/network/mhfpacket/msg_sys_get_stage_binary.go @@ -6,7 +6,14 @@ import ( ) // MsgSysGetStageBinary represents the MSG_SYS_GET_STAGE_BINARY -type MsgSysGetStageBinary struct{} +type MsgSysGetStageBinary struct { + AckHandle uint32 + BinaryType0 uint8 + BinaryType1 uint8 + Unk0 uint32 // Hardcoded 0 + StageIDLength uint8 + StageID string +} // Opcode returns the ID associated with this packet type. func (m *MsgSysGetStageBinary) Opcode() network.PacketID { @@ -15,10 +22,16 @@ func (m *MsgSysGetStageBinary) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysGetStageBinary) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.BinaryType0 = bf.ReadUint8() + m.BinaryType1 = bf.ReadUint8() + m.Unk0 = bf.ReadUint32() + 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 *MsgSysGetStageBinary) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_issue_logkey.go b/network/mhfpacket/msg_sys_issue_logkey.go index b8d95ddb0..2114b4d12 100644 --- a/network/mhfpacket/msg_sys_issue_logkey.go +++ b/network/mhfpacket/msg_sys_issue_logkey.go @@ -6,7 +6,11 @@ import ( ) // MsgSysIssueLogkey represents the MSG_SYS_ISSUE_LOGKEY -type MsgSysIssueLogkey struct{} +type MsgSysIssueLogkey struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 00 01 in binary + Unk1 uint16 // Hardcoded 0 in binary. +} // Opcode returns the ID associated with this packet type. func (m *MsgSysIssueLogkey) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgSysIssueLogkey) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysIssueLogkey) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil } // Build builds a binary packet from the current data. func (m *MsgSysIssueLogkey) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_lock_stage.go b/network/mhfpacket/msg_sys_lock_stage.go index 7968ef332..085aadc46 100644 --- a/network/mhfpacket/msg_sys_lock_stage.go +++ b/network/mhfpacket/msg_sys_lock_stage.go @@ -6,7 +6,13 @@ import ( ) // MsgSysLockStage represents the MSG_SYS_LOCK_STAGE -type MsgSysLockStage struct{} +type MsgSysLockStage struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 1 in the binary + Unk1 uint8 // Hardcoded 1 in the binary + StageIDLength uint8 + StageID string +} // Opcode returns the ID associated with this packet type. func (m *MsgSysLockStage) Opcode() network.PacketID { @@ -15,10 +21,15 @@ func (m *MsgSysLockStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysLockStage) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = 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 *MsgSysLockStage) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_set_stage_binary.go b/network/mhfpacket/msg_sys_set_stage_binary.go index 40d9e57bc..4f087b2ac 100644 --- a/network/mhfpacket/msg_sys_set_stage_binary.go +++ b/network/mhfpacket/msg_sys_set_stage_binary.go @@ -7,8 +7,8 @@ import ( // MsgSysSetStageBinary represents the MSG_SYS_SET_STAGE_BINARY type MsgSysSetStageBinary struct { - Unk0 uint8 - BinaryType uint8 // Index + BinaryType0 uint8 + BinaryType1 uint8 // Index StageIDLength uint8 // <= 0x20 DataSize uint16 // <= 0x400 StageID string @@ -22,8 +22,8 @@ func (m *MsgSysSetStageBinary) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysSetStageBinary) Parse(bf *byteframe.ByteFrame) error { - m.Unk0 = bf.ReadUint8() - m.BinaryType = bf.ReadUint8() + m.BinaryType0 = bf.ReadUint8() + m.BinaryType1 = bf.ReadUint8() m.StageIDLength = bf.ReadUint8() m.DataSize = bf.ReadUint16() m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) diff --git a/network/mhfpacket/msg_sys_unlock_stage.go b/network/mhfpacket/msg_sys_unlock_stage.go index 043ba6ce3..c53c46737 100644 --- a/network/mhfpacket/msg_sys_unlock_stage.go +++ b/network/mhfpacket/msg_sys_unlock_stage.go @@ -15,10 +15,11 @@ func (m *MsgSysUnlockStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysUnlockStage) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + // No data + return nil } // Build builds a binary packet from the current data. func (m *MsgSysUnlockStage) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 7b1547247..e5becd9d4 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -2,6 +2,7 @@ package channelserver import ( "bytes" + "crypto/rand" "encoding/base64" "fmt" "io/ioutil" @@ -246,7 +247,26 @@ func handleMsgSysCastedBinary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysIssueLogkey) + + // Make a random log key for this session. + logKey := make([]byte, 8) + _, err := rand.Read(logKey) + if err != nil { + panic(err) + } + + s.Lock() + s.logKey = logKey + s.Unlock() + + // Issue it. + resp := byteframe.NewByteFrame() + resp.WriteBytes(logKey) + resp.WriteBytes([]byte{0x8E, 0x8E}) // Unk + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {} @@ -383,7 +403,11 @@ func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysLockStage) + // TODO(Andoryuuta): What does this packet _actually_ do? + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {} @@ -403,9 +427,56 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysSetStageBinary) -func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {} + // Try to get the stage + stageID := stripNullTerminator(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.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload + stage.Unlock() + } else { + s.logger.Warn("Failed to get stage", zap.String("StageID", stageID)) + } + s.logger.Debug("handleMsgSysSetStageBinary Done!") +} + +func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysGetStageBinary) + + // Try to get the stage + stageID := stripNullTerminator(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() + stageBinary, gotBinary = stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] + stage.Unlock() + } else { + s.logger.Warn("Failed to get stage", zap.String("StageID", stageID)) + } + + if gotBinary { + doSizedAckResp(s, pkt.AckHandle, stageBinary) + } 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") + doSizedAckResp(s, pkt.AckHandle, []byte{}) + } + + s.logger.Debug("MsgSysGetStageBinary Done!") +} func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnumerateClient) @@ -431,6 +502,8 @@ func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { stage.RUnlock() doSizedAckResp(s, pkt.AckHandle, resp.Data()) + + s.logger.Debug("MsgSysEnumerateClient Done!") } func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { diff --git a/server/channelserver/session.go b/server/channelserver/session.go index 0a6b6c8ee..352a895c6 100644 --- a/server/channelserver/session.go +++ b/server/channelserver/session.go @@ -24,6 +24,7 @@ type Session struct { stageID string stage *Stage charID uint32 + logKey []byte } // NewSession creates a new Session type. diff --git a/server/channelserver/stage.go b/server/channelserver/stage.go index 219749fab..1b996b1a1 100644 --- a/server/channelserver/stage.go +++ b/server/channelserver/stage.go @@ -15,13 +15,19 @@ type StageObject struct { x, y, z float32 } +type stageBinaryKey struct { + id0 uint8 + id1 uint8 +} + // Stage holds stage-specific information type Stage struct { sync.RWMutex - id string // Stage ID string - gameObjectCount uint32 // Total count of objects ever created for this stage. Used for ObjID generation. - objects map[uint32]*StageObject // Map of ObjID -> StageObject - clients map[*Session]uint32 // Map of session -> charID + id string // Stage ID string + gameObjectCount uint32 // Total count of objects ever created for this stage. Used for ObjID generation. + objects map[uint32]*StageObject // Map of ObjID -> StageObject + clients map[*Session]uint32 // Map of session -> charID + rawBinaryData map[stageBinaryKey][]byte // Raw binary data set by the client. } // NewStage creates a new stage with intialized values. @@ -30,6 +36,7 @@ func NewStage(ID string) *Stage { id: ID, objects: make(map[uint32]*StageObject), clients: make(map[*Session]uint32), + rawBinaryData: make(map[stageBinaryKey][]byte), gameObjectCount: 1, }