diff --git a/server/channelserver/handlers_house.go b/server/channelserver/handlers_house.go index ec6a75ec6..eea1467c0 100644 --- a/server/channelserver/handlers_house.go +++ b/server/channelserver/handlers_house.go @@ -4,6 +4,7 @@ import ( "erupe-ce/common/byteframe" ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" + _config "erupe-ce/config" "erupe-ce/network/mhfpacket" "fmt" "go.uber.org/zap" @@ -256,6 +257,9 @@ func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) { s.logger.Error("Failed to load decomyset", zap.Error(err)) } if len(data) == 0 { + if s.server.erupeConfig.RealClientMode <= _config.G7 { + data = []byte{0x00, 0x00} + } data = []byte{0x01, 0x00} } // Validate and fix corrupted data with more than maxDecoMysets presets diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index ee45ba0a2..7e9305434 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -4,59 +4,49 @@ import ( "erupe-ce/common/byteframe" ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" - _config "erupe-ce/config" + "erupe-ce/common/token" "erupe-ce/server/channelserver" "fmt" - "strings" - "time" - "go.uber.org/zap" + "strings" ) -func (s *Session) makeSignResponse(uid uint32) []byte { +func makeSignInFailureResp(respID RespID) []byte { + bf := byteframe.NewByteFrame() + bf.WriteUint8(uint8(respID)) + return bf.Data() +} + +func (s *Session) makeSignInResp(uid int) []byte { + returnExpiry := s.server.getReturnExpiry(uid) + // Get the characters from the DB. chars, err := s.server.getCharactersForUser(uid) - if len(chars) == 0 && uid != 0 { - err = s.server.newUserChara(uid) - if err == nil { - chars, err = s.server.getCharactersForUser(uid) - } - } if err != nil { s.logger.Warn("Error getting characters from DB", zap.Error(err)) } + sessToken := token.Generate(16) + s.server.registerToken(uid, sessToken) + bf := byteframe.NewByteFrame() - var tokenID uint32 - var sessToken string - if uid == 0 && s.psn != "" { - tokenID, sessToken, err = s.server.registerPsnToken(s.psn) + + bf.WriteUint8(1) // resp_code + if s.server.erupeConfig.DevMode && s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" { + bf.WriteUint8(2) } else { - tokenID, sessToken, err = s.server.registerUidToken(uid) + bf.WriteUint8(0) } - if err != nil { - bf.WriteUint8(uint8(SIGN_EABORT)) - return bf.Data() - } - - if s.client == PS3 && (s.server.erupeConfig.PatchServerFile == "" || s.server.erupeConfig.PatchServerManifest == "") { - bf.WriteUint8(uint8(SIGN_EABORT)) - return bf.Data() - } - - bf.WriteUint8(uint8(SIGN_SUCCESS)) - bf.WriteUint8(2) // patch server count bf.WriteUint8(1) // entrance server count bf.WriteUint8(uint8(len(chars))) - bf.WriteUint32(tokenID) + bf.WriteUint32(0xFFFFFFFF) // login_token_number bf.WriteBytes([]byte(sessToken)) bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix())) - if s.client == PS3 { - ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerManifest), false) - ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerFile), false) - } else { - ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false) - ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false) + if s.server.erupeConfig.DevMode { + if s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" { + ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false) + ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false) + } } if strings.Split(s.rawConn.RemoteAddr().String(), ":")[0] == "127.0.0.1" { ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", s.server.erupeConfig.Entrance.Port), false) @@ -70,11 +60,14 @@ func (s *Session) makeSignResponse(uid uint32) []byte { lastPlayed = char.ID } bf.WriteUint32(char.ID) - if s.server.erupeConfig.DebugOptions.MaxLauncherHR { + + // Exp, HR[x] is split by 0, 1, 30, 50, 99, 299, 998, 999 + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.MaxLauncherHR { bf.WriteUint16(999) } else { - bf.WriteUint16(char.HR) + bf.WriteUint16(char.HRP) } + bf.WriteUint16(char.WeaponType) // Weapon, 0-13. bf.WriteUint32(char.LastLogin) // Last login date, unix timestamp in seconds. bf.WriteBool(char.IsFemale) // Sex, 0=male, 1=female. @@ -83,23 +76,15 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteBool(true) // Use uint16 GR, no reason not to bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str - if s.server.erupeConfig.RealClientMode >= _config.G7 { - bf.WriteUint16(char.GR) - bf.WriteUint8(0) // Unk - bf.WriteUint8(0) // Unk - } + bf.WriteUint16(char.GR) + bf.WriteUint16(0) // Unk } friends := s.server.getFriendsForCharacters(chars) if len(friends) == 0 { bf.WriteUint8(0) } else { - if len(friends) > 255 { - bf.WriteUint8(255) - bf.WriteUint16(uint16(len(friends))) - } else { - bf.WriteUint8(uint8(len(friends))) - } + bf.WriteUint8(uint8(len(friends))) for _, friend := range friends { bf.WriteUint32(friend.CID) bf.WriteUint32(friend.ID) @@ -111,12 +96,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte { if len(guildmates) == 0 { bf.WriteUint8(0) } else { - if len(guildmates) > 255 { - bf.WriteUint8(255) - bf.WriteUint16(uint16(len(guildmates))) - } else { - bf.WriteUint8(uint8(len(guildmates))) - } + bf.WriteUint8(uint8(len(guildmates))) for _, guildmate := range guildmates { bf.WriteUint32(guildmate.CID) bf.WriteUint32(guildmate.ID) @@ -125,278 +105,55 @@ func (s *Session) makeSignResponse(uid uint32) []byte { } if s.server.erupeConfig.HideLoginNotice { - bf.WriteBool(false) + bf.WriteUint8(0) } else { - bf.WriteBool(true) - bf.WriteUint8(0) - bf.WriteUint8(0) - ps.Uint16(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], ""), true) + bf.WriteUint8(uint8(len(s.server.erupeConfig.LoginNotices))) + for _, notice := range s.server.erupeConfig.LoginNotices { + ps.Uint32(bf, notice, true) + } } bf.WriteUint32(s.server.getLastCID(uid)) bf.WriteUint32(s.server.getUserRights(uid)) + ps.Uint16(bf, "", false) // filters + bf.WriteUint16(0xCA10) + bf.WriteUint16(0x4E20) + ps.Uint16(bf, "", false) // unk key + bf.WriteUint8(0x00) + bf.WriteUint16(0xCA11) + bf.WriteUint16(0x0001) + bf.WriteUint16(0x4E20) + ps.Uint16(bf, "", false) // unk ipv4 + bf.WriteUint32(uint32(returnExpiry.Unix())) + bf.WriteUint32(0x00000000) + bf.WriteUint32(0x0A5197DF) // unk id - namNGWords := []string{} - msgNGWords := []string{} - - filters := byteframe.NewByteFrame() - filters.SetLE() - filters.WriteNullTerminatedBytes([]byte("smc")) - smc := byteframe.NewByteFrame() - smc.SetLE() - smcData := []struct { - charGroup [][]rune - }{ - {[][]rune{{'='}, {'='}}}, - {[][]rune{{')'}, {')'}}}, - {[][]rune{{'('}, {'('}}}, - {[][]rune{{'!'}, {'!'}}}, - {[][]rune{{'/'}, {'/'}}}, - {[][]rune{{'+'}, {'+'}}}, - {[][]rune{{'&'}, {'&'}}}, - {[][]rune{{'ぼ'}, {'ボ'}, {'ホ', '゙'}, {'ほ', '゙'}, {'ホ', '゙'}, {'ほ', '゛'}, {'ホ', '゛'}, {'ホ', '゛'}}}, - {[][]rune{{'べ'}, {'ベ'}, {'ヘ', '゙'}, {'へ', '゙'}, {'ヘ', '゙'}, {'へ', '゛'}, {'ヘ', '゛'}, {'ヘ', '゛'}}}, - {[][]rune{{'で'}, {'デ'}, {'テ', '゙'}, {'て', '゙'}, {'テ', '゙'}, {'て', '゛'}, {'テ', '゛'}, {'テ', '゛'}, {'〒', '゛'}, {'〒', '゙'}, {'乙', '゙'}, {'乙', '゛'}}}, - {[][]rune{{'び'}, {'ビ'}, {'ヒ', '゙'}, {'ひ', '゙'}, {'ヒ', '゙'}, {'ひ', '゛'}, {'ヒ', '゛'}, {'ヒ', '゛'}}}, - {[][]rune{{'ど'}, {'ド'}, {'ト', '゙'}, {'と', '゙'}, {'ト', '゙'}, {'と', '゛'}, {'ト', '゛'}, {'ト', '゛'}, {'┣', '゙'}, {'┣', '゛'}, {'├', '゙'}, {'├', '゛'}}}, - {[][]rune{{'ば'}, {'バ'}, {'ハ', '゙'}, {'は', '゙'}, {'ハ', '゙'}, {'八', '゙'}, {'は', '゛'}, {'ハ', '゛'}, {'ハ', '゛'}, {'八', '゛'}}}, - {[][]rune{{'つ', '゙'}, {'ヅ'}, {'ツ', '゙'}, {'つ', '゛'}, {'ツ', '゛'}, {'ツ', '゙'}, {'ツ', '゛'}, {'づ'}, {'っ', '゙'}, {'ッ', '゙'}, {'ッ', '゙'}, {'っ', '゛'}, {'ッ', '゛'}, {'ッ', '゛'}}}, - {[][]rune{{'ぶ'}, {'ブ'}, {'フ', '゙'}, {'ヴ'}, {'ウ', '゙'}, {'う', '゛'}, {'う', '゙'}, {'ウ', '゙'}, {'ゥ', '゙'}, {'ぅ', '゙'}, {'ふ', '゙'}, {'フ', '゙'}, {'フ', '゛'}}}, - {[][]rune{{'ぢ'}, {'ヂ'}, {'チ', '゙'}, {'ち', '゙'}, {'チ', '゙'}, {'ち', '゛'}, {'チ', '゛'}, {'チ', '゛'}, {'千', '゛'}, {'千', '゙'}}}, - {[][]rune{{'だ'}, {'ダ'}, {'タ', '゙'}, {'た', '゙'}, {'タ', '゙'}, {'夕', '゙'}, {'た', '゛'}, {'タ', '゛'}, {'タ', '゛'}, {'夕', '゛'}}}, - {[][]rune{{'ぞ'}, {'ゾ'}, {'ソ', '゙'}, {'そ', '゙'}, {'ソ', '゙'}, {'そ', '゛'}, {'ソ', '゛'}, {'ソ', '゛'}, {'ン', '゙'}, {'ン', '゛'}, {'ン', '゛'}, {'ン', '゙'}, {'リ', '゙'}, {'リ', '゙'}, {'リ', '゛'}, {'リ', '゛'}}}, - {[][]rune{{'ぜ'}, {'セ', '゙'}, {'せ', '゙'}, {'セ', '゙'}, {'せ', '゛'}, {'セ', '゛'}, {'セ', '゛'}, {'ゼ'}}}, - {[][]rune{{'ず'}, {'ズ'}, {'ス', '゙'}, {'す', '゙'}, {'ス', '゙'}, {'す', '゛'}, {'ス', '゛'}, {'ス', '゛'}}}, - {[][]rune{{'じ'}, {'ジ'}, {'シ', '゙'}, {'し', '゙'}, {'シ', '゙'}, {'し', '゛'}, {'シ', '゛'}, {'シ', '゛'}}}, - {[][]rune{{'ざ'}, {'ザ'}, {'サ', '゙'}, {'さ', '゙'}, {'サ', '゙'}, {'さ', '゛'}, {'サ', '゛'}, {'サ', '゛'}}}, - {[][]rune{{'ご'}, {'ゴ'}, {'コ', '゙'}, {'こ', '゙'}, {'コ', '゙'}, {'こ', '゛'}, {'コ', '゛'}, {'コ', '゛'}}}, - {[][]rune{{'げ'}, {'ゲ'}, {'ケ', '゙'}, {'け', '゙'}, {'ケ', '゙'}, {'け', '゛'}, {'ケ', '゛'}, {'ケ', '゛'}, {'ヶ', '゙'}, {'ヶ', '゛'}}}, - {[][]rune{{'ぐ'}, {'グ'}, {'ク', '゙'}, {'く', '゙'}, {'ク', '゙'}, {'く', '゛'}, {'ク', '゛'}, {'ク', '゛'}}}, - {[][]rune{{'ぎ'}, {'ギ'}, {'キ', '゙'}, {'き', '゙'}, {'キ', '゙'}, {'き', '゛'}, {'キ', '゛'}, {'キ', '゛'}}}, - {[][]rune{{'が'}, {'ガ'}, {'カ', '゙'}, {'ヵ', '゙'}, {'カ', '゙'}, {'か', '゙'}, {'力', '゙'}, {'ヵ', '゛'}, {'カ', '゛'}, {'か', '゛'}, {'力', '゛'}, {'カ', '゛'}}}, - {[][]rune{{'を'}, {'ヲ'}, {'ヲ'}}}, - {[][]rune{{'わ'}, {'ワ'}, {'ワ'}, {'ヮ'}}}, - {[][]rune{{'ろ'}, {'ロ'}, {'ロ'}, {'□'}, {'口'}}}, - {[][]rune{{'れ'}, {'レ'}, {'レ'}}}, - {[][]rune{{'る'}, {'ル'}, {'ル'}}}, - {[][]rune{{'り'}, {'リ'}, {'リ'}}}, - {[][]rune{{'ら'}, {'ラ'}, {'ラ'}}}, - {[][]rune{{'よ'}, {'ヨ'}, {'ヨ'}, {'ョ'}, {'ょ'}, {'ョ'}}}, - {[][]rune{{'ゆ'}, {'ユ'}, {'ユ'}, {'ュ'}, {'ゅ'}, {'ュ'}}}, - {[][]rune{{'や'}, {'ヤ'}, {'ヤ'}, {'ャ'}, {'ゃ'}, {'ャ'}}}, - {[][]rune{{'も'}, {'モ'}, {'モ'}}}, - {[][]rune{{'め'}, {'メ'}, {'メ'}, {'M', 'E'}}}, - {[][]rune{{'む'}, {'ム'}, {'ム'}}}, - {[][]rune{{'み'}, {'ミ'}, {'ミ'}}}, - {[][]rune{{'ま'}, {'マ'}, {'マ'}}}, - {[][]rune{{'ほ'}, {'ホ'}, {'ホ'}}}, - {[][]rune{{'へ'}, {'ヘ'}, {'ヘ'}}}, - {[][]rune{{'ふ'}, {'フ'}, {'フ'}}}, - {[][]rune{{'ひ'}, {'ヒ'}, {'ヒ'}}}, - {[][]rune{{'は'}, {'ハ'}, {'ハ'}, {'八'}}}, - {[][]rune{{'の'}, {'ノ'}, {'ノ'}}}, - {[][]rune{{'ね'}, {'ネ'}, {'ネ'}}}, - {[][]rune{{'ぬ'}, {'ヌ'}, {'ヌ'}}}, - {[][]rune{{'に'}, {'ニ'}, {'ニ'}, {'二'}}}, - {[][]rune{{'な'}, {'ナ'}, {'ナ'}}}, - {[][]rune{{'と'}, {'ト'}, {'ト'}, {'┣'}, {'├'}}}, - {[][]rune{{'て'}, {'テ'}, {'テ'}, {'〒'}, {'乙'}}}, - {[][]rune{{'つ'}, {'ツ'}, {'ツ'}, {'っ'}, {'ッ'}, {'ッ'}}}, - {[][]rune{{'ち'}, {'チ'}, {'チ'}, {'千'}}}, - {[][]rune{{'た'}, {'タ'}, {'タ'}, {'夕'}}}, - {[][]rune{{'そ'}, {'ソ'}, {'ソ'}}}, - {[][]rune{{'せ'}, {'セ'}, {'セ'}}}, - {[][]rune{{'す'}, {'ス'}, {'ス'}}}, - {[][]rune{{'し'}, {'シ'}, {'シ'}}}, - {[][]rune{{'さ'}, {'サ'}, {'サ'}}}, - {[][]rune{{'こ'}, {'コ'}, {'コ'}}}, - {[][]rune{{'け'}, {'ケ'}, {'ケ'}, {'ヶ'}}}, - {[][]rune{{'く'}, {'ク'}, {'ク'}}}, - {[][]rune{{'き'}, {'キ'}, {'キ'}}}, - {[][]rune{{'か'}, {'カ'}, {'カ'}, {'ヵ'}, {'力'}}}, - {[][]rune{{'お'}, {'オ'}, {'オ'}, {'ォ'}, {'ぉ'}, {'ォ'}}}, - {[][]rune{{'え'}, {'エ'}, {'エ'}, {'ェ'}, {'ぇ'}, {'ェ'}, {'工'}}}, - {[][]rune{{'う'}, {'ウ'}, {'ウ'}, {'ゥ'}, {'ぅ'}, {'ゥ'}}}, - {[][]rune{{'い'}, {'イ'}, {'イ'}, {'ィ'}, {'ぃ'}, {'ィ'}}}, - {[][]rune{{'あ'}, {'ア'}, {'ァ'}, {'ア'}, {'ぁ'}, {'ァ'}}}, - {[][]rune{{'ー'}, {'―'}, {'‐'}, {'-'}, {'-'}, {'ー'}, {'一'}}}, - {[][]rune{{'9'}, {'9'}}}, - {[][]rune{{'8'}, {'8'}}}, - {[][]rune{{'7'}, {'7'}}}, - {[][]rune{{'6'}, {'6'}}}, - {[][]rune{{'5'}, {'5'}}}, - {[][]rune{{'4'}, {'4'}}}, - {[][]rune{{'3'}, {'3'}}}, - {[][]rune{{'2'}, {'2'}}}, - {[][]rune{{'1'}, {'1'}}}, - {[][]rune{{'ぽ'}, {'ポ'}, {'ホ', '゚'}, {'ほ', '゚'}, {'ホ', '゚'}, {'ホ', '°'}, {'ほ', '°'}, {'ホ', '°'}}}, - {[][]rune{{'ぺ'}, {'ペ'}, {'ヘ', '゚'}, {'へ', '゚'}, {'ヘ', '゚'}, {'ヘ', '°'}, {'へ', '°'}, {'ヘ', '°'}}}, - {[][]rune{{'ぷ'}, {'プ'}, {'フ', '゚'}, {'ふ', '゚'}, {'フ', '゚'}, {'フ', '°'}, {'ふ', '°'}, {'フ', '°'}}}, - {[][]rune{{'ぴ'}, {'ピ'}, {'ヒ', '゚'}, {'ひ', '゚'}, {'ヒ', '゚'}, {'ヒ', '°'}, {'ひ', '°'}, {'ヒ', '°'}}}, - {[][]rune{{'ぱ'}, {'パ'}, {'ハ', '゚'}, {'は', '゚'}, {'ハ', '゚'}, {'ハ', '°'}, {'は', '°'}, {'ハ', '°'}, {'八', '゚'}, {'八', '゜'}}}, - {[][]rune{{'z'}, {'z'}, {'Z'}, {'Z'}, {'Ζ'}}}, - {[][]rune{{'y'}, {'y'}, {'Y'}, {'Y'}, {'Υ'}, {'У'}, {'у'}}}, - {[][]rune{{'x'}, {'x'}, {'X'}, {'X'}, {'Χ'}, {'χ'}, {'Х'}, {'×'}, {'х'}}}, - {[][]rune{{'w'}, {'w'}, {'W'}, {'W'}, {'ω'}, {'Ш'}, {'ш'}, {'щ'}}}, - {[][]rune{{'v'}, {'v'}, {'V'}, {'V'}, {'ν'}, {'υ'}}}, - {[][]rune{{'u'}, {'u'}, {'U'}, {'U'}, {'μ'}, {'∪'}}}, - {[][]rune{{'t'}, {'t'}, {'T'}, {'T'}, {'Τ'}, {'τ'}, {'Т'}, {'т'}}}, - {[][]rune{{'s'}, {'s'}, {'S'}, {'S'}, {'∫'}, {'$'}, {'$'}}}, - {[][]rune{{'r'}, {'r'}, {'R'}, {'R'}, {'Я'}, {'я'}}}, - {[][]rune{{'q'}, {'q'}, {'Q'}, {'Q'}}}, - {[][]rune{{'p'}, {'p'}, {'P'}, {'P'}, {'Ρ'}, {'ρ'}, {'Р'}, {'р'}}}, - {[][]rune{{'o'}, {'o'}, {'O'}, {'O'}, {'○'}, {'Ο'}, {'ο'}, {'О'}, {'о'}, {'◯'}, {'〇'}, {'0'}, {'0'}}}, - {[][]rune{{'n'}, {'n'}, {'N'}, {'N'}, {'Ν'}, {'η'}, {'ン'}, {'ん'}, {'ン'}}}, - {[][]rune{{'m'}, {'m'}, {'M'}, {'M'}, {'Μ'}, {'М'}, {'м'}}}, - {[][]rune{{'l'}, {'l'}, {'L'}, {'L'}, {'|'}}}, - {[][]rune{{'k'}, {'k'}, {'K'}, {'K'}, {'Κ'}, {'κ'}, {'К'}, {'к'}}}, - {[][]rune{{'j'}, {'j'}, {'J'}, {'J'}}}, - {[][]rune{{'i'}, {'i'}, {'I'}, {'I'}, {'Ι'}}}, - {[][]rune{{'h'}, {'h'}, {'H'}, {'H'}, {'Η'}, {'Н'}, {'н'}}}, - {[][]rune{{'f'}, {'f'}, {'F'}, {'F'}}}, - {[][]rune{{'g'}, {'g'}, {'G'}, {'G'}}}, - {[][]rune{{'e'}, {'e'}, {'E'}, {'E'}, {'Ε'}, {'ε'}, {'Е'}, {'Ё'}, {'е'}, {'ё'}, {'∈'}}}, - {[][]rune{{'d'}, {'d'}, {'D'}, {'D'}}}, - {[][]rune{{'c'}, {'c'}, {'C'}, {'С'}, {'с'}, {'C'}, {'℃'}}}, - {[][]rune{{'b'}, {'B'}, {'b'}, {'B'}, {'β'}, {'Β'}, {'В'}, {'в'}, {'ъ'}, {'ь'}, {'♭'}}}, - {[][]rune{{'\''}, {'’'}}}, - {[][]rune{{'a'}, {'A'}, {'a'}, {'A'}, {'α'}, {'@'}, {'@'}, {'а'}, {'Å'}, {'А'}, {'Α'}}}, - {[][]rune{{'"'}, {'”'}}}, - {[][]rune{{'%'}, {'%'}}}, - } - for _, smcGroup := range smcData { - for _, smcPair := range smcGroup.charGroup { - smc.WriteUint16(stringsupport.ToNGWord(string(smcPair[0]))[0]) - if len(smcPair) > 1 { - smc.WriteUint16(stringsupport.ToNGWord(string(smcPair[1]))[0]) - } else { - smc.WriteUint16(0) - } + mezfes := s.server.erupeConfig.DevModeOptions.MezFesEvent + alt := s.server.erupeConfig.DevModeOptions.MezFesAlt + if mezfes { + // Start time + bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) + // End time + bf.WriteUint32(uint32(channelserver.TimeWeekNext().Unix())) + bf.WriteUint8(2) // Unk + bf.WriteUint32(20) // Single tickets + bf.WriteUint32(10) // Group tickets + bf.WriteUint8(8) // Stalls open + bf.WriteUint8(0xA) // Unk + bf.WriteUint8(0x3) // Pachinko + bf.WriteUint8(0x6) // Nyanrendo + bf.WriteUint8(0x9) // Point stall + if alt { + bf.WriteUint8(0x2) // Tokotoko + } else { + bf.WriteUint8(0x4) // Volpakkun } - smc.WriteUint32(0) - } - - filters.WriteUint32(uint32(len(smc.Data()))) - filters.WriteBytes(smc.Data()) - - filters.WriteNullTerminatedBytes([]byte("nam")) - nam := byteframe.NewByteFrame() - nam.SetLE() - for _, word := range namNGWords { - parts := stringsupport.ToNGWord(word) - nam.WriteUint32(uint32(len(parts))) - for _, part := range parts { - nam.WriteUint16(part) - var i int16 - j := int16(-1) - for _, smcGroup := range smcData { - if rune(part) == rune(stringsupport.ToNGWord(string(smcGroup.charGroup[0][0]))[0]) { - j = i - break - } - i += int16(len(smcGroup.charGroup) + 1) - } - nam.WriteInt16(j) - } - nam.WriteUint16(0) - nam.WriteInt16(-1) - } - filters.WriteUint32(uint32(len(nam.Data()))) - filters.WriteBytes(nam.Data()) - - filters.WriteNullTerminatedBytes([]byte("msg")) - msg := byteframe.NewByteFrame() - msg.SetLE() - for _, word := range msgNGWords { - parts := stringsupport.ToNGWord(word) - msg.WriteUint32(uint32(len(parts))) - for _, part := range parts { - msg.WriteUint16(part) - var i int16 - j := int16(-1) - for _, smcGroup := range smcData { - if rune(part) == rune(stringsupport.ToNGWord(string(smcGroup.charGroup[0][0]))[0]) { - j = i - break - } - i += int16(len(smcGroup.charGroup) + 1) - } - msg.WriteInt16(j) - } - msg.WriteUint16(0) - msg.WriteInt16(-1) - } - filters.WriteUint32(uint32(len(msg.Data()))) - filters.WriteBytes(msg.Data()) - - bf.WriteUint16(uint16(len(filters.Data()))) - bf.WriteBytes(filters.Data()) - - if s.client == VITA || s.client == PS3 || s.client == PS4 { - var psnUser string - s.server.db.QueryRow("SELECT psn_id FROM users WHERE id = $1", uid).Scan(&psnUser) - bf.WriteBytes(stringsupport.PaddedString(psnUser, 20, true)) - } - - // CapLink.Values requires at least 5 elements to avoid index out of range panics - // Provide safe defaults if array is too small - capLinkValues := s.server.erupeConfig.DebugOptions.CapLink.Values - if len(capLinkValues) < 5 { - capLinkValues = []uint16{0, 0, 0, 0, 0} - } - - bf.WriteUint16(capLinkValues[0]) - if capLinkValues[0] == 51728 { - bf.WriteUint16(capLinkValues[1]) - if capLinkValues[1] == 20000 || capLinkValues[1] == 20002 { - ps.Uint16(bf, s.server.erupeConfig.DebugOptions.CapLink.Key, false) - } - } - caStruct := []struct { - Unk0 uint8 - Unk1 uint32 - Unk2 string - }{} - bf.WriteUint8(uint8(len(caStruct))) - for i := range caStruct { - bf.WriteUint8(caStruct[i].Unk0) - bf.WriteUint32(caStruct[i].Unk1) - ps.Uint8(bf, caStruct[i].Unk2, false) - } - bf.WriteUint16(capLinkValues[2]) - bf.WriteUint16(capLinkValues[3]) - bf.WriteUint16(capLinkValues[4]) - if capLinkValues[2] == 51729 && capLinkValues[3] == 1 && capLinkValues[4] == 20000 { - ps.Uint16(bf, fmt.Sprintf(`%s:%d`, s.server.erupeConfig.DebugOptions.CapLink.Host, s.server.erupeConfig.DebugOptions.CapLink.Port), false) - } - - bf.WriteUint32(uint32(s.server.getReturnExpiry(uid).Unix())) - bf.WriteUint32(0) - - tickets := []uint32{ - s.server.erupeConfig.GameplayOptions.MezFesSoloTickets, - s.server.erupeConfig.GameplayOptions.MezFesGroupTickets, - } - stalls := []uint8{ - 10, 3, 6, 9, 4, 8, 5, 7, - } - if s.server.erupeConfig.GameplayOptions.MezFesSwitchMinigame { - stalls[4] = 2 - } - - // We can just use the start timestamp as the event ID - bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) - // Start time - bf.WriteUint32(uint32(channelserver.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix())) - // End time - bf.WriteUint32(uint32(channelserver.TimeWeekNext().Unix())) - bf.WriteUint8(uint8(len(tickets))) - for i := range tickets { - bf.WriteUint32(tickets[i]) - } - bf.WriteUint8(uint8(len(stalls))) - for i := range stalls { - bf.WriteUint8(stalls[i]) + bf.WriteUint8(0x8) // Battle cats + bf.WriteUint8(0x5) // Gook + bf.WriteUint8(0x7) // Honey + } else { + bf.WriteUint32(0) + bf.WriteUint32(0) } return bf.Data() }