Merge branch 'main' into main

This commit is contained in:
wish
2022-06-16 11:36:51 +10:00
committed by GitHub
12 changed files with 1279 additions and 2204 deletions

View File

@@ -12,6 +12,8 @@ type OperateMailOperation uint8
const (
OPERATE_MAIL_DELETE = 0x01
OPERATE_MAIL_LOCK = 0x02
OPERATE_MAIL_UNLOCK = 0x03
OPERATE_MAIL_ACQUIRE_ITEM = 0x05
)

View File

@@ -9,7 +9,14 @@ import (
)
// MsgMhfTransitMessage represents the MSG_MHF_TRANSIT_MESSAGE
type MsgMhfTransitMessage struct{}
type MsgMhfTransitMessage struct {
AckHandle uint32
Unk0 uint8
Unk1 uint8
Unk2 uint16
Unk3 uint16
TargetID uint32
}
// Opcode returns the ID associated with this packet type.
func (m *MsgMhfTransitMessage) Opcode() network.PacketID {
@@ -18,7 +25,13 @@ func (m *MsgMhfTransitMessage) Opcode() network.PacketID {
// Parse parses the packet from binary
func (m *MsgMhfTransitMessage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED")
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8()
m.Unk2 = bf.ReadUint16()
m.Unk3 = bf.ReadUint16()
m.TargetID = bf.ReadUint32()
return nil
}
// Build builds a binary packet from the current data.

View File

@@ -183,13 +183,12 @@ func logoutPlayer(s *Session) {
return
}
s.stage.RLock()
for client := range s.stage.clients {
client.QueueSendMHF(&mhfpacket.MsgSysDeleteUser{
s.server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser {
CharID: s.charID,
})
}
s.stage.RUnlock()
}, s)
delete(s.server.sessions, s.rawConn)
s.rawConn.Close()
if s.server.erupeConfig.DevModeOptions.ServerName != "" {
_, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_name=$2", uint32(len(s.server.sessions)), s.server.erupeConfig.DevModeOptions.ServerName)
@@ -198,13 +197,16 @@ func logoutPlayer(s *Session) {
}
}
removeSessionFromStage(s)
s.server.Lock()
for _, stage := range s.server.stages {
if _, exists := stage.reservedClientSlots[s.charID]; exists {
delete(stage.reservedClientSlots, s.charID)
}
}
s.server.Unlock()
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
if _, ok := s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots[s.charID]; ok {
removeSessionFromSemaphore(s)
}
}
removeSessionFromStage(s)
var timePlayed int
err := s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed)
@@ -213,7 +215,7 @@ func logoutPlayer(s *Session) {
var rpGained int
if s.rights == 0x08091e4e || s.rights == 0x08091e0e { // N Course
if s.rights > 0x40000000 { // N Course
rpGained = timePlayed / 900
timePlayed = timePlayed % 900
} else {
@@ -326,7 +328,13 @@ func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}
func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfTransitMessage)
// TODO: figure out what this is supposed to return
// probably what world+land the targeted character is on?
// stubbed response will just say user not found
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {}
@@ -699,241 +707,726 @@ func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
}
func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfInfoScenarioCounter)
scenarioCounter := []struct {
Unk0 uint32 // Main ID?
Unk1 uint8
Unk2 uint8
MainID uint32
Unk1 uint8 // Bool item exchange?
// 0 = basic, 1 = veteran, 3 = other, 6 = pallone, 7 = diva
CategoryID uint8
}{
//000000110000
{
Unk0: 0x00000000,
Unk1: 1,
Unk2: 4,
MainID: 0x00000011, Unk1: 0, CategoryID: 0,
},
// 0000005D0001
{
Unk0: 0x00000001,
Unk1: 1,
Unk2: 4,
MainID: 0x0000005D, Unk1: 0, CategoryID: 1,
},
// 0000005C0001
{
Unk0: 0x00000002,
Unk1: 1,
Unk2: 4,
MainID: 0x0000005C, Unk1: 0, CategoryID: 1,
},
// 000000510001
{
Unk0: 0x00000003,
Unk1: 1,
Unk2: 4,
MainID: 0x00000051, Unk1: 0, CategoryID: 1,
},
// 0000005B0001
{
Unk0: 0x00000004,
Unk1: 1,
Unk2: 4,
MainID: 0x0000005B, Unk1: 0, CategoryID: 1,
},
// 0000005A0001
{
Unk0: 0x00000005,
Unk1: 1,
Unk2: 4,
MainID: 0x0000005A, Unk1: 0, CategoryID: 1,
},
// 000000590001
{
Unk0: 0x00000006,
Unk1: 1,
Unk2: 4,
MainID: 0x00000059, Unk1: 0, CategoryID: 1,
},
// 000000580001
{
Unk0: 0x00000007,
Unk1: 1,
Unk2: 4,
MainID: 0x00000058, Unk1: 0, CategoryID: 1,
},
// 000000570001
{
Unk0: 0x00000008,
Unk1: 1,
Unk2: 4,
MainID: 0x00000057, Unk1: 0, CategoryID: 1,
},
// 000000560001
{
Unk0: 0x00000009,
Unk1: 1,
Unk2: 4,
MainID: 0x00000056, Unk1: 0, CategoryID: 1,
},
// 000000550001
{
Unk0: 0x0000000A,
Unk1: 1,
Unk2: 4,
MainID: 0x00000055, Unk1: 0, CategoryID: 1,
},
// 000000540001
{
Unk0: 0x0000000B,
Unk1: 1,
Unk2: 4,
MainID: 0x00000054, Unk1: 0, CategoryID: 1,
},
// 000000530001
{
Unk0: 0x0000000C,
Unk1: 1,
Unk2: 4,
MainID: 0x00000053, Unk1: 0, CategoryID: 1,
},
// 000000520001
{
Unk0: 0x0000000D,
Unk1: 1,
Unk2: 4,
MainID: 0x00000052, Unk1: 0, CategoryID: 1,
},
// 000000570103
{
Unk0: 0x0000000E,
Unk1: 1,
Unk2: 4,
MainID: 0x00000057, Unk1: 1, CategoryID: 3,
},
// 000000580103
{
Unk0: 0x00000032,
Unk1: 1,
Unk2: 5,
MainID: 0x00000058, Unk1: 1, CategoryID: 3,
},
// 000000590103
{
Unk0: 0x00000033,
Unk1: 1,
Unk2: 5,
MainID: 0x00000059, Unk1: 1, CategoryID: 3,
},
// 0000005A0103
{
Unk0: 0x00000034,
Unk1: 1,
Unk2: 5,
MainID: 0x0000005A, Unk1: 1, CategoryID: 3,
},
// 0000005B0103
{
Unk0: 0x00000035,
Unk1: 1,
Unk2: 5,
MainID: 0x0000005B, Unk1: 1, CategoryID: 3,
},
// 0000005C0103
{
Unk0: 0x00000036,
Unk1: 1,
Unk2: 5,
MainID: 0x0000005C, Unk1: 1, CategoryID: 3,
},
// 000000530103
{
Unk0: 0x00000037,
Unk1: 1,
Unk2: 5,
MainID: 0x00000053, Unk1: 1, CategoryID: 3,
},
// 000000560103
{
Unk0: 0x00000038,
Unk1: 1,
Unk2: 5,
MainID: 0x00000056, Unk1: 1, CategoryID: 3,
},
// 0000003C0103
{
Unk0: 0x0000003A,
Unk1: 1,
Unk2: 5,
MainID: 0x0000003C, Unk1: 1, CategoryID: 3,
},
// 0000003A0103
{
Unk0: 0x0000003F,
Unk1: 1,
Unk2: 5,
MainID: 0x0000003A, Unk1: 1, CategoryID: 3,
},
// 0000003B0103
{
Unk0: 0x00000040,
Unk1: 1,
Unk2: 5,
MainID: 0x0000003B, Unk1: 1, CategoryID: 3,
},
// 0000001B0103
{
Unk0: 0x00000041,
Unk1: 1,
Unk2: 5,
MainID: 0x0000001B, Unk1: 1, CategoryID: 3,
},
// 000000190103
{
Unk0: 0x00000047,
Unk1: 1,
Unk2: 5,
MainID: 0x00000019, Unk1: 1, CategoryID: 3,
},
// 0000001A0103
{
Unk0: 0x0000004B,
Unk1: 1,
Unk2: 5,
MainID: 0x0000001A, Unk1: 1, CategoryID: 3,
},
// 000000170103
{
Unk0: 0x0000003D,
Unk1: 1,
Unk2: 5,
MainID: 0x00000017, Unk1: 1, CategoryID: 3,
},
// 000000020103
{
Unk0: 0x00000044,
Unk1: 1,
Unk2: 5,
MainID: 0x00000002, Unk1: 1, CategoryID: 3,
},
// 000000030103
{
Unk0: 0x00000042,
Unk1: 1,
Unk2: 5,
MainID: 0x00000003, Unk1: 1, CategoryID: 3,
},
// 000000040103
{
Unk0: 0x0000004C,
Unk1: 1,
Unk2: 5,
MainID: 0x00000004, Unk1: 1, CategoryID: 3,
},
// 0000001F0103
{
Unk0: 0x00000046,
Unk1: 1,
Unk2: 5,
MainID: 0x0000001F, Unk1: 1, CategoryID: 3,
},
// 000000200103
{
Unk0: 0x0000004D,
Unk1: 1,
Unk2: 5,
MainID: 0x00000020, Unk1: 1, CategoryID: 3,
},
// 000000210103
{
Unk0: 0x00000048,
Unk1: 1,
Unk2: 5,
MainID: 0x00000021, Unk1: 1, CategoryID: 3,
},
// 000000220103
{
Unk0: 0x0000004A,
Unk1: 1,
Unk2: 5,
MainID: 0x00000022, Unk1: 1, CategoryID: 3,
},
// 000000230103
{
Unk0: 0x00000049,
Unk1: 1,
Unk2: 5,
MainID: 0x00000023, Unk1: 1, CategoryID: 3,
},
// 000000240103
{
Unk0: 0x0000004E,
Unk1: 1,
Unk2: 5,
MainID: 0x00000024, Unk1: 1, CategoryID: 3,
},
// 000000250103
{
Unk0: 0x00000045,
Unk1: 1,
Unk2: 5,
MainID: 0x00000025, Unk1: 1, CategoryID: 3,
},
// 000000280103
{
Unk0: 0x0000003E,
Unk1: 1,
Unk2: 5,
MainID: 0x00000028, Unk1: 1, CategoryID: 3,
},
// 000000260103
{
Unk0: 0x0000004F,
Unk1: 1,
Unk2: 5,
MainID: 0x00000026, Unk1: 1, CategoryID: 3,
},
// 000000270103
{
MainID: 0x00000027, Unk1: 1, CategoryID: 3,
},
// 000000300103
{
MainID: 0x00000030, Unk1: 1, CategoryID: 3,
},
// 0000000C0103
{
MainID: 0x0000000C, Unk1: 1, CategoryID: 3,
},
// 0000000D0103
{
MainID: 0x0000000D, Unk1: 1, CategoryID: 3,
},
// 0000001E0103
{
MainID: 0x0000001E, Unk1: 1, CategoryID: 3,
},
// 0000001D0103
{
MainID: 0x0000001D, Unk1: 1, CategoryID: 3,
},
// 0000002E0003
{
MainID: 0x0000002E, Unk1: 0, CategoryID: 3,
},
// 000000000004
{
MainID: 0x00000000, Unk1: 0, CategoryID: 4,
},
// 000000010004
{
MainID: 0x00000001, Unk1: 0, CategoryID: 4,
},
// 000000020004
{
MainID: 0x00000002, Unk1: 0, CategoryID: 4,
},
// 000000030004
{
MainID: 0x00000003, Unk1: 0, CategoryID: 4,
},
// 000000040004
{
MainID: 0x00000004, Unk1: 0, CategoryID: 4,
},
// 000000050004
{
MainID: 0x00000005, Unk1: 0, CategoryID: 4,
},
// 000000060004
{
MainID: 0x00000006, Unk1: 0, CategoryID: 4,
},
// 000000070004
{
MainID: 0x00000007, Unk1: 0, CategoryID: 4,
},
// 000000080004
{
MainID: 0x00000008, Unk1: 0, CategoryID: 4,
},
// 000000090004
{
MainID: 0x00000009, Unk1: 0, CategoryID: 4,
},
// 0000000A0004
{
MainID: 0x0000000A, Unk1: 0, CategoryID: 4,
},
// 0000000B0004
{
MainID: 0x0000000B, Unk1: 0, CategoryID: 4,
},
// 0000000C0004
{
MainID: 0x0000000C, Unk1: 0, CategoryID: 4,
},
// 0000000D0004
{
MainID: 0x0000000D, Unk1: 0, CategoryID: 4,
},
// 0000000E0004
{
MainID: 0x0000000E, Unk1: 0, CategoryID: 4,
},
// 000000320005
{
MainID: 0x00000032, Unk1: 0, CategoryID: 5,
},
// 000000330005
{
MainID: 0x00000033, Unk1: 0, CategoryID: 5,
},
// 000000340005
{
MainID: 0x00000034, Unk1: 0, CategoryID: 5,
},
// 000000350005
{
MainID: 0x00000035, Unk1: 0, CategoryID: 5,
},
// 000000360005
{
MainID: 0x00000036, Unk1: 0, CategoryID: 5,
},
// 000000370005
{
MainID: 0x00000037, Unk1: 0, CategoryID: 5,
},
// 000000380005
{
MainID: 0x00000038, Unk1: 0, CategoryID: 5,
},
// 0000003A0005
{
MainID: 0x0000003A, Unk1: 0, CategoryID: 5,
},
// 0000003F0005
{
MainID: 0x0000003F, Unk1: 0, CategoryID: 5,
},
// 000000400005
{
MainID: 0x00000040, Unk1: 0, CategoryID: 5,
},
// 000000410005
{
MainID: 0x00000041, Unk1: 0, CategoryID: 5,
},
// 000000430005
{
MainID: 0x00000043, Unk1: 0, CategoryID: 5,
},
// 000000470005
{
MainID: 0x00000047, Unk1: 0, CategoryID: 5,
},
// 0000004B0005
{
MainID: 0x0000004B, Unk1: 0, CategoryID: 5,
},
// 0000003D0005
{
MainID: 0x0000003D, Unk1: 0, CategoryID: 5,
},
// 000000440005
{
MainID: 0x00000044, Unk1: 0, CategoryID: 5,
},
// 000000420005
{
MainID: 0x00000042, Unk1: 0, CategoryID: 5,
},
// 0000004C0005
{
MainID: 0x0000004C, Unk1: 0, CategoryID: 5,
},
// 000000460005
{
MainID: 0x00000046, Unk1: 0, CategoryID: 5,
},
// 0000004D0005
{
MainID: 0x0000004D, Unk1: 0, CategoryID: 5,
},
// 000000480005
{
MainID: 0x00000048, Unk1: 0, CategoryID: 5,
},
// 0000004A0005
{
MainID: 0x0000004A, Unk1: 0, CategoryID: 5,
},
// 000000490005
{
MainID: 0x00000049, Unk1: 0, CategoryID: 5,
},
// 0000004E0005
{
MainID: 0x0000004E, Unk1: 0, CategoryID: 5,
},
// 000000450005
{
MainID: 0x00000045, Unk1: 0, CategoryID: 5,
},
// 0000003E0005
{
MainID: 0x0000003E, Unk1: 0, CategoryID: 5,
},
// 0000004F0005
{
MainID: 0x0000004F, Unk1: 0, CategoryID: 5,
},
// 000000000106
{
MainID: 0x00000000, Unk1: 1, CategoryID: 6,
},
// 000000010106
{
MainID: 0x00000001, Unk1: 1, CategoryID: 6,
},
// 000000020106
{
MainID: 0x00000002, Unk1: 1, CategoryID: 6,
},
// 000000030106
{
MainID: 0x00000003, Unk1: 1, CategoryID: 6,
},
// 000000040106
{
MainID: 0x00000004, Unk1: 1, CategoryID: 6,
},
// 000000050106
{
MainID: 0x00000005, Unk1: 1, CategoryID: 6,
},
// 000000060106
{
MainID: 0x00000006, Unk1: 1, CategoryID: 6,
},
// 000000070106
{
MainID: 0x00000007, Unk1: 1, CategoryID: 6,
},
// 000000080106
{
MainID: 0x00000008, Unk1: 1, CategoryID: 6,
},
// 000000090106
{
MainID: 0x00000009, Unk1: 1, CategoryID: 6,
},
// 000000110106
{
MainID: 0x00000011, Unk1: 1, CategoryID: 6,
},
// 0000000A0106
{
MainID: 0x0000000A, Unk1: 1, CategoryID: 6,
},
// 0000000B0106
{
MainID: 0x0000000B, Unk1: 1, CategoryID: 6,
},
// 0000000C0106
{
MainID: 0x0000000C, Unk1: 1, CategoryID: 6,
},
// 0000000D0106
{
MainID: 0x0000000D, Unk1: 1, CategoryID: 6,
},
// 0000000E0106
{
MainID: 0x0000000E, Unk1: 1, CategoryID: 6,
},
// 0000000F0106
{
MainID: 0x0000000F, Unk1: 1, CategoryID: 6,
},
// 000000100106
{
MainID: 0x00000010, Unk1: 1, CategoryID: 6,
},
// 000000320107
{
MainID: 0x00000032, Unk1: 1, CategoryID: 7,
},
// 000000350107
{
MainID: 0x00000035, Unk1: 1, CategoryID: 7,
},
// 0000003E0107
{
MainID: 0x0000003E, Unk1: 1, CategoryID: 7,
},
// 000000340107
{
MainID: 0x00000034, Unk1: 1, CategoryID: 7,
},
// 000000380107
{
MainID: 0x00000038, Unk1: 1, CategoryID: 7,
},
// 000000330107
{
MainID: 0x00000033, Unk1: 1, CategoryID: 7,
},
// 000000310107
{
MainID: 0x00000031, Unk1: 1, CategoryID: 7,
},
// 000000360107
{
MainID: 0x00000036, Unk1: 1, CategoryID: 7,
},
// 000000390107
{
MainID: 0x00000039, Unk1: 1, CategoryID: 7,
},
// 000000370107
{
MainID: 0x00000037, Unk1: 1, CategoryID: 7,
},
// 0000003D0107
{
MainID: 0x0000003D, Unk1: 1, CategoryID: 7,
},
// 0000003A0107
{
MainID: 0x0000003A, Unk1: 1, CategoryID: 7,
},
// 0000003C0107
{
MainID: 0x0000003C, Unk1: 1, CategoryID: 7,
},
// 0000003B0107
{
MainID: 0x0000003B, Unk1: 1, CategoryID: 7,
},
// 0000002A0107
{
MainID: 0x0000002A, Unk1: 1, CategoryID: 7,
},
// 000000300107
{
MainID: 0x00000030, Unk1: 1, CategoryID: 7,
},
// 000000280107
{
MainID: 0x00000028, Unk1: 1, CategoryID: 7,
},
// 000000270107
{
MainID: 0x00000027, Unk1: 1, CategoryID: 7,
},
// 0000002B0107
{
MainID: 0x0000002B, Unk1: 1, CategoryID: 7,
},
// 0000002E0107
{
MainID: 0x0000002E, Unk1: 1, CategoryID: 7,
},
// 000000290107
{
MainID: 0x00000029, Unk1: 1, CategoryID: 7,
},
// 0000002C0107
{
MainID: 0x0000002C, Unk1: 1, CategoryID: 7,
},
// 0000002D0107
{
MainID: 0x0000002D, Unk1: 1, CategoryID: 7,
},
// 0000002F0107
{
MainID: 0x0000002F, Unk1: 1, CategoryID: 7,
},
// 000000250107
{
MainID: 0x00000025, Unk1: 1, CategoryID: 7,
},
// 000000220107
{
MainID: 0x00000022, Unk1: 1, CategoryID: 7,
},
// 000000210107
{
MainID: 0x00000021, Unk1: 1, CategoryID: 7,
},
// 000000200107
{
MainID: 0x00000020, Unk1: 1, CategoryID: 7,
},
// 0000001C0107
{
MainID: 0x0000001C, Unk1: 1, CategoryID: 7,
},
// 0000001A0107
{
MainID: 0x0000001A, Unk1: 1, CategoryID: 7,
},
// 000000240107
{
MainID: 0x00000024, Unk1: 1, CategoryID: 7,
},
// 000000260107
{
MainID: 0x00000026, Unk1: 1, CategoryID: 7,
},
// 000000230107
{
MainID: 0x00000023, Unk1: 1, CategoryID: 7,
},
// 0000001B0107
{
MainID: 0x0000001B, Unk1: 1, CategoryID: 7,
},
// 0000001E0107
{
MainID: 0x0000001E, Unk1: 1, CategoryID: 7,
},
// 0000001F0107
{
MainID: 0x0000001F, Unk1: 1, CategoryID: 7,
},
// 0000001D0107
{
MainID: 0x0000001D, Unk1: 1, CategoryID: 7,
},
// 000000180107
{
MainID: 0x00000018, Unk1: 1, CategoryID: 7,
},
// 000000170107
{
MainID: 0x00000017, Unk1: 1, CategoryID: 7,
},
// 000000160107
{
MainID: 0x00000016, Unk1: 1, CategoryID: 7,
},
// 000000150107
// Missing file
// {
// MainID: 0x00000015, Unk1: 1, CategoryID: 7,
// },
// 000000190107
{
MainID: 0x00000019, Unk1: 1, CategoryID: 7,
},
// 000000140107
// Missing file
// {
// MainID: 0x00000014, Unk1: 1, CategoryID: 7,
// },
// 000000070107
// Missing file
// {
// MainID: 0x00000007, Unk1: 1, CategoryID: 7,
// },
// 000000090107
// Missing file
// {
// MainID: 0x00000009, Unk1: 1, CategoryID: 7,
// },
// 0000000D0107
// Missing file
// {
// MainID: 0x0000000D, Unk1: 1, CategoryID: 7,
// },
// 000000100107
// Missing file
// {
// MainID: 0x00000010, Unk1: 1, CategoryID: 7,
// },
// 0000000C0107
// Missing file
// {
// MainID: 0x0000000C, Unk1: 1, CategoryID: 7,
// },
// 0000000E0107
// Missing file
// {
// MainID: 0x0000000E, Unk1: 1, CategoryID: 7,
// },
// 0000000F0107
// Missing file
// {
// MainID: 0x0000000F, Unk1: 1, CategoryID: 7,
// },
// 000000130107
// Missing file
// {
// MainID: 0x00000013, Unk1: 1, CategoryID: 7,
// },
// 0000000A0107
// Missing file
// {
// MainID: 0x0000000A, Unk1: 1, CategoryID: 7,
// },
// 000000080107
// Missing file
// {
// MainID: 0x00000008, Unk1: 1, CategoryID: 7,
// },
// 0000000B0107
// Missing file
// {
// MainID: 0x0000000B, Unk1: 1, CategoryID: 7,
// },
// 000000120107
// Missing file
// {
// MainID: 0x00000012, Unk1: 1, CategoryID: 7,
// },
// 000000110107
// Missing file
// {
// MainID: 0x00000011, Unk1: 1, CategoryID: 7,
// },
// 000000060107
// Missing file
// {
// MainID: 0x00000006, Unk1: 1, CategoryID: 7,
// },
// 000000050107
// Missing file
// {
// MainID: 0x00000005, Unk1: 1, CategoryID: 7,
// },
// 000000040107
// Missing file
// {
// MainID: 0x00000004, Unk1: 1, CategoryID: 7,
// },
// 000000030107
{
MainID: 0x00000003, Unk1: 1, CategoryID: 7,
},
// 000000020107
{
MainID: 0x00000002, Unk1: 1, CategoryID: 7,
},
// 000000010107
{
MainID: 0x00000001, Unk1: 1, CategoryID: 7,
},
// 000000000107
{
MainID: 0x00000000, Unk1: 1, CategoryID: 7,
},
}
resp := byteframe.NewByteFrame()
resp.WriteUint8(uint8(len(scenarioCounter))) // Entry count
for _, entry := range scenarioCounter {
resp.WriteUint32(entry.Unk0)
resp.WriteUint32(entry.MainID)
resp.WriteUint8(entry.Unk1)
resp.WriteUint8(entry.Unk2)
resp.WriteUint8(entry.CategoryID)
}
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
// DEBUG, DELETE ME!
/*
data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "debug/info_scenario_counter_resp.bin"))
if err != nil {
panic(err)
}
doAckBufSucceed(s, pkt.AckHandle, data)
*/
}
func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -22,7 +22,7 @@ const (
const (
BroadcastTypeTargeted = 0x01
BroadcastTypeStage = 0x03
BroadcastTypeRavi = 0x06
BroadcastTypeSemaphore = 0x06
BroadcastTypeWorld = 0x0a
)
@@ -93,10 +93,24 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
s.server.BroadcastMHF(resp, s)
case BroadcastTypeStage:
s.stage.BroadcastMHF(resp, s)
case BroadcastTypeRavi:
case BroadcastTypeSemaphore:
if pkt.MessageType == 1 {
session := s.server.semaphore["hs_l0u3B51J9k3"]
var session *Semaphore
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
session = s.server.semaphore["hs_l0u3B51J9k3"]
} else if _, exists := s.server.semaphore["hs_l0u3B5129k3"]; exists {
session = s.server.semaphore["hs_l0u3B5129k3"]
} else if _, exists := s.server.semaphore["hs_l0u3B512Ak3"]; exists {
session = s.server.semaphore["hs_l0u3B512Ak3"]
}
(*session).BroadcastMHF(resp, s)
} else {
s.Lock()
haveStage := s.stage != nil
if haveStage {
s.stage.BroadcastMHF(resp, s)
}
s.Unlock()
}
case BroadcastTypeTargeted:
for _, targetID := range (*msgBinTargeted).TargetCharIDs {
@@ -133,113 +147,66 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message)
}
// RAVI COMMANDS
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
s.server.semaphoreLock.Lock()
getSemaphore := s.server.semaphore["hs_l0u3B51J9k3"]
s.server.semaphoreLock.Unlock()
if _, exists := getSemaphore.reservedClientSlots[s.charID]; exists {
if strings.HasPrefix(chatMessage.Message, "!ravistart") {
row := s.server.db.QueryRow("SELECT raviposttime, ravistarted FROM raviregister WHERE refid = 12")
var raviPosted, raviStarted uint32
err := row.Scan(&raviPosted, &raviStarted)
if err != nil {
panic(err)
return
}
if raviStarted == 0 {
sendServerChatMessage(s, fmt.Sprintf("Raviente will start in less than 10 seconds"))
s.server.db.Exec("UPDATE raviregister SET ravistarted = $1", raviPosted)
// RAVI COMMANDS V2
if strings.HasPrefix(chatMessage.Message, "!ravi") {
if checkRaviSemaphore(s) {
s.server.raviente.Lock()
if !strings.HasPrefix(chatMessage.Message, "!ravi ") {
sendServerChatMessage(s, "No Raviente command specified!")
} else {
sendServerChatMessage(s, fmt.Sprintf("Raviente has already started"))
}
}
if strings.HasPrefix(chatMessage.Message, "!bressend") {
row := s.server.db.QueryRow("SELECT unknown20 FROM ravistate WHERE refid = 29")
var berserkRes uint32
err := row.Scan(&berserkRes)
if err != nil {
panic(err)
return
}
if berserkRes > 0 {
sendServerChatMessage(s, fmt.Sprintf("Sending ressurection support"))
s.server.db.Exec("UPDATE ravistate SET unknown20 = $1", 0)
if strings.HasPrefix(chatMessage.Message, "!ravi start") {
if s.server.raviente.register.startTime == 0 {
s.server.raviente.register.startTime = s.server.raviente.register.postTime
sendServerChatMessage(s, "The Great Slaying will begin in a moment")
s.notifyall()
} else {
sendServerChatMessage(s, fmt.Sprintf("Ressurection support has not been requested"))
}
}
if strings.HasPrefix(chatMessage.Message, "!bsedsend") {
hprow := s.server.db.QueryRow("SELECT phase1hp, phase2hp, phase3hp, phase4hp, phase5hp FROM ravistate WHERE refid = 29")
var phase1HP, phase2HP, phase3HP, phase4HP, phase5HP uint32
hperr := hprow.Scan(&phase1HP, &phase2HP, &phase3HP, &phase4HP, &phase5HP)
if hperr != nil {
panic(hperr)
return
}
row := s.server.db.QueryRow("SELECT support2 FROM ravisupport WHERE refid = 25")
var berserkTranq uint32
err := row.Scan(&berserkTranq)
if err != nil {
panic(err)
return
}
sendServerChatMessage(s, fmt.Sprintf("Sending sedation support if requested"))
s.server.db.Exec("UPDATE ravisupport SET support2 = $1", (phase1HP + phase2HP + phase3HP + phase4HP + phase5HP))
}
if strings.HasPrefix(chatMessage.Message, "!bsedreq") {
hprow := s.server.db.QueryRow("SELECT phase1hp, phase2hp, phase3hp, phase4hp, phase5hp FROM ravistate WHERE refid = 29")
var phase1HP, phase2HP, phase3HP, phase4HP, phase5HP uint32
hperr := hprow.Scan(&phase1HP, &phase2HP, &phase3HP, &phase4HP, &phase5HP)
if hperr != nil {
panic(hperr)
return
}
row := s.server.db.QueryRow("SELECT support2 FROM ravisupport WHERE refid = 25")
var berserkTranq uint32
err := row.Scan(&berserkTranq)
if err != nil {
panic(err)
return
}
sendServerChatMessage(s, fmt.Sprintf("Requesting sedation support"))
s.server.db.Exec("UPDATE ravisupport SET support2 = $1", ((phase1HP + phase2HP + phase3HP + phase4HP + phase5HP) + 12))
}
if strings.HasPrefix(chatMessage.Message, "!setmultiplier ") {
var num uint8
n, numerr := fmt.Sscanf(chatMessage.Message, "!setmultiplier %d", &num)
row := s.server.db.QueryRow("SELECT damagemultiplier FROM ravistate WHERE refid = 29")
var damageMultiplier uint32
err := row.Scan(&damageMultiplier)
if err != nil {
panic(err)
return
sendServerChatMessage(s, "The Great Slaying has already begun!")
}
} else if strings.HasPrefix(chatMessage.Message, "!ravi sm") || strings.HasPrefix(chatMessage.Message, "!ravi setmultiplier") {
var num uint16
n, numerr := fmt.Sscanf(chatMessage.Message, "!ravi sm %d", &num)
if numerr != nil || n != 1 {
sendServerChatMessage(s, fmt.Sprintf("Please use the format !setmultiplier x"))
} else if damageMultiplier == 1 {
if num > 20 {
sendServerChatMessage(s, fmt.Sprintf("Max multiplier for Ravi is 20, setting to this value"))
s.server.db.Exec("UPDATE ravistate SET damagemultiplier = $1", 20)
sendServerChatMessage(s, "Error in command. Format: !ravi sm n")
} else if s.server.raviente.state.damageMultiplier == 1 {
if num > 65535 {
sendServerChatMessage(s, "Raviente multiplier too high, defaulting to 20x")
s.server.raviente.state.damageMultiplier = 65535
} else {
sendServerChatMessage(s, fmt.Sprintf("Setting Ravi damage multiplier to %d", num))
s.server.db.Exec("UPDATE ravistate SET damagemultiplier = $1", num)
sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier set to %dx", num))
s.server.raviente.state.damageMultiplier = uint32(num)
}
} else {
sendServerChatMessage(s, fmt.Sprintf("Multiplier can only be set once, please restart Ravi to set again"))
sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is already set to %dx!", s.server.raviente.state.damageMultiplier))
}
} else if strings.HasPrefix(chatMessage.Message, "!ravi cm") || strings.HasPrefix(chatMessage.Message, "!ravi checkmultiplier") {
sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is currently %dx", s.server.raviente.state.damageMultiplier))
} else if strings.HasPrefix(chatMessage.Message, "!ravi sr") || strings.HasPrefix(chatMessage.Message, "!ravi sendres") {
if s.server.raviente.state.stateData[28] > 0 {
sendServerChatMessage(s, "Sending resurrection support!")
s.server.raviente.state.stateData[28] = 0
} else {
sendServerChatMessage(s, "Resurrection support has not been requested!")
}
} else if strings.HasPrefix(chatMessage.Message, "!ravi ss") || strings.HasPrefix(chatMessage.Message, "!ravi sendsed") {
sendServerChatMessage(s, "Sending sedation support if requested!")
// 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
} else if strings.HasPrefix(chatMessage.Message, "!ravi rs") || strings.HasPrefix(chatMessage.Message, "!ravi reqsed") {
sendServerChatMessage(s, "Requesting sedation support!")
// 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
} else {
sendServerChatMessage(s, "Raviente command not recognised!")
}
}
if strings.HasPrefix(chatMessage.Message, "!checkmultiplier") {
var damageMultiplier uint32
row := s.server.db.QueryRow("SELECT damagemultiplier FROM ravistate WHERE refid = 29").Scan(&damageMultiplier)
if row != nil {
return
} else {
sendServerChatMessage(s, "No one has joined the Great Slaying!")
}
sendServerChatMessage(s, fmt.Sprintf("Ravi's current damage multiplier is %d", damageMultiplier))
s.server.raviente.Unlock()
}
}
}
// END OF RAVI COMMANDS
// END RAVI COMMANDS V2
if strings.HasPrefix(chatMessage.Message, "!tele ") {
var x, y int16

View File

@@ -128,16 +128,5 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSexChanger)
if pkt.Gender == 0 {
_, err := s.server.db.Exec("UPDATE characters SET is_female=true WHERE id=$1", s.charID)
if err != nil {
s.logger.Fatal("Failed to update gender in db", zap.Error(err))
}
} else {
_, err := s.server.db.Exec("UPDATE characters SET is_female=false WHERE id=$1", s.charID)
if err != nil {
s.logger.Fatal("Failed to update gender in db", zap.Error(err))
}
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}

View File

@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"github.com/Andoryuuta/byteframe"
"github.com/Solenataris/Erupe/common/bfutil"
"github.com/Solenataris/Erupe/network/mhfpacket"
"github.com/Solenataris/Erupe/server/channelserver/compression/deltacomp"
@@ -32,17 +33,16 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
s.logger.Fatal("Failed to decompress diff", zap.Error(err))
}
// Perform diff.
characterSaveData.SetBaseSaveData(deltacomp.ApplyDataDiff(diff, characterSaveData.BaseSaveData()))
s.logger.Info("Diffing...")
characterSaveData.SetBaseSaveData(deltacomp.ApplyDataDiff(diff, characterSaveData.BaseSaveData()))
} else {
// Regular blob update.
saveData, err := nullcomp.Decompress(pkt.RawDataPayload)
characterSaveData.SetBaseSaveData(saveData)
if err != nil {
s.logger.Fatal("Failed to decompress savedata from packet", zap.Error(err))
}
s.logger.Info("Updating save with blob")
characterSaveData.SetBaseSaveData(saveData)
}
characterSaveData.IsNewCharacter = false
characterBaseSaveData := characterSaveData.BaseSaveData()
@@ -193,7 +193,10 @@ func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSaveScenarioData)
_, err := s.server.db.Exec("UPDATE characters SET scenariodata = $1 WHERE characters.id = $2", pkt.RawDataPayload, int(s.charID))
if err != nil {
s.logger.Fatal("Failed to update scenario data in db", zap.Error(err))
}
// Do this ack manually because it uses a non-(0|1) error code
s.QueueSendMHF(&mhfpacket.MsgSysAck{
AckHandle: pkt.AckHandle,
@@ -205,7 +208,19 @@ func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfLoadScenarioData)
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
var scenarioData []byte
bf := byteframe.NewByteFrame()
err := s.server.db.QueryRow("SELECT scenariodata FROM characters WHERE characters.id = $1", int(s.charID)).Scan(&scenarioData)
if err != nil {
s.logger.Fatal("Failed to get scenario data contents in db", zap.Error(err))
} else {
if len(scenarioData) == 0 {
bf.WriteUint32(0x00)
} else {
bf.WriteBytes(scenarioData)
}
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {

View File

@@ -26,7 +26,6 @@ type ItemDist struct {
func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateDistItem)
bf := byteframe.NewByteFrame()
distCount := 0
dists, err := s.server.db.Queryx(`
SELECT d.id, event_name, description, times_acceptable,
@@ -55,7 +54,6 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
if err != nil {
s.logger.Error("Error parsing item distribution data", zap.Error(err))
}
bf.WriteUint32(distData.ID)
bf.WriteUint32(distData.Deadline)
bf.WriteUint32(0) // Unk
@@ -119,18 +117,15 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfGetDistDescription(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetDistDescription)
var itemDesc string
err := s.server.db.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&itemDesc)
var desc string
err := s.server.db.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&desc)
if err != nil {
s.logger.Error("Error parsing item distribution description", zap.Error(err))
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
bf := byteframe.NewByteFrame()
description, _ := stringsupport.ConvertUTF8ToShiftJIS(itemDesc)
description, _ := stringsupport.ConvertUTF8ToShiftJIS(desc)
bf.WriteUint16(uint16(len(description)+1))
bf.WriteNullTerminatedBytes(description)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())

View File

@@ -4,7 +4,6 @@ import (
"database/sql"
"time"
"github.com/Solenataris/Erupe/common/stringsupport"
"github.com/Solenataris/Erupe/network/binpacket"
"github.com/Solenataris/Erupe/network/mhfpacket"
"github.com/Andoryuuta/byteframe"
@@ -19,9 +18,10 @@ type Mail struct {
Body string `db:"body"`
Read bool `db:"read"`
Deleted bool `db:"deleted"`
Locked bool `db:"locked"`
AttachedItemReceived bool `db:"attached_item_received"`
AttachedItemID *uint16 `db:"attached_item"`
AttachedItemAmount int16 `db:"attached_item_amount"`
AttachedItemID uint16 `db:"attached_item"`
AttachedItemAmount uint16 `db:"attached_item_amount"`
CreatedAt time.Time `db:"created_at"`
IsGuildInvite bool `db:"is_guild_invite"`
SenderName string `db:"sender_name"`
@@ -49,8 +49,8 @@ func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
zap.Uint32("recipientID", m.RecipientID),
zap.String("subject", m.Subject),
zap.String("body", m.Body),
zap.Uint16p("itemID", m.AttachedItemID),
zap.Int16("itemAmount", m.AttachedItemAmount),
zap.Uint16("itemID", m.AttachedItemID),
zap.Uint16("itemAmount", m.AttachedItemAmount),
zap.Bool("isGuildInvite", m.IsGuildInvite),
)
return err
@@ -110,6 +110,23 @@ func (m *Mail) MarkAcquired(s *Session) error {
return nil
}
func (m *Mail) MarkLocked(s *Session, locked bool) error {
_, err := s.server.db.Exec(`
UPDATE mail SET locked = $1 WHERE id = $2
`, locked, m.ID)
if err != nil {
s.logger.Error(
"failed to mark mail as locked",
zap.Error(err),
zap.Int("mailID", m.ID),
)
return err
}
return nil
}
func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
rows, err := s.server.db.Queryx(`
SELECT
@@ -124,6 +141,7 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
m.created_at,
m.is_guild_invite,
m.deleted,
m.locked,
c.name as sender_name
FROM mail m
JOIN characters c ON c.id = m.sender_id
@@ -171,6 +189,7 @@ func GetMailByID(s *Session, ID int) (*Mail, error) {
m.created_at,
m.is_guild_invite,
m.deleted,
m.locked,
c.name as sender_name
FROM mail m
JOIN characters c ON c.id = m.sender_id
@@ -255,8 +274,9 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
_ = mail.MarkRead(s)
bf := byteframe.NewByteFrame()
bodyBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(mail.Body)
bf.WriteNullTerminatedBytes(bodyBytes)
body := s.clientContext.StrConv.MustEncode(mail.Body)
bf.WriteNullTerminatedBytes(body)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
@@ -286,9 +306,10 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
s.mailList[accIndex] = m.ID
s.mailAccIndex++
itemAttached := m.AttachedItemID != nil
subjectBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.Subject)
senderNameBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.SenderName)
itemAttached := m.AttachedItemID != 0
subject := s.clientContext.StrConv.MustEncode(m.Subject)
sender := s.clientContext.StrConv.MustEncode(m.SenderName)
msg.WriteUint32(m.SenderID)
msg.WriteUint32(uint32(m.CreatedAt.Unix()))
@@ -302,28 +323,34 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
flags |= 0x01
}
if m.AttachedItemReceived {
if m.Locked {
flags |= 0x02
}
// System message, hides ID
// flags |= 0x04
// Mitigate game crash
flags |= 0x08
if m.AttachedItemReceived {
// flags |= 0x08
}
if m.IsGuildInvite {
// Guild Invite
flags |= 0x10
// System message?
flags |= 0x04
}
msg.WriteUint8(flags)
msg.WriteBool(itemAttached)
msg.WriteUint8(uint8(len(subjectBytes)+1))
msg.WriteUint8(uint8(len(senderNameBytes)+1))
msg.WriteNullTerminatedBytes(subjectBytes)
msg.WriteNullTerminatedBytes(senderNameBytes)
msg.WriteUint8(uint8(len(subject)+1))
msg.WriteUint8(uint8(len(sender)+1))
msg.WriteNullTerminatedBytes(subject)
msg.WriteNullTerminatedBytes(sender)
// TODO: The game will crash if it attempts to receive items
if itemAttached {
msg.WriteInt16(m.AttachedItemAmount)
msg.WriteUint16(*m.AttachedItemID)
msg.WriteUint16(m.AttachedItemAmount)
msg.WriteUint16(m.AttachedItemID)
}
}
@@ -347,6 +374,18 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err)
}
case mhfpacket.OPERATE_MAIL_LOCK:
err = mail.MarkLocked(s, true)
if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err)
}
case mhfpacket.OPERATE_MAIL_UNLOCK:
err = mail.MarkLocked(s, false)
if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err)
}
case mhfpacket.OPERATE_MAIL_ACQUIRE_ITEM:
err = mail.MarkAcquired(s)
if err != nil {

File diff suppressed because it is too large Load Diff

View File

@@ -2,10 +2,22 @@ package channelserver
import (
"fmt"
"strings"
"github.com/Solenataris/Erupe/network/mhfpacket"
)
func removeSessionFromSemaphore(s *Session) {
s.server.semaphoreLock.Lock()
for _, semaphore := range s.server.semaphore {
if _, exists := semaphore.clients[s]; exists {
delete(semaphore.clients, s)
}
}
releaseRaviSemaphore(s)
s.server.semaphoreLock.Unlock()
}
func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysCreateSemaphore)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
@@ -22,18 +34,40 @@ func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k3" {
delete(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots, s.charID)
delete(s.server.semaphore["hs_l0u3B51J9k3"].clients, s)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k3" {
delete(s.server.semaphore["hs_l0u3B5129k3"].reservedClientSlots, s.charID)
delete(s.server.semaphore["hs_l0u3B5129k3"].clients, s)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak3" {
delete(s.server.semaphore["hs_l0u3B512Ak3"].reservedClientSlots, s.charID)
delete(s.server.semaphore["hs_l0u3B512Ak3"].clients, s)
}
case 851997:
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k4" {
delete(s.server.semaphore["hs_l0u3B51J9k4"].reservedClientSlots, s.charID)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k4" {
delete(s.server.semaphore["hs_l0u3B5129k4"].reservedClientSlots, s.charID)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak4" {
delete(s.server.semaphore["hs_l0u3B512Ak4"].reservedClientSlots, s.charID)
}
case 786461:
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k5" {
delete(s.server.semaphore["hs_l0u3B51J9k5"].reservedClientSlots, s.charID)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k5" {
delete(s.server.semaphore["hs_l0u3B5129k5"].reservedClientSlots, s.charID)
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak5" {
delete(s.server.semaphore["hs_l0u3B512Ak5"].reservedClientSlots, s.charID)
}
default:
if len(s.server.semaphore[id].reservedClientSlots) != 0 {
if s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k3" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k4" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k5" {
if s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k3" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k4" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k5" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k3" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k4" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k5" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak3" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak4" &&
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak5" {
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
}
}
@@ -52,11 +86,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID)
if !gotNewStage {
s.server.semaphoreLock.Lock()
if SemaphoreID == "hs_l0u3B51J9k1" ||
SemaphoreID == "hs_l0u3B51J9k2" ||
SemaphoreID == "hs_l0u3B51J9k3" ||
SemaphoreID == "hs_l0u3B51J9k4" ||
SemaphoreID == "hs_l0u3B51J9k5" {
if strings.HasPrefix(SemaphoreID, "hs_l0u3B51") {
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 32)
} else {
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 1)
@@ -68,24 +98,23 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
newSemaphore.Lock()
defer newSemaphore.Unlock()
if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists {
s.logger.Info("IS ALREADY EXIST !")
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
switch SemaphoreID {
case "hs_l0u3B51J9k3":
case "hs_l0u3B51J9k3", "hs_l0u3B5129k3", "hs_l0u3B512Ak3":
newSemaphore.reservedClientSlots[s.charID] = nil
newSemaphore.clients[s] = s.charID
s.Lock()
s.semaphore = newSemaphore
s.Unlock()
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0E, 0x00, 0x1D})
case "hs_l0u3B51J9k4":
case "hs_l0u3B51J9k4", "hs_l0u3B5129k4", "hs_l0u3B512Ak4":
newSemaphore.reservedClientSlots[s.charID] = nil
s.Lock()
s.semaphore = newSemaphore
s.Unlock()
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0D, 0x00, 0x1D})
case "hs_l0u3B51J9k5":
case "hs_l0u3B51J9k5", "hs_l0u3B5129k5", "hs_l0u3B512Ak5":
newSemaphore.reservedClientSlots[s.charID] = nil
s.Lock()
s.semaphore = newSemaphore
@@ -109,29 +138,16 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
//pkt := p.(*mhfpacket.MsgSysReleaseSemaphore)
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
reset := len(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots)
if reset == 0 {
s.server.db.Exec("CALL ravireset($1)", 0)
}
}
}
func removeSessionFromSemaphore(s *Session) {
s.server.semaphoreLock.Lock()
for id := range s.server.semaphore {
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
if id == "hs_l0u3B51J9k3" {
delete(s.server.semaphore[id].clients, s)
} else {
continue
}
}
s.server.semaphoreLock.Unlock()
releaseRaviSemaphore(s)
}
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysCheckSemaphore)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
resp := []byte{0x00, 0x00, 0x00, 0x00}
s.server.semaphoreLock.Lock()
if _, exists := s.server.semaphore[pkt.StageID]; exists {
resp = []byte{0x00, 0x00, 0x00, 0x01}
}
s.server.semaphoreLock.Unlock()
doAckSimpleSucceed(s, pkt.AckHandle, resp)
}

