From 1685f409e711bfa10aec273921f3cfd5c8dbfb78 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 27 Aug 2023 22:16:51 +1000 Subject: [PATCH 1/9] initial ravi-v3 commit --- network/mhfpacket/msg_sys_load_register.go | 4 +- network/mhfpacket/msg_sys_operate_register.go | 3 +- server/channelserver/handlers_cast_binary.go | 18 +- server/channelserver/handlers_register.go | 281 +++--------------- server/channelserver/sys_channel_server.go | 86 +++--- 5 files changed, 103 insertions(+), 289 deletions(-) diff --git a/network/mhfpacket/msg_sys_load_register.go b/network/mhfpacket/msg_sys_load_register.go index 730616d65..7e1ac5950 100644 --- a/network/mhfpacket/msg_sys_load_register.go +++ b/network/mhfpacket/msg_sys_load_register.go @@ -11,7 +11,7 @@ import ( type MsgSysLoadRegister struct { AckHandle uint32 RegisterID uint32 - Unk1 uint8 + Values uint8 } // Opcode returns the ID associated with this packet type. @@ -23,7 +23,7 @@ func (m *MsgSysLoadRegister) Opcode() network.PacketID { func (m *MsgSysLoadRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.RegisterID = bf.ReadUint32() - m.Unk1 = bf.ReadUint8() + m.Values = bf.ReadUint8() _ = bf.ReadUint8() _ = bf.ReadUint16() return nil diff --git a/network/mhfpacket/msg_sys_operate_register.go b/network/mhfpacket/msg_sys_operate_register.go index 6978609b1..c51a483e3 100644 --- a/network/mhfpacket/msg_sys_operate_register.go +++ b/network/mhfpacket/msg_sys_operate_register.go @@ -25,7 +25,8 @@ func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl m.SemaphoreID = bf.ReadUint32() _ = bf.ReadUint16() dataSize := bf.ReadUint16() - m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + m.RawDataPayload = bf.ReadBytes(uint(dataSize) - 1) + _ = bf.ReadBytes(1) // Null terminator return nil } diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index d93cf1a04..bd6ea053c 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -263,32 +263,32 @@ func parseChatCommand(s *Session, command string) { sendServerChatMessage(s, s.server.dict["commandRaviNoCommand"]) } else { if strings.HasPrefix(command, "!ravi start") { - if s.server.raviente.register.startTime == 0 { - s.server.raviente.register.startTime = s.server.raviente.register.postTime + if s.server.raviente.register[1] == 0 { + s.server.raviente.register[1] = s.server.raviente.register[3] sendServerChatMessage(s, s.server.dict["commandRaviStartSuccess"]) s.notifyRavi() } else { sendServerChatMessage(s, s.server.dict["commandRaviStartError"]) } } else if strings.HasPrefix(command, "!ravi cm") || strings.HasPrefix(command, "!ravi checkmultiplier") { - sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandRaviMultiplier"], s.server.raviente.GetRaviMultiplier(s.server))) + sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandRaviMultiplier"], s.server.GetRaviMultiplier())) } else if strings.HasPrefix(command, "!ravi sr") || strings.HasPrefix(command, "!ravi sendres") { - if s.server.raviente.state.stateData[28] > 0 { + if s.server.raviente.state[28] > 0 { sendServerChatMessage(s, s.server.dict["commandRaviResSuccess"]) - s.server.raviente.state.stateData[28] = 0 + s.server.raviente.state[28] = 0 } else { sendServerChatMessage(s, s.server.dict["commandRaviResError"]) } } else if strings.HasPrefix(command, "!ravi ss") || strings.HasPrefix(command, "!ravi sendsed") { sendServerChatMessage(s, s.server.dict["commandRaviSedSuccess"]) // Total BerRavi HP - HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] - s.server.raviente.support.supportData[1] = HP + HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] + s.server.raviente.support[1] = HP } else if strings.HasPrefix(command, "!ravi rs") || strings.HasPrefix(command, "!ravi reqsed") { sendServerChatMessage(s, s.server.dict["commandRaviRequest"]) // Total BerRavi HP - HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] - s.server.raviente.support.supportData[1] = HP + 12 + HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] + s.server.raviente.support[1] = HP + 12 } else { sendServerChatMessage(s, s.server.dict["commandRaviError"]) } diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index 33261a94e..be423d206 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -3,243 +3,69 @@ package channelserver import ( "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" + "go.uber.org/zap" "strings" ) +type RaviUpdate struct { + Op uint8 + Dest uint8 + Data uint32 +} + func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysOperateRegister) + + var raviUpdates []RaviUpdate + var raviUpdate RaviUpdate bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) - s.server.raviente.Lock() - switch pkt.SemaphoreID { - case 4: - resp := byteframe.NewByteFrame() - size := 6 - for i := 0; i < len(bf.Data())-1; i += size { - op := bf.ReadUint8() - dest := bf.ReadUint8() - data := bf.ReadUint32() - resp.WriteUint8(1) - resp.WriteUint8(dest) - ref := &s.server.raviente.state.stateData[dest] - damageMultiplier := s.server.raviente.GetRaviMultiplier(s.server) - switch op { - case 2: - resp.WriteUint32(*ref) - if dest == 28 { // Berserk resurrection tracker - resp.WriteUint32(*ref + data) - *ref += data - } else if dest == 17 { // Berserk poison tracker - if damageMultiplier == 1 { - resp.WriteUint32(*ref + data) - *ref += data - } else { - resp.WriteUint32(*ref) - } - } else { - data = uint32(float64(data) * damageMultiplier) - resp.WriteUint32(*ref + data) - *ref += data - } - case 13: - fallthrough - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - } - } - resp.WriteUint8(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) - case 5: - resp := byteframe.NewByteFrame() - size := 6 - for i := 0; i < len(bf.Data())-1; i += size { - op := bf.ReadUint8() - dest := bf.ReadUint8() - data := bf.ReadUint32() - resp.WriteUint8(1) - resp.WriteUint8(dest) - ref := &s.server.raviente.support.supportData[dest] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - fallthrough - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - } - } - resp.WriteUint8(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) - case 6: - resp := byteframe.NewByteFrame() - size := 6 - for i := 0; i < len(bf.Data())-1; i += size { - op := bf.ReadUint8() - dest := bf.ReadUint8() - data := bf.ReadUint32() - resp.WriteUint8(1) - resp.WriteUint8(dest) - switch dest { - case 0: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.nextTime = data - case 1: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.startTime = data - case 2: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.killedTime = data - case 3: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.postTime = data - case 4: - ref := &s.server.raviente.register.register[0] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - } - case 5: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.carveQuest = data - case 6: - ref := &s.server.raviente.register.register[1] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - } - case 7: - ref := &s.server.raviente.register.register[2] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - } - case 8: - ref := &s.server.raviente.register.register[3] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - } - case 9: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.maxPlayers = data - case 10: - resp.WriteUint32(0) - resp.WriteUint32(data) - s.server.raviente.register.ravienteType = data - case 11: - ref := &s.server.raviente.register.register[4] - switch op { - case 2: - resp.WriteUint32(*ref) - resp.WriteUint32(*ref + data) - *ref += data - case 13: - resp.WriteUint32(0) - resp.WriteUint32(data) - *ref = data - case 14: - resp.WriteUint32(0) - resp.WriteUint32(data) - } - default: - resp.WriteUint32(0) - resp.WriteUint32(0) - } - } - resp.WriteUint8(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + for i := len(pkt.RawDataPayload) / 6; i > 0; i-- { + raviUpdate.Op = bf.ReadUint8() + raviUpdate.Dest = bf.ReadUint8() + raviUpdate.Data = bf.ReadUint32() + s.logger.Debug("RaviOps", zap.Uint8s("Op/Dest", []uint8{raviUpdate.Op, raviUpdate.Dest}), zap.Uint32s("Sema/Data", []uint32{pkt.SemaphoreID, raviUpdate.Data})) + raviUpdates = append(raviUpdates, raviUpdate) } + bf = byteframe.NewByteFrame() + + var _old, _new uint32 + s.server.raviente.Lock() + for _, update := range raviUpdates { + switch update.Op { + case 2: + _old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true) + case 13, 14: + _old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false) + } + bf.WriteUint8(1) + bf.WriteUint8(update.Dest) + bf.WriteUint32(_old) + bf.WriteUint32(_new) + } + s.server.raviente.Unlock() + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente { s.notifyRavi() } - s.server.raviente.Unlock() } func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLoadRegister) - r := pkt.Unk1 - switch r { - case 12: - resp := byteframe.NewByteFrame() - resp.WriteUint8(0) - resp.WriteUint8(12) - resp.WriteUint32(s.server.raviente.register.nextTime) - resp.WriteUint32(s.server.raviente.register.startTime) - resp.WriteUint32(s.server.raviente.register.killedTime) - resp.WriteUint32(s.server.raviente.register.postTime) - resp.WriteUint32(s.server.raviente.register.register[0]) - resp.WriteUint32(s.server.raviente.register.carveQuest) - resp.WriteUint32(s.server.raviente.register.register[1]) - resp.WriteUint32(s.server.raviente.register.register[2]) - resp.WriteUint32(s.server.raviente.register.register[3]) - resp.WriteUint32(s.server.raviente.register.maxPlayers) - resp.WriteUint32(s.server.raviente.register.ravienteType) - resp.WriteUint32(s.server.raviente.register.register[4]) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) - case 29: - resp := byteframe.NewByteFrame() - resp.WriteUint8(0) - resp.WriteUint8(29) - for _, v := range s.server.raviente.state.stateData { - resp.WriteUint32(v) + bf := byteframe.NewByteFrame() + bf.WriteUint8(0) + bf.WriteUint8(pkt.Values) + for i := uint8(0); i < pkt.Values; i++ { + switch pkt.RegisterID { + case 4: + bf.WriteUint32(s.server.raviente.state[i]) + case 5: + bf.WriteUint32(s.server.raviente.support[i]) + case 6: + bf.WriteUint32(s.server.raviente.register[i]) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) - case 25: - resp := byteframe.NewByteFrame() - resp.WriteUint8(0) - resp.WriteUint8(25) - for _, v := range s.server.raviente.support.supportData { - resp.WriteUint32(v) - } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func (s *Session) notifyRavi() { @@ -282,18 +108,7 @@ func getRaviSemaphore(s *Server) *Semaphore { } func resetRavi(s *Session) { - s.server.raviente.Lock() - s.server.raviente.register.nextTime = 0 - s.server.raviente.register.startTime = 0 - s.server.raviente.register.killedTime = 0 - s.server.raviente.register.postTime = 0 - s.server.raviente.register.ravienteType = 0 - s.server.raviente.register.maxPlayers = 0 - s.server.raviente.register.carveQuest = 0 - s.server.raviente.register.register = []uint32{0, 0, 0, 0, 0} - s.server.raviente.state.stateData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - s.server.raviente.support.supportData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - s.server.raviente.Unlock() + s.server.raviente = NewRaviente() } func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index cad64bbe4..6273a7939 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -76,61 +76,25 @@ type Server struct { type Raviente struct { sync.Mutex - - register *RavienteRegister - state *RavienteState - support *RavienteSupport + register []uint32 + state []uint32 + support []uint32 } -type RavienteRegister struct { - nextTime uint32 - startTime uint32 - postTime uint32 - killedTime uint32 - ravienteType uint32 - maxPlayers uint32 - carveQuest uint32 - register []uint32 -} - -type RavienteState struct { - stateData []uint32 -} - -type RavienteSupport struct { - supportData []uint32 -} - -// Set up the Raviente variables for the server func NewRaviente() *Raviente { - ravienteRegister := &RavienteRegister{ - nextTime: 0, - startTime: 0, - killedTime: 0, - postTime: 0, - ravienteType: 0, - maxPlayers: 0, - carveQuest: 0, - } - ravienteState := &RavienteState{} - ravienteSupport := &RavienteSupport{} - ravienteRegister.register = []uint32{0, 0, 0, 0, 0} - ravienteState.stateData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - ravienteSupport.supportData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - raviente := &Raviente{ - register: ravienteRegister, - state: ravienteState, - support: ravienteSupport, + register: make([]uint32, 30), + state: make([]uint32, 30), + support: make([]uint32, 30), } return raviente } -func (r *Raviente) GetRaviMultiplier(s *Server) float64 { +func (s *Server) GetRaviMultiplier() float64 { raviSema := getRaviSemaphore(s) if raviSema != nil { var minPlayers int - if r.register.maxPlayers > 8 { + if s.raviente.register[9] > 8 { minPlayers = 24 } else { minPlayers = 4 @@ -143,6 +107,40 @@ func (r *Raviente) GetRaviMultiplier(s *Server) float64 { return 0 } +func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) { + var prev uint32 + switch semaID { + case 4: + switch index { + case 17, 28: // Ignore res and poison + break + default: + value = uint32(float64(value) * s.GetRaviMultiplier()) + } + prev = s.raviente.state[index] + if prev != 0 && !update { + return prev, prev + } + s.raviente.state[index] += value + return prev, s.raviente.state[index] + case 5: + prev = s.raviente.support[index] + if prev != 0 && !update { + return prev, prev + } + s.raviente.support[index] += value + return prev, s.raviente.support[index] + case 6: + prev = s.raviente.register[index] + if prev != 0 && !update { + return prev, prev + } + s.raviente.register[index] += value + return prev, s.raviente.register[index] + } + return 0, 0 +} + // NewServer creates a new Server type. func NewServer(config *Config) *Server { s := &Server{ From e6f1298935e8554d03ea89ff526059625cffe5e0 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 00:15:52 +1000 Subject: [PATCH 2/9] disable incompatible ravi commands --- server/channelserver/handlers_cast_binary.go | 37 ++++++++++++-------- server/channelserver/sys_language.go | 2 ++ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 390a5fc74..6652c748f 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -258,23 +258,30 @@ func parseChatCommand(s *Session, command string) { } case "cm", "check", "checkmultiplier", "multiplier": sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandRaviMultiplier"], s.server.GetRaviMultiplier())) - case "sr", "sendres", "resurrection": - if s.server.raviente.state[28] > 0 { - sendServerChatMessage(s, s.server.dict["commandRaviResSuccess"]) - s.server.raviente.state[28] = 0 + case "sr", "sendres", "resurrection", "ss", "sendsed", "rs", "reqsed": + if s.server.erupeConfig.RealClientMode == _config.ZZ { + switch args[1] { + case "sr", "sendres", "resurrection": + if s.server.raviente.state[28] > 0 { + sendServerChatMessage(s, s.server.dict["commandRaviResSuccess"]) + s.server.raviente.state[28] = 0 + } else { + sendServerChatMessage(s, s.server.dict["commandRaviResError"]) + } + case "ss", "sendsed": + sendServerChatMessage(s, s.server.dict["commandRaviSedSuccess"]) + // Total BerRavi HP + HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] + s.server.raviente.support[1] = HP + case "rs", "reqsed": + sendServerChatMessage(s, s.server.dict["commandRaviRequest"]) + // Total BerRavi HP + HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] + s.server.raviente.support[1] = HP + 1 + } } else { - sendServerChatMessage(s, s.server.dict["commandRaviResError"]) + sendServerChatMessage(s, s.server.dict["commandRaviVersion"]) } - case "ss", "sendsed": - sendServerChatMessage(s, s.server.dict["commandRaviSedSuccess"]) - // Total BerRavi HP - HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] - s.server.raviente.support[1] = HP - case "rs", "reqsed": - sendServerChatMessage(s, s.server.dict["commandRaviRequest"]) - // Total BerRavi HP - HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] - s.server.raviente.support[1] = HP + 1 default: sendServerChatMessage(s, s.server.dict["commandRaviError"]) } diff --git a/server/channelserver/sys_language.go b/server/channelserver/sys_language.go index 418e1cecb..dbd48cfb8 100644 --- a/server/channelserver/sys_language.go +++ b/server/channelserver/sys_language.go @@ -34,6 +34,7 @@ func getLangStrings(s *Server) map[string]string { strings["commandRaviRequest"] = "鎮静支援を要請します" strings["commandRaviError"] = "ラヴィコマンドが認識されません" strings["commandRaviNoPlayers"] = "誰も大討伐に参加していません" + strings["commandRaviVersion"] = "This command is disabled outside of MHFZZ" strings["ravienteBerserk"] = "<大討伐:猛狂期>が開催されました!" strings["ravienteExtreme"] = "<大討伐:猛狂期【極】>が開催されました!" @@ -85,6 +86,7 @@ func getLangStrings(s *Server) map[string]string { strings["commandRaviRequest"] = "Requesting sedation support!" strings["commandRaviError"] = "Raviente command not recognised!" strings["commandRaviNoPlayers"] = "No one has joined the Great Slaying!" + strings["commandRaviVersion"] = "This command is disabled outside of MHFZZ" strings["ravienteBerserk"] = " is being held!" strings["ravienteExtreme"] = " is being held!" From 81e8d21d4b0fabff41ee786e4a2238a57e8ee70f Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 21:08:40 +1000 Subject: [PATCH 3/9] clean up --- network/mhfpacket/msg_sys_operate_register.go | 3 +-- server/channelserver/handlers_register.go | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/network/mhfpacket/msg_sys_operate_register.go b/network/mhfpacket/msg_sys_operate_register.go index c51a483e3..6978609b1 100644 --- a/network/mhfpacket/msg_sys_operate_register.go +++ b/network/mhfpacket/msg_sys_operate_register.go @@ -25,8 +25,7 @@ func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl m.SemaphoreID = bf.ReadUint32() _ = bf.ReadUint16() dataSize := bf.ReadUint16() - m.RawDataPayload = bf.ReadBytes(uint(dataSize) - 1) - _ = bf.ReadBytes(1) // Null terminator + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) return nil } diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index be423d206..f060b664e 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -3,7 +3,6 @@ package channelserver import ( "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" - "go.uber.org/zap" "strings" ) @@ -18,12 +17,12 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) { var raviUpdates []RaviUpdate var raviUpdate RaviUpdate - bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) + // Strip null terminator + bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload[:len(pkt.RawDataPayload)-1]) for i := len(pkt.RawDataPayload) / 6; i > 0; i-- { raviUpdate.Op = bf.ReadUint8() raviUpdate.Dest = bf.ReadUint8() raviUpdate.Data = bf.ReadUint32() - s.logger.Debug("RaviOps", zap.Uint8s("Op/Dest", []uint8{raviUpdate.Op, raviUpdate.Dest}), zap.Uint32s("Sema/Data", []uint32{pkt.SemaphoreID, raviUpdate.Data})) raviUpdates = append(raviUpdates, raviUpdate) } bf = byteframe.NewByteFrame() From 813a3df6a7043c4697feec1cc643fa57eee7d8ed Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 22:18:37 +1000 Subject: [PATCH 4/9] correctly parse RegisterEvent & move handlers --- network/mhfpacket/msg_mhf_register_event.go | 12 +++--- server/channelserver/handlers_event.go | 38 ------------------- server/channelserver/handlers_register.go | 42 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/network/mhfpacket/msg_mhf_register_event.go b/network/mhfpacket/msg_mhf_register_event.go index aaa5b51a8..956c4a399 100644 --- a/network/mhfpacket/msg_mhf_register_event.go +++ b/network/mhfpacket/msg_mhf_register_event.go @@ -1,20 +1,19 @@ package mhfpacket import ( + "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" - "erupe-ce/common/byteframe" ) // MsgMhfRegisterEvent represents the MSG_MHF_REGISTER_EVENT type MsgMhfRegisterEvent struct { AckHandle uint32 Unk0 uint16 - Unk1 uint8 - Unk2 uint8 + WorldID uint16 + LandID uint16 Unk3 uint8 Unk4 uint8 - Unk5 uint16 } // Opcode returns the ID associated with this packet type. @@ -26,11 +25,10 @@ func (m *MsgMhfRegisterEvent) Opcode() network.PacketID { func (m *MsgMhfRegisterEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint16() - m.Unk1 = bf.ReadUint8() - m.Unk2 = bf.ReadUint8() + m.WorldID = bf.ReadUint16() + m.LandID = bf.ReadUint16() m.Unk3 = bf.ReadUint8() m.Unk4 = bf.ReadUint8() - m.Unk5 = bf.ReadUint16() return nil } diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index 74d0cef13..d01f92a3d 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -10,44 +10,6 @@ import ( "erupe-ce/network/mhfpacket" ) -func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfRegisterEvent) - bf := byteframe.NewByteFrame() - bf.WriteUint8(pkt.Unk2) - bf.WriteUint8(pkt.Unk4) - bf.WriteUint16(0x1142) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) -} - -func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfReleaseEvent) - - // Do this ack manually because it uses a non-(0|1) error code - /* - _ACK_SUCCESS = 0 - _ACK_ERROR = 1 - - _ACK_EINPROGRESS = 16 - _ACK_ENOENT = 17 - _ACK_ENOSPC = 18 - _ACK_ETIMEOUT = 19 - - _ACK_EINVALID = 64 - _ACK_EFAILED = 65 - _ACK_ENOMEM = 66 - _ACK_ENOTEXIT = 67 - _ACK_ENOTREADY = 68 - _ACK_EALREADY = 69 - _ACK_DISABLE_WORK = 71 - */ - s.QueueSendMHF(&mhfpacket.MsgSysAck{ - AckHandle: pkt.AckHandle, - IsBufferResponse: false, - ErrorCode: 0x41, - AckData: []byte{0x00, 0x00, 0x00, 0x00}, - }) -} - type Event struct { EventType uint16 Unk1 uint16 diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index f060b664e..911249554 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -6,6 +6,48 @@ import ( "strings" ) +func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfRegisterEvent) + bf := byteframe.NewByteFrame() + if pkt.Unk3 > 0 { + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + return + } + bf.WriteUint8(uint8(pkt.WorldID)) + bf.WriteUint8(uint8(pkt.LandID)) + bf.WriteUint16(0x1142) // Probably random ID + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReleaseEvent) + + // Do this ack manually because it uses a non-(0|1) error code + /* + _ACK_SUCCESS = 0 + _ACK_ERROR = 1 + + _ACK_EINPROGRESS = 16 + _ACK_ENOENT = 17 + _ACK_ENOSPC = 18 + _ACK_ETIMEOUT = 19 + + _ACK_EINVALID = 64 + _ACK_EFAILED = 65 + _ACK_ENOMEM = 66 + _ACK_ENOTEXIT = 67 + _ACK_ENOTREADY = 68 + _ACK_EALREADY = 69 + _ACK_DISABLE_WORK = 71 + */ + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: pkt.AckHandle, + IsBufferResponse: false, + ErrorCode: 0x41, + AckData: []byte{0x00, 0x00, 0x00, 0x00}, + }) +} + type RaviUpdate struct { Op uint8 Dest uint8 From 42abdfb0c7ea7b01b4f52560a9da314a299767d4 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 22:29:49 +1000 Subject: [PATCH 5/9] change getRaviSemaphore scope & handle RegisterEvent --- network/mhfpacket/msg_mhf_release_event.go | 4 ++-- server/channelserver/handlers_cast_binary.go | 4 ++-- server/channelserver/handlers_register.go | 7 ++++--- server/channelserver/sys_channel_server.go | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/network/mhfpacket/msg_mhf_release_event.go b/network/mhfpacket/msg_mhf_release_event.go index 08e507c81..52178279b 100644 --- a/network/mhfpacket/msg_mhf_release_event.go +++ b/network/mhfpacket/msg_mhf_release_event.go @@ -11,7 +11,7 @@ import ( // MsgMhfReleaseEvent represents the MSG_MHF_RELEASE_EVENT type MsgMhfReleaseEvent struct { AckHandle uint32 - Unk0 uint32 + RaviID uint32 Unk1 uint32 } @@ -23,7 +23,7 @@ func (m *MsgMhfReleaseEvent) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfReleaseEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() + m.RaviID = bf.ReadUint32() m.Unk1 = bf.ReadUint32() return nil } diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 6652c748f..ded566268 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -246,7 +246,7 @@ func parseChatCommand(s *Session, command string) { case commands["Raviente"].Prefix: if commands["Raviente"].Enabled { if len(args) > 1 { - if getRaviSemaphore(s.server) != nil { + if s.server.getRaviSemaphore() != nil { switch args[1] { case "start": if s.server.raviente.register[1] == 0 { @@ -420,7 +420,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { } case BroadcastTypeServer: if pkt.MessageType == 1 { - if getRaviSemaphore(s.server) != nil { + if s.server.getRaviSemaphore() != nil { s.server.BroadcastMHF(resp, s) } } else { diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index 911249554..57bce3e61 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -9,7 +9,8 @@ import ( func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegisterEvent) bf := byteframe.NewByteFrame() - if pkt.Unk3 > 0 { + // Some kind of check if there's already a session + if pkt.Unk3 > 0 && s.server.getRaviSemaphore() == nil { doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } @@ -110,7 +111,7 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) { } func (s *Session) notifyRavi() { - sema := getRaviSemaphore(s.server) + sema := s.server.getRaviSemaphore() if sema == nil { return } @@ -139,7 +140,7 @@ func (s *Session) notifyRavi() { } } -func getRaviSemaphore(s *Server) *Semaphore { +func (s *Server) getRaviSemaphore() *Semaphore { for _, semaphore := range s.semaphore { if strings.HasPrefix(semaphore.id_semaphore, "hs_l0u3B5") && strings.HasSuffix(semaphore.id_semaphore, "3") { return semaphore diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index 6273a7939..0de5650c0 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -91,7 +91,7 @@ func NewRaviente() *Raviente { } func (s *Server) GetRaviMultiplier() float64 { - raviSema := getRaviSemaphore(s) + raviSema := s.getRaviSemaphore() if raviSema != nil { var minPlayers int if s.raviente.register[9] > 8 { From 5b5621a3d8455c6dd8753b97ea62fcc759685cbf Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 23:43:56 +1000 Subject: [PATCH 6/9] fix and rework various Raviente ID systems --- server/channelserver/handlers_register.go | 8 ++------ server/channelserver/handlers_semaphore.go | 8 ++++---- server/channelserver/sys_channel_server.go | 19 +++++++++++-------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index 57bce3e61..2135af6fb 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -16,7 +16,7 @@ func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint8(uint8(pkt.WorldID)) bf.WriteUint8(uint8(pkt.LandID)) - bf.WriteUint16(0x1142) // Probably random ID + bf.WriteUint16(s.server.raviente.id) doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } @@ -142,15 +142,11 @@ func (s *Session) notifyRavi() { func (s *Server) getRaviSemaphore() *Semaphore { for _, semaphore := range s.semaphore { - if strings.HasPrefix(semaphore.id_semaphore, "hs_l0u3B5") && strings.HasSuffix(semaphore.id_semaphore, "3") { + if strings.HasPrefix(semaphore.id_semaphore, "hs_l0") && strings.HasSuffix(semaphore.id_semaphore, "3") { return semaphore } } return nil } -func resetRavi(s *Session) { - s.server.raviente = NewRaviente() -} - func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_semaphore.go b/server/channelserver/handlers_semaphore.go index 503df5110..21b12682e 100644 --- a/server/channelserver/handlers_semaphore.go +++ b/server/channelserver/handlers_semaphore.go @@ -35,7 +35,7 @@ func destructEmptySemaphores(s *Session) { s.server.semaphoreLock.Unlock() delete(s.server.semaphore, id) s.server.semaphoreLock.Lock() - if strings.HasPrefix(id, "hs_l0u3B5") { + if strings.HasPrefix(id, "hs_l0") { releaseRaviSemaphore(s, sema) } s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id)) @@ -49,7 +49,7 @@ func releaseRaviSemaphore(s *Session, sema *Semaphore) { delete(sema.clients, s) if strings.HasSuffix(sema.id_semaphore, "2") && len(sema.clients) == 0 { s.logger.Debug("Main raviente semaphore is empty, resetting") - resetRavi(s) + s.server.resetRaviente() } } @@ -60,7 +60,7 @@ func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { s.server.semaphoreLock.Lock() for id, sema := range s.server.semaphore { if sema.id == pkt.SemaphoreID { - if strings.HasPrefix(id, "hs_l0u3B5") { + if strings.HasPrefix(id, "hs_l0") { releaseRaviSemaphore(s, sema) s.server.semaphoreLock.Unlock() return @@ -84,7 +84,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID) if !exists { s.server.semaphoreLock.Lock() - if strings.HasPrefix(SemaphoreID, "hs_l0u3B5") { + if strings.HasPrefix(SemaphoreID, "hs_l0") { suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:]) s.server.semaphore[SemaphoreID] = &Semaphore{ id_semaphore: pkt.SemaphoreID, diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index 0de5650c0..8c0e9fe23 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -76,18 +76,17 @@ type Server struct { type Raviente struct { sync.Mutex + id uint16 register []uint32 state []uint32 support []uint32 } -func NewRaviente() *Raviente { - raviente := &Raviente{ - register: make([]uint32, 30), - state: make([]uint32, 30), - support: make([]uint32, 30), - } - return raviente +func (s *Server) resetRaviente() { + s.raviente.id = s.raviente.id + 1 + s.raviente.register = make([]uint32, 30) + s.raviente.state = make([]uint32, 30) + s.raviente.support = make([]uint32, 30) } func (s *Server) GetRaviMultiplier() float64 { @@ -158,7 +157,11 @@ func NewServer(config *Config) *Server { semaphoreIndex: 7, discordBot: config.DiscordBot, name: config.Name, - raviente: NewRaviente(), + raviente: &Raviente{ + register: make([]uint32, 30), + state: make([]uint32, 30), + support: make([]uint32, 30), + }, } // Mezeporta From 9f76d34e46effe3021c2ac37797463c00f659dac Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 30 Aug 2023 23:58:50 +1000 Subject: [PATCH 7/9] fix Raviente ID --- server/channelserver/sys_channel_server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index 8c0e9fe23..dd25db23f 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -158,6 +158,7 @@ func NewServer(config *Config) *Server { discordBot: config.DiscordBot, name: config.Name, raviente: &Raviente{ + id: 1, register: make([]uint32, 30), state: make([]uint32, 30), support: make([]uint32, 30), From 0bdd873336ba84f8adebef4a612bf1bacd349256 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 2 Sep 2023 23:52:15 +1000 Subject: [PATCH 8/9] broadcast Raviente party message correctly --- server/channelserver/handlers_cast_binary.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index ded566268..30a377b82 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -420,8 +420,9 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { } case BroadcastTypeServer: if pkt.MessageType == 1 { - if s.server.getRaviSemaphore() != nil { - s.server.BroadcastMHF(resp, s) + raviSema := s.server.getRaviSemaphore() + if raviSema != nil { + raviSema.BroadcastMHF(resp, s) } } else { s.server.BroadcastMHF(resp, s) From 4a35be488cae3a0c2af6c8d2b396c0bc8742c257 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 3 Sep 2023 00:00:08 +1000 Subject: [PATCH 9/9] rework Semaphores --- server/channelserver/handlers_register.go | 14 ++--- server/channelserver/handlers_semaphore.go | 73 ++++++++-------------- server/channelserver/sys_channel_server.go | 20 ++++-- server/channelserver/sys_semaphore.go | 40 +++--------- 4 files changed, 57 insertions(+), 90 deletions(-) diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index 2135af6fb..6a74358aa 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -99,11 +99,11 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(pkt.Values) for i := uint8(0); i < pkt.Values; i++ { switch pkt.RegisterID { - case 4: + case 0x40000: bf.WriteUint32(s.server.raviente.state[i]) - case 5: + case 0x50000: bf.WriteUint32(s.server.raviente.support[i]) - case 6: + case 0x60000: bf.WriteUint32(s.server.raviente.register[i]) } } @@ -117,13 +117,13 @@ func (s *Session) notifyRavi() { } var temp mhfpacket.MHFPacket raviNotif := byteframe.NewByteFrame() - temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 4} + temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x40000} raviNotif.WriteUint16(uint16(temp.Opcode())) temp.Build(raviNotif, s.clientContext) - temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 5} + temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x50000} raviNotif.WriteUint16(uint16(temp.Opcode())) temp.Build(raviNotif, s.clientContext) - temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 6} + temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x60000} raviNotif.WriteUint16(uint16(temp.Opcode())) temp.Build(raviNotif, s.clientContext) raviNotif.WriteUint16(0x0010) // End it. @@ -142,7 +142,7 @@ func (s *Session) notifyRavi() { func (s *Server) getRaviSemaphore() *Semaphore { for _, semaphore := range s.semaphore { - if strings.HasPrefix(semaphore.id_semaphore, "hs_l0") && strings.HasSuffix(semaphore.id_semaphore, "3") { + if strings.HasPrefix(semaphore.name, "hs_l0") && strings.HasSuffix(semaphore.name, "3") { return semaphore } } diff --git a/server/channelserver/handlers_semaphore.go b/server/channelserver/handlers_semaphore.go index 21b12682e..19925c6d6 100644 --- a/server/channelserver/handlers_semaphore.go +++ b/server/channelserver/handlers_semaphore.go @@ -2,7 +2,6 @@ package channelserver import ( "erupe-ce/common/byteframe" - "fmt" "go.uber.org/zap" "strconv" "strings" @@ -13,9 +12,6 @@ import ( func removeSessionFromSemaphore(s *Session) { s.server.semaphoreLock.Lock() for _, semaphore := range s.server.semaphore { - if _, exists := semaphore.reservedClientSlots[s.charID]; exists { - delete(semaphore.reservedClientSlots, s.charID) - } if _, exists := semaphore.clients[s]; exists { delete(semaphore.clients, s) } @@ -31,48 +27,38 @@ func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) { func destructEmptySemaphores(s *Session) { s.server.semaphoreLock.Lock() for id, sema := range s.server.semaphore { - if len(sema.reservedClientSlots) == 0 && len(sema.clients) == 0 { - s.server.semaphoreLock.Unlock() + if len(sema.clients) == 0 { delete(s.server.semaphore, id) - s.server.semaphoreLock.Lock() if strings.HasPrefix(id, "hs_l0") { - releaseRaviSemaphore(s, sema) + s.server.resetRaviente() } - s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id)) + s.logger.Debug("Destructed semaphore", zap.String("sema.name", id)) } } s.server.semaphoreLock.Unlock() } -func releaseRaviSemaphore(s *Session, sema *Semaphore) { - delete(sema.reservedClientSlots, s.charID) - delete(sema.clients, s) - if strings.HasSuffix(sema.id_semaphore, "2") && len(sema.clients) == 0 { - s.logger.Debug("Main raviente semaphore is empty, resetting") - s.server.resetRaviente() - } -} - func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysDeleteSemaphore) - if s.server.semaphore != nil { - destructEmptySemaphores(s) - s.server.semaphoreLock.Lock() - for id, sema := range s.server.semaphore { - if sema.id == pkt.SemaphoreID { - if strings.HasPrefix(id, "hs_l0") { - releaseRaviSemaphore(s, sema) - s.server.semaphoreLock.Unlock() - return + destructEmptySemaphores(s) + s.server.semaphoreLock.Lock() + for id, sema := range s.server.semaphore { + if sema.id == pkt.SemaphoreID { + for session := range sema.clients { + if s == session { + delete(sema.clients, s) } - s.server.semaphoreLock.Unlock() + } + if len(sema.clients) == 0 { delete(s.server.semaphore, id) - s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id)) - return + if strings.HasPrefix(id, "hs_l0") { + s.server.resetRaviente() + } + s.logger.Debug("Destructed semaphore", zap.String("sema.name", id)) } } - s.server.semaphoreLock.Unlock() } + s.server.semaphoreLock.Unlock() } func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { @@ -80,18 +66,15 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { SemaphoreID := pkt.SemaphoreID newSemaphore, exists := s.server.semaphore[SemaphoreID] - - fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID) if !exists { s.server.semaphoreLock.Lock() if strings.HasPrefix(SemaphoreID, "hs_l0") { suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:]) s.server.semaphore[SemaphoreID] = &Semaphore{ - id_semaphore: pkt.SemaphoreID, - id: uint32(suffix + 1), - clients: make(map[*Session]uint32), - reservedClientSlots: make(map[uint32]interface{}), - maxPlayers: 127, + name: pkt.SemaphoreID, + id: uint32((suffix + 1) * 0x10000), + clients: make(map[*Session]uint32), + maxPlayers: 127, } } else { s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1) @@ -102,22 +85,19 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { newSemaphore.Lock() defer newSemaphore.Unlock() - if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists { - bf := byteframe.NewByteFrame() + bf := byteframe.NewByteFrame() + if _, exists := newSemaphore.clients[s]; exists { bf.WriteUint32(newSemaphore.id) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) - } else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers { - newSemaphore.reservedClientSlots[s.charID] = nil + } else if uint16(len(newSemaphore.clients)) < newSemaphore.maxPlayers { newSemaphore.clients[s] = s.charID s.Lock() s.semaphore = newSemaphore s.Unlock() - bf := byteframe.NewByteFrame() bf.WriteUint32(newSemaphore.id) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + bf.WriteUint32(0) } + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { @@ -130,7 +110,6 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { } else { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } - } func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) { diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index dd25db23f..5a4b29fe9 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -3,6 +3,7 @@ package channelserver import ( "fmt" "net" + "strings" "sync" "erupe-ce/common/byteframe" @@ -83,6 +84,12 @@ type Raviente struct { } func (s *Server) resetRaviente() { + for _, semaphore := range s.semaphore { + if strings.HasPrefix(semaphore.name, "hs_l0") { + return + } + } + s.logger.Debug("All Raviente Semaphores empty, resetting") s.raviente.id = s.raviente.id + 1 s.raviente.register = make([]uint32, 30) s.raviente.state = make([]uint32, 30) @@ -109,7 +116,7 @@ func (s *Server) GetRaviMultiplier() float64 { func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) { var prev uint32 switch semaID { - case 4: + case 0x40000: switch index { case 17, 28: // Ignore res and poison break @@ -122,14 +129,14 @@ func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update boo } s.raviente.state[index] += value return prev, s.raviente.state[index] - case 5: + case 0x50000: prev = s.raviente.support[index] if prev != 0 && !update { return prev, prev } s.raviente.support[index] += value return prev, s.raviente.support[index] - case 6: + case 0x60000: prev = s.raviente.register[index] if prev != 0 && !update { return prev, prev @@ -395,15 +402,16 @@ func (s *Server) NextSemaphoreID() uint32 { for { exists := false s.semaphoreIndex = s.semaphoreIndex + 1 - if s.semaphoreIndex == 0 { - s.semaphoreIndex = 7 // Skip reserved indexes + if s.semaphoreIndex > 0xFFFF { + s.semaphoreIndex = 1 } for _, semaphore := range s.semaphore { if semaphore.id == s.semaphoreIndex { exists = true + break } } - if exists == false { + if !exists { break } } diff --git a/server/channelserver/sys_semaphore.go b/server/channelserver/sys_semaphore.go index 369e481b6..78ff963b5 100644 --- a/server/channelserver/sys_semaphore.go +++ b/server/channelserver/sys_semaphore.go @@ -7,55 +7,35 @@ import ( "sync" ) -// Stage holds stage-specific information +// Semaphore holds Semaphore-specific information type Semaphore struct { sync.RWMutex - // Stage ID string - id_semaphore string + // Semaphore ID string + name string id uint32 // Map of session -> charID. - // These are clients that are CURRENTLY in the stage + // These are clients that are registered to the Semaphore clients map[*Session]uint32 - // Map of charID -> interface{}, only the key is used, value is always nil. - reservedClientSlots map[uint32]interface{} - // Max Players for Semaphore maxPlayers uint16 } -// NewStage creates a new stage with intialized values. +// NewSemaphore creates a new Semaphore with intialized values func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore { sema := &Semaphore{ - id_semaphore: ID, - id: s.NextSemaphoreID(), - clients: make(map[*Session]uint32), - reservedClientSlots: make(map[uint32]interface{}), - maxPlayers: MaxPlayers, + name: ID, + id: s.NextSemaphoreID(), + clients: make(map[*Session]uint32), + maxPlayers: MaxPlayers, } return sema } -func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) { - // Broadcast the data. - for session := range s.clients { - - // Make the header - bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(pkt.Opcode())) - - // Build the packet onto the byteframe. - pkt.Build(bf, session.clientContext) - - // Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full. - session.QueueSendNonBlocking(bf.Data()) - } -} - -// 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 Semaphore func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { // Broadcast the data. for session := range s.clients {