From 820563dc4c4bad66269399a6627e520b8b6220b7 Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 5 Aug 2022 07:39:37 +1000 Subject: [PATCH] matchmaking support --- .../mhfpacket/msg_sys_acquire_semaphore.go | 19 ++-- server/channelserver/handlers.go | 102 ++++++++++++++++-- server/channelserver/handlers_semaphore.go | 11 +- server/signserver/dsgn_resp.go | 2 +- 4 files changed, 118 insertions(+), 16 deletions(-) diff --git a/network/mhfpacket/msg_sys_acquire_semaphore.go b/network/mhfpacket/msg_sys_acquire_semaphore.go index 89b974ff4..2be7284d9 100644 --- a/network/mhfpacket/msg_sys_acquire_semaphore.go +++ b/network/mhfpacket/msg_sys_acquire_semaphore.go @@ -1,15 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" + "erupe-ce/common/bfutil" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgSysAcquireSemaphore represents the MSG_SYS_ACQUIRE_SEMAPHORE -type MsgSysAcquireSemaphore struct{} +type MsgSysAcquireSemaphore struct { + AckHandle uint32 + SemaphoreID string +} // Opcode returns the ID associated with this packet type. func (m *MsgSysAcquireSemaphore) Opcode() network.PacketID { @@ -18,7 +22,10 @@ func (m *MsgSysAcquireSemaphore) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysAcquireSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + SemaphoreIDLength := bf.ReadUint8() + m.SemaphoreID = string(bfutil.UpToNull(bf.ReadBytes(uint(SemaphoreIDLength)))) + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index b4d979c7e..1cfe9e3ff 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -345,14 +345,11 @@ func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfTransitMessage) - // 1 -> CID - // 2 -> Name - // 4 -> Group resp := byteframe.NewByteFrame() resp.WriteUint16(0) var count uint16 switch pkt.SearchType { - case 1: + case 1: // CID bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) CharID := bf.ReadUint32() for _, c := range s.server.Channels { @@ -366,17 +363,17 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(session.charID) resp.WriteBool(true) resp.WriteUint8(uint8(len(sessionName) + 1)) - resp.WriteUint16(0x180) // lenUserBinary + resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{charID: session.charID, index: 3}]))) resp.WriteBytes(make([]byte, 40)) resp.WriteUint8(uint8(len(sessionStage) + 1)) resp.WriteBytes(make([]byte, 8)) resp.WriteNullTerminatedBytes(sessionName) - resp.WriteBytes(c.userBinaryParts[userBinaryPartID{charID: session.charID, index: 3}]) + resp.WriteBytes(c.userBinaryParts[userBinaryPartID{session.charID, 3}]) resp.WriteNullTerminatedBytes(sessionStage) } } } - case 2: + case 2: // Name bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) bf.ReadUint16() // lenSearchTerm bf.ReadUint16() // maxResults @@ -396,7 +393,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(session.charID) resp.WriteBool(true) resp.WriteUint8(uint8(len(sessionName) + 1)) - resp.WriteUint16(0x180) // lenUserBinary + resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{session.charID, 3}]))) resp.WriteBytes(make([]byte, 40)) resp.WriteUint8(uint8(len(sessionStage) + 1)) resp.WriteBytes(make([]byte, 8)) @@ -406,6 +403,95 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { } } } + case 3: // Enumerate Party + bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) + ip := bf.ReadBytes(4) + ipString := fmt.Sprintf("%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]) + port := bf.ReadUint16() + bf.ReadUint16() // lenStage + maxResults := bf.ReadUint16() + bf.ReadBytes(1) + stageID := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + for _, c := range s.server.Channels { + if c.IP == ipString && c.Port == port { + for _, stage := range c.stages { + if stage.id == stageID { + if count == maxResults { + break + } + for session := range stage.clients { + count++ + sessionStage := stringsupport.UTF8ToSJIS(session.stageID) + sessionName := stringsupport.UTF8ToSJIS(session.Name) + resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) + resp.WriteUint16(c.Port) + resp.WriteUint32(session.charID) + resp.WriteUint8(uint8(len(sessionStage) + 1)) + resp.WriteUint8(uint8(len(sessionName) + 1)) + resp.WriteUint8(0) + resp.WriteUint8(7) // lenBinary + resp.WriteBytes(make([]byte, 48)) + resp.WriteNullTerminatedBytes(sessionStage) + resp.WriteNullTerminatedBytes(sessionName) + resp.WriteUint16(999) // HR + resp.WriteUint16(999) // GR + resp.WriteBytes([]byte{0x06, 0x10, 0x00}) // Unk + } + } + } + } + } + case 4: // Find Party + bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) + bf.ReadUint8() + maxResults := bf.ReadUint16() + bf.ReadUint8() + bf.ReadUint8() + partyType := bf.ReadUint16() + _ = bf.DataFromCurrent() // Restrictions + var stagePrefix string + switch partyType { + case 0: // Public Bar + stagePrefix = "sl2Ls210" + case 1: // Tokotoko Partnya + stagePrefix = "sl2Ls463" + case 2: // Hunting Prowess Match + stagePrefix = "sl2Ls286" + case 3: // Volpakkun Together + stagePrefix = "sl2Ls465" + case 5: // Quick Party + // Unk + } + for _, c := range s.server.Channels { + for _, stage := range c.stages { + if count == maxResults { + break + } + if strings.HasPrefix(stage.id, stagePrefix) { + count++ + sessionStage := stringsupport.UTF8ToSJIS(stage.id) + resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) + resp.WriteUint16(c.Port) + + // TODO: This is half right, could be trimmed + resp.WriteUint16(0) + resp.WriteUint16(uint16(len(stage.clients))) + resp.WriteUint16(uint16(len(stage.clients))) + resp.WriteUint16(stage.maxPlayers) + resp.WriteUint16(0) + resp.WriteUint16(uint16(len(stage.clients))) + // + + resp.WriteUint16(uint16(len(sessionStage) + 1)) + resp.WriteUint8(1) + resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 1}]))) + resp.WriteBytes(make([]byte, 16)) + resp.WriteNullTerminatedBytes(sessionStage) + resp.WriteBytes([]byte{0x00}) + resp.WriteBytes(stage.rawBinaryData[stageBinaryKey{1, 1}]) + } + } + } } resp.Seek(0, io.SeekStart) resp.WriteUint16(count) diff --git a/server/channelserver/handlers_semaphore.go b/server/channelserver/handlers_semaphore.go index e7b9834ab..6659bd2da 100644 --- a/server/channelserver/handlers_semaphore.go +++ b/server/channelserver/handlers_semaphore.go @@ -124,7 +124,16 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { } func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { - //pkt := p.(*mhfpacket.MsgSysAcquireSemaphore) + pkt := p.(*mhfpacket.MsgSysAcquireSemaphore) + if sema, exists := s.server.semaphore[pkt.SemaphoreID]; exists { + sema.clients[s] = s.charID + bf := byteframe.NewByteFrame() + bf.WriteUint32(sema.id) + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + } else { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + } + } func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) { diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index fee38c1d3..80764c408 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -136,7 +136,7 @@ func (s *Session) makeSignInResp(uid int) []byte { bf.WriteUint32(uint32(channelserver.Time_Current_Adjusted().Add(24 * time.Hour * 7).Unix())) bf.WriteUint8(2) // Unk bf.WriteUint32(20) // Single tickets - bf.WriteUint32(0) // Group tickets + bf.WriteUint32(10) // Group tickets bf.WriteUint8(8) // Stalls open bf.WriteUint8(0xA) // Unk bf.WriteUint8(0x3) // Pachinko