View File

@@ -3,6 +3,7 @@ package channelserver
import (
"fmt"
"time"
"strings"
"github.com/Solenataris/Erupe/network/mhfpacket"
"github.com/Andoryuuta/byteframe"
@@ -11,13 +12,16 @@ import (
func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysCreateStage)
s.server.stagesLock.Lock()
s.server.Lock()
defer s.server.Unlock()
if _, exists := s.server.stages[pkt.StageID]; exists {
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} else {
stage := NewStage(pkt.StageID)
stage.maxPlayers = uint16(pkt.PlayerCount)
s.server.stages[stage.id] = stage
s.server.stagesLock.Unlock()
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}
}
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
@@ -64,30 +68,31 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
// Notify existing stage clients that this new client has entered.
s.logger.Info("Sending MsgSysInsertUser")
if s.stage != nil { // avoids lock up when using bed for dream quests
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
// Add character to everyone elses stage
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser {
CharID: s.charID,
}, s)
// It seems to be acceptable to recast all MSG_SYS_SET_USER_BINARY messages so far,
// players are still notified when a new player has joined the stage.
// These extra messages may not be needed
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
// CharID: s.charID,
// BinaryType: 1,
//}, s)
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
// CharID: s.charID,
// BinaryType: 2,
//}, s)
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
// CharID: s.charID,
// BinaryType: 3,
//}, s)
// Update others binary of your session
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
CharID: s.charID,
BinaryType: 1,
}, s)
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
CharID: s.charID,
BinaryType: 2,
}, s)
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
CharID: s.charID,
BinaryType: 3,
}, s)
//Notify the entree client about all of the existing clients in the stage.
// Notify the entree client about all of the existing clients in the stage.
s.logger.Info("Notifying entree about existing stage clients")
s.stage.RLock()
clientNotif := byteframe.NewByteFrame()
// Get other players in the stage
for session := range s.stage.clients {
var cur mhfpacket.MHFPacket
cur = &mhfpacket.MsgSysInsertUser{
@@ -95,6 +100,12 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
}
clientNotif.WriteUint16(uint16(cur.Opcode()))
cur.Build(clientNotif, session.clientContext)
}
// Get every players binary
for session := range s.server.sessions {
var cur mhfpacket.MHFPacket
session := s.server.sessions[session]
cur = &mhfpacket.MsgSysNotifyUserBinary{
CharID: session.charID,
@@ -143,6 +154,18 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
}
}
func removeEmptyStages(s *Session) {
s.server.Lock()
for sid, stage := range s.server.stages {
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
if strings.HasPrefix(sid, "sl1Qs") || strings.HasPrefix(sid, "sl2Qs") || strings.HasPrefix(sid, "sl3Qs") {
delete(s.server.stages, sid)
}
}
}
s.server.Unlock()
}
func removeSessionFromStage(s *Session) {
s.stage.Lock()
defer s.stage.Unlock()
@@ -151,6 +174,15 @@ func removeSessionFromStage(s *Session) {
delete(s.stage.clients, s)
delete(s.stage.reservedClientSlots, s.charID)
// Remove client from all reservations
s.server.Lock()
for _, stage := range s.server.stages {
if _, exists := stage.reservedClientSlots[s.charID]; exists {
delete(stage.reservedClientSlots, s.charID)
}
}
s.server.Unlock()
// Delete old stage objects owned by the client.
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
for objID, stageObject := range s.stage.objects {
@@ -163,7 +195,7 @@ func removeSessionFromStage(s *Session) {
// Actually delete it form the objects map.
delete(s.stage.objects, objID)
}
}
}
for objListID, stageObjectList := range s.stage.objectList {
if stageObjectList.charid == s.charID {
//Added to prevent duplicates from flooding ObjectMap and causing server hangs
@@ -171,6 +203,8 @@ func removeSessionFromStage(s *Session) {
s.stage.objectList[objListID].charid=0
}
}
removeEmptyStages(s)
}
@@ -252,7 +286,9 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
s.server.stagesLock.Unlock()
if !gotStage {
s.logger.Fatal("Failed to get stage", zap.String("StageID", stageID))
s.logger.Error("Failed to get stage", zap.String("StageID", stageID))
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
return
}
// Try to reserve a slot, fail if full.
@@ -427,15 +463,17 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
// Build the response
resp := byteframe.NewByteFrame()
resp.WriteUint16(uint16(len(s.server.stages)))
bf := byteframe.NewByteFrame()
var joinable int
for sid, stage := range s.server.stages {
stage.RLock()
defer stage.RUnlock()
if len(stage.reservedClientSlots)+len(stage.clients) == 0 {
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
continue
}
joinable++
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Current players.
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Reserved players.
resp.WriteUint16(0) // Unknown value
var hasDeparted uint16
@@ -448,6 +486,8 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
resp.WriteUint8(uint8(len(sid)))
resp.WriteBytes([]byte(sid))
}
bf.WriteUint16(uint16(joinable))
bf.WriteBytes(resp.Data())
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -248,10 +248,15 @@ function switchPrompt() {
}
} catch (e) {
addLog('Error parsing character info XML: '+e, 'error');
switchPrompt();
return;
}
let uid = localStorage.getItem('uid');
if (uid != 'null' && uids.indexOf(uid) >= 0) {
setUidIndex(uids.indexOf(uid));
} else {
addLog('Error setting character ID: '+e, 'error');
switchPrompt();
}
}
}