mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-16 17:05:03 +01:00
@@ -1,20 +1,19 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/network"
|
"erupe-ce/network"
|
||||||
"erupe-ce/network/clientctx"
|
"erupe-ce/network/clientctx"
|
||||||
"erupe-ce/common/byteframe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfRegisterEvent represents the MSG_MHF_REGISTER_EVENT
|
// MsgMhfRegisterEvent represents the MSG_MHF_REGISTER_EVENT
|
||||||
type MsgMhfRegisterEvent struct {
|
type MsgMhfRegisterEvent struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint16
|
Unk0 uint16
|
||||||
Unk1 uint8
|
WorldID uint16
|
||||||
Unk2 uint8
|
LandID uint16
|
||||||
Unk3 uint8
|
Unk3 uint8
|
||||||
Unk4 uint8
|
Unk4 uint8
|
||||||
Unk5 uint16
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// 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 {
|
func (m *MsgMhfRegisterEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint16()
|
m.Unk0 = bf.ReadUint16()
|
||||||
m.Unk1 = bf.ReadUint8()
|
m.WorldID = bf.ReadUint16()
|
||||||
m.Unk2 = bf.ReadUint8()
|
m.LandID = bf.ReadUint16()
|
||||||
m.Unk3 = bf.ReadUint8()
|
m.Unk3 = bf.ReadUint8()
|
||||||
m.Unk4 = bf.ReadUint8()
|
m.Unk4 = bf.ReadUint8()
|
||||||
m.Unk5 = bf.ReadUint16()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// MsgMhfReleaseEvent represents the MSG_MHF_RELEASE_EVENT
|
// MsgMhfReleaseEvent represents the MSG_MHF_RELEASE_EVENT
|
||||||
type MsgMhfReleaseEvent struct {
|
type MsgMhfReleaseEvent struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint32
|
RaviID uint32
|
||||||
Unk1 uint32
|
Unk1 uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ func (m *MsgMhfReleaseEvent) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfReleaseEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfReleaseEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint32()
|
m.RaviID = bf.ReadUint32()
|
||||||
m.Unk1 = bf.ReadUint32()
|
m.Unk1 = bf.ReadUint32()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
type MsgSysLoadRegister struct {
|
type MsgSysLoadRegister struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
RegisterID uint32
|
RegisterID uint32
|
||||||
Unk1 uint8
|
Values uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// 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 {
|
func (m *MsgSysLoadRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.RegisterID = bf.ReadUint32()
|
m.RegisterID = bf.ReadUint32()
|
||||||
m.Unk1 = bf.ReadUint8()
|
m.Values = bf.ReadUint8()
|
||||||
_ = bf.ReadUint8()
|
_ = bf.ReadUint8()
|
||||||
_ = bf.ReadUint16()
|
_ = bf.ReadUint16()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -246,35 +246,42 @@ func parseChatCommand(s *Session, command string) {
|
|||||||
case commands["Raviente"].Prefix:
|
case commands["Raviente"].Prefix:
|
||||||
if commands["Raviente"].Enabled {
|
if commands["Raviente"].Enabled {
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
if getRaviSemaphore(s.server) != nil {
|
if s.server.getRaviSemaphore() != nil {
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
case "start":
|
case "start":
|
||||||
if s.server.raviente.register.startTime == 0 {
|
if s.server.raviente.register[1] == 0 {
|
||||||
s.server.raviente.register.startTime = s.server.raviente.register.postTime
|
s.server.raviente.register[1] = s.server.raviente.register[3]
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviStartSuccess"])
|
sendServerChatMessage(s, s.server.dict["commandRaviStartSuccess"])
|
||||||
s.notifyRavi()
|
s.notifyRavi()
|
||||||
} else {
|
} else {
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviStartError"])
|
sendServerChatMessage(s, s.server.dict["commandRaviStartError"])
|
||||||
}
|
}
|
||||||
case "cm", "check", "checkmultiplier", "multiplier":
|
case "cm", "check", "checkmultiplier", "multiplier":
|
||||||
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()))
|
||||||
|
case "sr", "sendres", "resurrection", "ss", "sendsed", "rs", "reqsed":
|
||||||
|
if s.server.erupeConfig.RealClientMode == _config.ZZ {
|
||||||
|
switch args[1] {
|
||||||
case "sr", "sendres", "resurrection":
|
case "sr", "sendres", "resurrection":
|
||||||
if s.server.raviente.state.stateData[28] > 0 {
|
if s.server.raviente.state[28] > 0 {
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviResSuccess"])
|
sendServerChatMessage(s, s.server.dict["commandRaviResSuccess"])
|
||||||
s.server.raviente.state.stateData[28] = 0
|
s.server.raviente.state[28] = 0
|
||||||
} else {
|
} else {
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviResError"])
|
sendServerChatMessage(s, s.server.dict["commandRaviResError"])
|
||||||
}
|
}
|
||||||
case "ss", "sendsed":
|
case "ss", "sendsed":
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviSedSuccess"])
|
sendServerChatMessage(s, s.server.dict["commandRaviSedSuccess"])
|
||||||
// Total BerRavi HP
|
// 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]
|
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.supportData[1] = HP
|
s.server.raviente.support[1] = HP
|
||||||
case "rs", "reqsed":
|
case "rs", "reqsed":
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviRequest"])
|
sendServerChatMessage(s, s.server.dict["commandRaviRequest"])
|
||||||
// Total BerRavi HP
|
// 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]
|
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.supportData[1] = HP + 12
|
s.server.raviente.support[1] = HP + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendServerChatMessage(s, s.server.dict["commandRaviVersion"])
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
sendServerChatMessage(s, s.server.dict["commandRaviError"])
|
sendServerChatMessage(s, s.server.dict["commandRaviError"])
|
||||||
}
|
}
|
||||||
@@ -413,8 +420,9 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
case BroadcastTypeServer:
|
case BroadcastTypeServer:
|
||||||
if pkt.MessageType == 1 {
|
if pkt.MessageType == 1 {
|
||||||
if getRaviSemaphore(s.server) != nil {
|
raviSema := s.server.getRaviSemaphore()
|
||||||
s.server.BroadcastMHF(resp, s)
|
if raviSema != nil {
|
||||||
|
raviSema.BroadcastMHF(resp, s)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.server.BroadcastMHF(resp, s)
|
s.server.BroadcastMHF(resp, s)
|
||||||
|
|||||||
@@ -10,44 +10,6 @@ import (
|
|||||||
"erupe-ce/network/mhfpacket"
|
"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 {
|
type Event struct {
|
||||||
EventType uint16
|
EventType uint16
|
||||||
Unk1 uint16
|
Unk1 uint16
|
||||||
|
|||||||
@@ -6,256 +6,124 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgMhfRegisterEvent)
|
||||||
|
bf := byteframe.NewByteFrame()
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
bf.WriteUint8(uint8(pkt.WorldID))
|
||||||
|
bf.WriteUint8(uint8(pkt.LandID))
|
||||||
|
bf.WriteUint16(s.server.raviente.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
|
||||||
|
Data uint32
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysOperateRegister)
|
pkt := p.(*mhfpacket.MsgSysOperateRegister)
|
||||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
|
||||||
|
var raviUpdates []RaviUpdate
|
||||||
|
var raviUpdate RaviUpdate
|
||||||
|
// 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()
|
||||||
|
raviUpdates = append(raviUpdates, raviUpdate)
|
||||||
|
}
|
||||||
|
bf = byteframe.NewByteFrame()
|
||||||
|
|
||||||
|
var _old, _new uint32
|
||||||
s.server.raviente.Lock()
|
s.server.raviente.Lock()
|
||||||
switch pkt.SemaphoreID {
|
for _, update := range raviUpdates {
|
||||||
case 4:
|
switch update.Op {
|
||||||
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:
|
case 2:
|
||||||
resp.WriteUint32(*ref)
|
_old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true)
|
||||||
if dest == 28 { // Berserk resurrection tracker
|
case 13, 14:
|
||||||
resp.WriteUint32(*ref + data)
|
_old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false)
|
||||||
*ref += data
|
|
||||||
} else if dest == 17 { // Berserk poison tracker
|
|
||||||
if damageMultiplier == 1 {
|
|
||||||
resp.WriteUint32(*ref + data)
|
|
||||||
*ref += data
|
|
||||||
} else {
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
}
|
}
|
||||||
} else {
|
bf.WriteUint8(1)
|
||||||
data = uint32(float64(data) * damageMultiplier)
|
bf.WriteUint8(update.Dest)
|
||||||
resp.WriteUint32(*ref + data)
|
bf.WriteUint32(_old)
|
||||||
*ref += data
|
bf.WriteUint32(_new)
|
||||||
}
|
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
s.server.raviente.Unlock()
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
|
|
||||||
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
|
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
|
||||||
s.notifyRavi()
|
s.notifyRavi()
|
||||||
}
|
}
|
||||||
s.server.raviente.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysLoadRegister)
|
pkt := p.(*mhfpacket.MsgSysLoadRegister)
|
||||||
r := pkt.Unk1
|
bf := byteframe.NewByteFrame()
|
||||||
switch r {
|
bf.WriteUint8(0)
|
||||||
case 12:
|
bf.WriteUint8(pkt.Values)
|
||||||
resp := byteframe.NewByteFrame()
|
for i := uint8(0); i < pkt.Values; i++ {
|
||||||
resp.WriteUint8(0)
|
switch pkt.RegisterID {
|
||||||
resp.WriteUint8(12)
|
case 0x40000:
|
||||||
resp.WriteUint32(s.server.raviente.register.nextTime)
|
bf.WriteUint32(s.server.raviente.state[i])
|
||||||
resp.WriteUint32(s.server.raviente.register.startTime)
|
case 0x50000:
|
||||||
resp.WriteUint32(s.server.raviente.register.killedTime)
|
bf.WriteUint32(s.server.raviente.support[i])
|
||||||
resp.WriteUint32(s.server.raviente.register.postTime)
|
case 0x60000:
|
||||||
resp.WriteUint32(s.server.raviente.register.register[0])
|
bf.WriteUint32(s.server.raviente.register[i])
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
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() {
|
func (s *Session) notifyRavi() {
|
||||||
sema := getRaviSemaphore(s.server)
|
sema := s.server.getRaviSemaphore()
|
||||||
if sema == nil {
|
if sema == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var temp mhfpacket.MHFPacket
|
var temp mhfpacket.MHFPacket
|
||||||
raviNotif := byteframe.NewByteFrame()
|
raviNotif := byteframe.NewByteFrame()
|
||||||
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 4}
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x40000}
|
||||||
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
temp.Build(raviNotif, s.clientContext)
|
temp.Build(raviNotif, s.clientContext)
|
||||||
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 5}
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x50000}
|
||||||
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
temp.Build(raviNotif, s.clientContext)
|
temp.Build(raviNotif, s.clientContext)
|
||||||
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 6}
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x60000}
|
||||||
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
temp.Build(raviNotif, s.clientContext)
|
temp.Build(raviNotif, s.clientContext)
|
||||||
raviNotif.WriteUint16(0x0010) // End it.
|
raviNotif.WriteUint16(0x0010) // End it.
|
||||||
@@ -272,28 +140,13 @@ func (s *Session) notifyRavi() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRaviSemaphore(s *Server) *Semaphore {
|
func (s *Server) getRaviSemaphore() *Semaphore {
|
||||||
for _, semaphore := range s.semaphore {
|
for _, semaphore := range s.semaphore {
|
||||||
if strings.HasPrefix(semaphore.id_semaphore, "hs_l0u3B5") && strings.HasSuffix(semaphore.id_semaphore, "3") {
|
if strings.HasPrefix(semaphore.name, "hs_l0") && strings.HasSuffix(semaphore.name, "3") {
|
||||||
return semaphore
|
return semaphore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package channelserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
"fmt"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -13,9 +12,6 @@ import (
|
|||||||
func removeSessionFromSemaphore(s *Session) {
|
func removeSessionFromSemaphore(s *Session) {
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
for _, semaphore := range s.server.semaphore {
|
for _, semaphore := range s.server.semaphore {
|
||||||
if _, exists := semaphore.reservedClientSlots[s.charID]; exists {
|
|
||||||
delete(semaphore.reservedClientSlots, s.charID)
|
|
||||||
}
|
|
||||||
if _, exists := semaphore.clients[s]; exists {
|
if _, exists := semaphore.clients[s]; exists {
|
||||||
delete(semaphore.clients, s)
|
delete(semaphore.clients, s)
|
||||||
}
|
}
|
||||||
@@ -31,48 +27,38 @@ func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func destructEmptySemaphores(s *Session) {
|
func destructEmptySemaphores(s *Session) {
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
for id, sema := range s.server.semaphore {
|
for id, sema := range s.server.semaphore {
|
||||||
if len(sema.reservedClientSlots) == 0 && len(sema.clients) == 0 {
|
if len(sema.clients) == 0 {
|
||||||
s.server.semaphoreLock.Unlock()
|
|
||||||
delete(s.server.semaphore, id)
|
delete(s.server.semaphore, id)
|
||||||
s.server.semaphoreLock.Lock()
|
if strings.HasPrefix(id, "hs_l0") {
|
||||||
if strings.HasPrefix(id, "hs_l0u3B5") {
|
s.server.resetRaviente()
|
||||||
releaseRaviSemaphore(s, sema)
|
|
||||||
}
|
}
|
||||||
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()
|
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")
|
|
||||||
resetRavi(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
||||||
if s.server.semaphore != nil {
|
|
||||||
destructEmptySemaphores(s)
|
destructEmptySemaphores(s)
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
for id, sema := range s.server.semaphore {
|
for id, sema := range s.server.semaphore {
|
||||||
if sema.id == pkt.SemaphoreID {
|
if sema.id == pkt.SemaphoreID {
|
||||||
if strings.HasPrefix(id, "hs_l0u3B5") {
|
for session := range sema.clients {
|
||||||
releaseRaviSemaphore(s, sema)
|
if s == session {
|
||||||
s.server.semaphoreLock.Unlock()
|
delete(sema.clients, s)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
s.server.semaphoreLock.Unlock()
|
}
|
||||||
|
if len(sema.clients) == 0 {
|
||||||
delete(s.server.semaphore, id)
|
delete(s.server.semaphore, id)
|
||||||
s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id))
|
if strings.HasPrefix(id, "hs_l0") {
|
||||||
return
|
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) {
|
func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
@@ -80,17 +66,14 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
SemaphoreID := pkt.SemaphoreID
|
SemaphoreID := pkt.SemaphoreID
|
||||||
|
|
||||||
newSemaphore, exists := s.server.semaphore[SemaphoreID]
|
newSemaphore, exists := s.server.semaphore[SemaphoreID]
|
||||||
|
|
||||||
fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID)
|
|
||||||
if !exists {
|
if !exists {
|
||||||
s.server.semaphoreLock.Lock()
|
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:])
|
suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:])
|
||||||
s.server.semaphore[SemaphoreID] = &Semaphore{
|
s.server.semaphore[SemaphoreID] = &Semaphore{
|
||||||
id_semaphore: pkt.SemaphoreID,
|
name: pkt.SemaphoreID,
|
||||||
id: uint32(suffix + 1),
|
id: uint32((suffix + 1) * 0x10000),
|
||||||
clients: make(map[*Session]uint32),
|
clients: make(map[*Session]uint32),
|
||||||
reservedClientSlots: make(map[uint32]interface{}),
|
|
||||||
maxPlayers: 127,
|
maxPlayers: 127,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -102,22 +85,19 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
newSemaphore.Lock()
|
newSemaphore.Lock()
|
||||||
defer newSemaphore.Unlock()
|
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)
|
bf.WriteUint32(newSemaphore.id)
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
} else if uint16(len(newSemaphore.clients)) < newSemaphore.maxPlayers {
|
||||||
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
|
||||||
newSemaphore.clients[s] = s.charID
|
newSemaphore.clients[s] = s.charID
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.semaphore = newSemaphore
|
s.semaphore = newSemaphore
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
bf := byteframe.NewByteFrame()
|
|
||||||
bf.WriteUint32(newSemaphore.id)
|
bf.WriteUint32(newSemaphore.id)
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
|
||||||
} else {
|
} 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) {
|
func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
@@ -130,7 +110,6 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
} else {
|
} else {
|
||||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package channelserver
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
@@ -76,61 +77,30 @@ type Server struct {
|
|||||||
|
|
||||||
type Raviente struct {
|
type Raviente struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
id uint16
|
||||||
register *RavienteRegister
|
|
||||||
state *RavienteState
|
|
||||||
support *RavienteSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
type RavienteRegister struct {
|
|
||||||
nextTime uint32
|
|
||||||
startTime uint32
|
|
||||||
postTime uint32
|
|
||||||
killedTime uint32
|
|
||||||
ravienteType uint32
|
|
||||||
maxPlayers uint32
|
|
||||||
carveQuest uint32
|
|
||||||
register []uint32
|
register []uint32
|
||||||
|
state []uint32
|
||||||
|
support []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type RavienteState struct {
|
func (s *Server) resetRaviente() {
|
||||||
stateData []uint32
|
for _, semaphore := range s.semaphore {
|
||||||
}
|
if strings.HasPrefix(semaphore.name, "hs_l0") {
|
||||||
|
return
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
return raviente
|
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)
|
||||||
|
s.raviente.support = make([]uint32, 30)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Raviente) GetRaviMultiplier(s *Server) float64 {
|
func (s *Server) GetRaviMultiplier() float64 {
|
||||||
raviSema := getRaviSemaphore(s)
|
raviSema := s.getRaviSemaphore()
|
||||||
if raviSema != nil {
|
if raviSema != nil {
|
||||||
var minPlayers int
|
var minPlayers int
|
||||||
if r.register.maxPlayers > 8 {
|
if s.raviente.register[9] > 8 {
|
||||||
minPlayers = 24
|
minPlayers = 24
|
||||||
} else {
|
} else {
|
||||||
minPlayers = 4
|
minPlayers = 4
|
||||||
@@ -143,6 +113,40 @@ func (r *Raviente) GetRaviMultiplier(s *Server) float64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) {
|
||||||
|
var prev uint32
|
||||||
|
switch semaID {
|
||||||
|
case 0x40000:
|
||||||
|
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 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 0x60000:
|
||||||
|
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.
|
// NewServer creates a new Server type.
|
||||||
func NewServer(config *Config) *Server {
|
func NewServer(config *Config) *Server {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
@@ -160,7 +164,12 @@ func NewServer(config *Config) *Server {
|
|||||||
semaphoreIndex: 7,
|
semaphoreIndex: 7,
|
||||||
discordBot: config.DiscordBot,
|
discordBot: config.DiscordBot,
|
||||||
name: config.Name,
|
name: config.Name,
|
||||||
raviente: NewRaviente(),
|
raviente: &Raviente{
|
||||||
|
id: 1,
|
||||||
|
register: make([]uint32, 30),
|
||||||
|
state: make([]uint32, 30),
|
||||||
|
support: make([]uint32, 30),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mezeporta
|
// Mezeporta
|
||||||
@@ -393,15 +402,16 @@ func (s *Server) NextSemaphoreID() uint32 {
|
|||||||
for {
|
for {
|
||||||
exists := false
|
exists := false
|
||||||
s.semaphoreIndex = s.semaphoreIndex + 1
|
s.semaphoreIndex = s.semaphoreIndex + 1
|
||||||
if s.semaphoreIndex == 0 {
|
if s.semaphoreIndex > 0xFFFF {
|
||||||
s.semaphoreIndex = 7 // Skip reserved indexes
|
s.semaphoreIndex = 1
|
||||||
}
|
}
|
||||||
for _, semaphore := range s.semaphore {
|
for _, semaphore := range s.semaphore {
|
||||||
if semaphore.id == s.semaphoreIndex {
|
if semaphore.id == s.semaphoreIndex {
|
||||||
exists = true
|
exists = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if exists == false {
|
if !exists {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func getLangStrings(s *Server) map[string]string {
|
|||||||
strings["commandRaviRequest"] = "鎮静支援を要請します"
|
strings["commandRaviRequest"] = "鎮静支援を要請します"
|
||||||
strings["commandRaviError"] = "ラヴィコマンドが認識されません"
|
strings["commandRaviError"] = "ラヴィコマンドが認識されません"
|
||||||
strings["commandRaviNoPlayers"] = "誰も大討伐に参加していません"
|
strings["commandRaviNoPlayers"] = "誰も大討伐に参加していません"
|
||||||
|
strings["commandRaviVersion"] = "This command is disabled outside of MHFZZ"
|
||||||
|
|
||||||
strings["ravienteBerserk"] = "<大討伐:猛狂期>が開催されました!"
|
strings["ravienteBerserk"] = "<大討伐:猛狂期>が開催されました!"
|
||||||
strings["ravienteExtreme"] = "<大討伐:猛狂期【極】>が開催されました!"
|
strings["ravienteExtreme"] = "<大討伐:猛狂期【極】>が開催されました!"
|
||||||
@@ -85,6 +86,7 @@ func getLangStrings(s *Server) map[string]string {
|
|||||||
strings["commandRaviRequest"] = "Requesting sedation support!"
|
strings["commandRaviRequest"] = "Requesting sedation support!"
|
||||||
strings["commandRaviError"] = "Raviente command not recognised!"
|
strings["commandRaviError"] = "Raviente command not recognised!"
|
||||||
strings["commandRaviNoPlayers"] = "No one has joined the Great Slaying!"
|
strings["commandRaviNoPlayers"] = "No one has joined the Great Slaying!"
|
||||||
|
strings["commandRaviVersion"] = "This command is disabled outside of MHFZZ"
|
||||||
|
|
||||||
strings["ravienteBerserk"] = "<Great Slaying: Berserk> is being held!"
|
strings["ravienteBerserk"] = "<Great Slaying: Berserk> is being held!"
|
||||||
strings["ravienteExtreme"] = "<Great Slaying: Extreme> is being held!"
|
strings["ravienteExtreme"] = "<Great Slaying: Extreme> is being held!"
|
||||||
|
|||||||
@@ -7,55 +7,35 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stage holds stage-specific information
|
// Semaphore holds Semaphore-specific information
|
||||||
type Semaphore struct {
|
type Semaphore struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
// Stage ID string
|
// Semaphore ID string
|
||||||
id_semaphore string
|
name string
|
||||||
|
|
||||||
id uint32
|
id uint32
|
||||||
|
|
||||||
// Map of session -> charID.
|
// 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
|
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
|
// Max Players for Semaphore
|
||||||
maxPlayers uint16
|
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 {
|
func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore {
|
||||||
sema := &Semaphore{
|
sema := &Semaphore{
|
||||||
id_semaphore: ID,
|
name: ID,
|
||||||
id: s.NextSemaphoreID(),
|
id: s.NextSemaphoreID(),
|
||||||
clients: make(map[*Session]uint32),
|
clients: make(map[*Session]uint32),
|
||||||
reservedClientSlots: make(map[uint32]interface{}),
|
|
||||||
maxPlayers: MaxPlayers,
|
maxPlayers: MaxPlayers,
|
||||||
}
|
}
|
||||||
return sema
|
return sema
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
|
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the Semaphore
|
||||||
// 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.
|
|
||||||
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||||
// Broadcast the data.
|
// Broadcast the data.
|
||||||
for session := range s.clients {
|
for session := range s.clients {
|
||||||
|
|||||||
Reference in New Issue
Block a user