From 4d6a2b3ea9fe7482a99657bf334de66c0d5ae862 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 29 Apr 2023 15:00:13 +1000 Subject: [PATCH 01/99] fix multiple login notices --- server/signserver/dsgn_resp.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index b39a2901c..77216bee0 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -100,12 +100,10 @@ func (s *Session) makeSignResponse(uid int) []byte { } if s.server.erupeConfig.HideLoginNotice { - bf.WriteUint8(0) + bf.WriteBool(false) } else { - bf.WriteUint8(uint8(len(s.server.erupeConfig.LoginNotices))) - for _, notice := range s.server.erupeConfig.LoginNotices { - ps.Uint32(bf, notice, true) - } + bf.WriteBool(true) + ps.Uint32(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], ""), true) } bf.WriteUint32(s.server.getLastCID(uid)) From cf28660957188df3b2c37521db7eab916679c7a3 Mon Sep 17 00:00:00 2001 From: wish Date: Thu, 4 May 2023 23:41:51 +1000 Subject: [PATCH 02/99] hacky fix for PS3 object desync --- server/channelserver/handlers_object.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_object.go b/server/channelserver/handlers_object.go index 8984c21bf..520b6fef7 100644 --- a/server/channelserver/handlers_object.go +++ b/server/channelserver/handlers_object.go @@ -78,7 +78,8 @@ func handleMsgSysRotateObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgSysSetObjectBinary) + _ = p.(*mhfpacket.MsgSysSetObjectBinary) + /* This causes issues with PS3 as this actually sends with endiness! for _, session := range s.server.sessions { if session.charID == s.charID { s.server.userBinaryPartsLock.Lock() @@ -91,6 +92,7 @@ func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) { s.server.BroadcastMHF(msg, s) } } + */ } func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} From e1eea87d73c43a2c167f734017a9d32ee25aa46d Mon Sep 17 00:00:00 2001 From: wish Date: Thu, 4 May 2023 23:53:45 +1000 Subject: [PATCH 03/99] add mezfes tickets to gameplay options --- config.json | 4 +++- config/config.go | 2 ++ server/signserver/dsgn_resp.go | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/config.json b/config.json index 2a62a3809..fb6c27348 100644 --- a/config.json +++ b/config.json @@ -40,7 +40,9 @@ "BoostTimeDuration": 120, "GuildMealDuration": 60, "BonusQuestAllowance": 3, - "DailyQuestAllowance": 1 + "DailyQuestAllowance": 1, + "MezfesSoloTickets": 10, + "MezfesGroupTickets": 4 }, "Discord": { "Enabled": false, diff --git a/config/config.go b/config/config.go index 1e91b24b7..5c9ed3750 100644 --- a/config/config.go +++ b/config/config.go @@ -70,6 +70,8 @@ type GameplayOptions struct { GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily DailyQuestAllowance uint32 // Number of Daily Quests to allow daily + MezfesSoloTickets uint32 // Number of solo tickets given weekly + MezfesGroupTickets uint32 // Number of group tickets given weekly } // Discord holds the discord integration config. diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 77216bee0..40dc707d8 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -133,9 +133,9 @@ func (s *Session) makeSignResponse(uid int) []byte { 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(2) // Unk + bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesSoloTickets) + bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesGroupTickets) bf.WriteUint8(8) // Stalls open bf.WriteUint8(0xA) // Unk bf.WriteUint8(0x3) // Pachinko From 086b338f84ad548edd997ef83b2771feacbc80c9 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 13 May 2023 01:21:37 +1000 Subject: [PATCH 04/99] automatically create new character when none exist --- server/signserver/dbutils.go | 42 ++++++++-------------------------- server/signserver/dsgn_resp.go | 8 ++++++- server/signserver/session.go | 4 ++-- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/server/signserver/dbutils.go b/server/signserver/dbutils.go index ee4dcc493..3d7e34318 100644 --- a/server/signserver/dbutils.go +++ b/server/signserver/dbutils.go @@ -8,15 +8,9 @@ import ( "golang.org/x/crypto/bcrypt" ) -func (s *Server) newUserChara(username string) error { - var id int - err := s.db.QueryRow("SELECT id FROM users WHERE username = $1", username).Scan(&id) - if err != nil { - return err - } - +func (s *Server) newUserChara(uid int) error { var numNewChars int - err = s.db.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", id).Scan(&numNewChars) + err := s.db.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", uid).Scan(&numNewChars) if err != nil { return err } @@ -31,7 +25,7 @@ func (s *Server) newUserChara(username string) error { user_id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login) VALUES($1, False, True, '', '', 0, 0, 0, $2)`, - id, + uid, uint32(time.Now().Unix()), ) if err != nil { @@ -41,38 +35,20 @@ func (s *Server) newUserChara(username string) error { return nil } -func (s *Server) registerDBAccount(username string, password string) error { +func (s *Server) registerDBAccount(username string, password string) (int, error) { // Create salted hash of user password passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { - return err - } - - _, err = s.db.Exec("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3)", username, string(passwordHash), time.Now().Add(time.Hour*24*30)) - if err != nil { - return err + return 0, err } var id int - err = s.db.QueryRow("SELECT id FROM users WHERE username = $1", username).Scan(&id) + err = s.db.QueryRow("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) RETURNING id", username, string(passwordHash), time.Now().Add(time.Hour*24*30)).Scan(&id) if err != nil { - return err + return 0, err } - // Create a base new character. - _, err = s.db.Exec(` - INSERT INTO characters ( - user_id, is_female, is_new_character, name, unk_desc_string, - hrp, gr, weapon_type, last_login) - VALUES($1, False, True, '', '', 0, 0, 0, $2)`, - id, - uint32(time.Now().Unix()), - ) - if err != nil { - return err - } - - return nil + return id, nil } type character struct { @@ -89,7 +65,7 @@ type character struct { func (s *Server) getCharactersForUser(uid int) ([]character, error) { characters := make([]character, 0) - err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id ASC", uid) + err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id", uid) if err != nil { return nil, err } diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 40dc707d8..5d47dc067 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -14,6 +14,12 @@ import ( func (s *Session) makeSignResponse(uid int) []byte { // Get the characters from the DB. chars, err := s.server.getCharactersForUser(uid) + if len(chars) == 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)) } @@ -23,7 +29,7 @@ func (s *Session) makeSignResponse(uid int) []byte { bf := byteframe.NewByteFrame() - bf.WriteUint8(1) // resp_code + bf.WriteUint8(uint8(SIGN_SUCCESS)) // resp_code if (s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "") || s.client == PS3 { bf.WriteUint8(2) } else { diff --git a/server/signserver/session.go b/server/signserver/session.go index 3eb914c93..de46c5337 100644 --- a/server/signserver/session.go +++ b/server/signserver/session.go @@ -99,7 +99,7 @@ func (s *Session) authenticate(username string, password string) { s.logger.Info("User not found", zap.String("Username", username)) if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.AutoCreateAccount { s.logger.Info("Creating user", zap.String("Username", username)) - err = s.server.registerDBAccount(username, password) + id, err = s.server.registerDBAccount(username, password) if err == nil { bf.WriteBytes(s.makeSignResponse(id)) } @@ -113,7 +113,7 @@ func (s *Session) authenticate(username string, password string) { if bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil || s.client == VITA || s.client == PS3 || s.client == WIIU { s.logger.Debug("Passwords match!") if newCharaReq { - err = s.server.newUserChara(username) + err = s.server.newUserChara(id) if err != nil { s.logger.Error("Error adding new character to user", zap.Error(err)) bf.WriteUint8(uint8(SIGN_EABORT)) From 8ac0552ec1a9edfddc7c6859de911508b6172ed1 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 13 May 2023 14:07:04 +1000 Subject: [PATCH 05/99] initial decoding --- server/channelserver/handlers_quest.go | 491 ++++++++++++++++++++++++- 1 file changed, 482 insertions(+), 9 deletions(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 9caef6dbf..f941fca3f 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -1,15 +1,13 @@ package channelserver import ( - "encoding/hex" + "erupe-ce/common/byteframe" + "erupe-ce/network/mhfpacket" "fmt" + "go.uber.org/zap" "io" "os" "path/filepath" - - "erupe-ce/common/byteframe" - "erupe-ce/network/mhfpacket" - "go.uber.org/zap" ) func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { @@ -113,6 +111,485 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { return } + tuneValues := []struct { + ID uint16 + Value uint16 + }{ + {ID: 608, Value: 1}, + {ID: 612, Value: 0}, + {ID: 613, Value: 0}, + {ID: 614, Value: 1130}, + {ID: 615, Value: 0}, + {ID: 616, Value: 5}, + {ID: 617, Value: 1}, + {ID: 618, Value: 5}, + {ID: 619, Value: 1}, + {ID: 620, Value: 1}, + {ID: 621, Value: 3}, + {ID: 622, Value: 300}, + {ID: 624, Value: 2}, + {ID: 625, Value: 4}, + {ID: 626, Value: 1}, + {ID: 627, Value: 1}, + {ID: 628, Value: 5}, + {ID: 629, Value: 1}, + {ID: 630, Value: 3}, + {ID: 631, Value: 3}, + {ID: 634, Value: 5}, + {ID: 636, Value: 10}, + {ID: 637, Value: 2}, + {ID: 638, Value: 10}, + {ID: 639, Value: 4}, + {ID: 667, Value: 20}, + {ID: 668, Value: 0}, + {ID: 669, Value: 0}, + {ID: 670, Value: 0}, + {ID: 671, Value: 200}, + {ID: 672, Value: 5}, + {ID: 673, Value: 2}, + {ID: 674, Value: 10}, + {ID: 675, Value: 2}, + {ID: 676, Value: 3}, + {ID: 677, Value: 2}, + {ID: 678, Value: 10}, + {ID: 679, Value: 1}, + {ID: 680, Value: 5}, + {ID: 681, Value: 2}, + {ID: 682, Value: 10}, + {ID: 683, Value: 2}, + {ID: 684, Value: 5}, + {ID: 685, Value: 2}, + {ID: 686, Value: 10}, + {ID: 687, Value: 2}, + {ID: 692, Value: 0}, + {ID: 694, Value: 10}, + {ID: 705, Value: 50000}, + {ID: 714, Value: 80}, + {ID: 715, Value: 70}, + {ID: 716, Value: 25000}, + {ID: 717, Value: 90}, + {ID: 718, Value: 50000}, + {ID: 719, Value: 25000}, + {ID: 720, Value: 0}, + {ID: 721, Value: 1}, + {ID: 724, Value: 300}, + {ID: 726, Value: 300}, + {ID: 727, Value: 300}, + {ID: 728, Value: 4}, + {ID: 729, Value: 2}, + {ID: 730, Value: 10}, + {ID: 731, Value: 1}, + {ID: 732, Value: 4}, + {ID: 733, Value: 2}, + {ID: 734, Value: 1}, + {ID: 735, Value: 1}, + {ID: 736, Value: 8}, + {ID: 737, Value: 100}, + {ID: 738, Value: 100}, + {ID: 739, Value: 30}, + {ID: 740, Value: 999}, + {ID: 741, Value: 100}, + {ID: 742, Value: 150}, + {ID: 743, Value: 1}, + {ID: 752, Value: 99}, + {ID: 762, Value: 200}, + {ID: 765, Value: 200}, + {ID: 1296, Value: 200}, + {ID: 1297, Value: 200}, + {ID: 1298, Value: 300}, + {ID: 1299, Value: 300}, + {ID: 1300, Value: 300}, + {ID: 1301, Value: 300}, + {ID: 1305, Value: 8}, + {ID: 1306, Value: 100}, + {ID: 1307, Value: 400}, + {ID: 1701, Value: 1}, + {ID: 1718, Value: 1}, + {ID: 1720, Value: 1}, + {ID: 1735, Value: 1}, + {ID: 1742, Value: 1}, + {ID: 1747, Value: 1}, + {ID: 1751, Value: 1}, + {ID: 1757, Value: 1}, + {ID: 1778, Value: 1}, + {ID: 1788, Value: 1}, + {ID: 1789, Value: 1}, + {ID: 2278, Value: 0}, + {ID: 2560, Value: 200}, + {ID: 2561, Value: 200}, + {ID: 2562, Value: 200}, + {ID: 2563, Value: 200}, + {ID: 2564, Value: 200}, + {ID: 2565, Value: 200}, + {ID: 2566, Value: 200}, + {ID: 2567, Value: 200}, + {ID: 2568, Value: 200}, + {ID: 2569, Value: 200}, + {ID: 2570, Value: 200}, + {ID: 2571, Value: 200}, + {ID: 2572, Value: 200}, + {ID: 2573, Value: 200}, + {ID: 2574, Value: 200}, + {ID: 2575, Value: 200}, + {ID: 2576, Value: 300}, + {ID: 2577, Value: 300}, + {ID: 2578, Value: 300}, + {ID: 2579, Value: 300}, + {ID: 2580, Value: 300}, + {ID: 2581, Value: 300}, + {ID: 2582, Value: 300}, + {ID: 2583, Value: 300}, + {ID: 2584, Value: 300}, + {ID: 2585, Value: 300}, + {ID: 2586, Value: 300}, + {ID: 2587, Value: 300}, + {ID: 2588, Value: 300}, + {ID: 2589, Value: 300}, + {ID: 2590, Value: 300}, + {ID: 2591, Value: 300}, + {ID: 2608, Value: 200}, + {ID: 2609, Value: 200}, + {ID: 2616, Value: 200}, + {ID: 2617, Value: 200}, + {ID: 2618, Value: 200}, + {ID: 2619, Value: 200}, + {ID: 2620, Value: 200}, + {ID: 2621, Value: 200}, + {ID: 2622, Value: 200}, + {ID: 2623, Value: 200}, + {ID: 2624, Value: 0}, + {ID: 2625, Value: 0}, + {ID: 2626, Value: 0}, + {ID: 2627, Value: 0}, + {ID: 2628, Value: 0}, + {ID: 2629, Value: 0}, + {ID: 2632, Value: 0}, + {ID: 2634, Value: 0}, + {ID: 2635, Value: 0}, + {ID: 2636, Value: 0}, + {ID: 2637, Value: 0}, + {ID: 2638, Value: 0}, + {ID: 2639, Value: 0}, + {ID: 2664, Value: 0}, + {ID: 2665, Value: 0}, + {ID: 2666, Value: 0}, + {ID: 2667, Value: 0}, + {ID: 2668, Value: 0}, + {ID: 2669, Value: 0}, + {ID: 2670, Value: 0}, + {ID: 2671, Value: 0}, + {ID: 2674, Value: 0}, + {ID: 2676, Value: 0}, + {ID: 2677, Value: 0}, + {ID: 2678, Value: 0}, + {ID: 2679, Value: 0}, + {ID: 2694, Value: 0}, + {ID: 2696, Value: 0}, + {ID: 2697, Value: 0}, + {ID: 2704, Value: 0}, + {ID: 2705, Value: 0}, + {ID: 2706, Value: 0}, + {ID: 2707, Value: 0}, + {ID: 2708, Value: 0}, + {ID: 2709, Value: 0}, + {ID: 2710, Value: 0}, + {ID: 2711, Value: 0}, + {ID: 2716, Value: 0}, + {ID: 2718, Value: 0}, + {ID: 2719, Value: 0}, + {ID: 2720, Value: 100}, + {ID: 2722, Value: 100}, + {ID: 2723, Value: 100}, + {ID: 2724, Value: 100}, + {ID: 2725, Value: 100}, + {ID: 2726, Value: 100}, + {ID: 2727, Value: 100}, + {ID: 2736, Value: 0}, + {ID: 2737, Value: 0}, + {ID: 2738, Value: 0}, + {ID: 2739, Value: 0}, + {ID: 2744, Value: 0}, + {ID: 2745, Value: 0}, + {ID: 2746, Value: 0}, + {ID: 2747, Value: 0}, + {ID: 2748, Value: 0}, + {ID: 2749, Value: 0}, + {ID: 2750, Value: 0}, + {ID: 2751, Value: 0}, + {ID: 2752, Value: 100}, + {ID: 2753, Value: 100}, + {ID: 2754, Value: 100}, + {ID: 2755, Value: 100}, + {ID: 2756, Value: 100}, + {ID: 2757, Value: 100}, + {ID: 2758, Value: 100}, + {ID: 2759, Value: 100}, + {ID: 2762, Value: 100}, + {ID: 2764, Value: 100}, + {ID: 2765, Value: 100}, + {ID: 2766, Value: 100}, + {ID: 2767, Value: 100}, + {ID: 2776, Value: 100}, + {ID: 2777, Value: 100}, + {ID: 2778, Value: 100}, + {ID: 2779, Value: 100}, + {ID: 2780, Value: 100}, + {ID: 2781, Value: 100}, + {ID: 2784, Value: 100}, + {ID: 2785, Value: 100}, + {ID: 2792, Value: 100}, + {ID: 2793, Value: 100}, + {ID: 2794, Value: 100}, + {ID: 2795, Value: 100}, + {ID: 2796, Value: 100}, + {ID: 2797, Value: 100}, + {ID: 2798, Value: 100}, + {ID: 2799, Value: 100}, + {ID: 2804, Value: 100}, + {ID: 2806, Value: 100}, + {ID: 2807, Value: 100}, + {ID: 2816, Value: 0}, + {ID: 2818, Value: 0}, + {ID: 2819, Value: 0}, + {ID: 2820, Value: 0}, + {ID: 2821, Value: 0}, + {ID: 2822, Value: 0}, + {ID: 2823, Value: 0}, + {ID: 2832, Value: 0}, + {ID: 2833, Value: 0}, + {ID: 2834, Value: 0}, + {ID: 2835, Value: 0}, + {ID: 2840, Value: 0}, + {ID: 2841, Value: 0}, + {ID: 2842, Value: 0}, + {ID: 2843, Value: 0}, + {ID: 2844, Value: 0}, + {ID: 2845, Value: 0}, + {ID: 2846, Value: 0}, + {ID: 2847, Value: 0}, + {ID: 2848, Value: 0}, + {ID: 2849, Value: 0}, + {ID: 2850, Value: 0}, + {ID: 2851, Value: 0}, + {ID: 2852, Value: 0}, + {ID: 2853, Value: 0}, + {ID: 2854, Value: 0}, + {ID: 2855, Value: 0}, + {ID: 2858, Value: 0}, + {ID: 2860, Value: 0}, + {ID: 2861, Value: 0}, + {ID: 2862, Value: 0}, + {ID: 2863, Value: 0}, + {ID: 2872, Value: 0}, + {ID: 2873, Value: 0}, + {ID: 2874, Value: 0}, + {ID: 2875, Value: 0}, + {ID: 2876, Value: 0}, + {ID: 2877, Value: 0}, + {ID: 2880, Value: 0}, + {ID: 2881, Value: 0}, + {ID: 2888, Value: 0}, + {ID: 2889, Value: 0}, + {ID: 2890, Value: 0}, + {ID: 2891, Value: 0}, + {ID: 2892, Value: 0}, + {ID: 2893, Value: 0}, + {ID: 2894, Value: 0}, + {ID: 2895, Value: 0}, + {ID: 2900, Value: 0}, + {ID: 2902, Value: 0}, + {ID: 2903, Value: 0}, + {ID: 2920, Value: 100}, + {ID: 2921, Value: 100}, + {ID: 2922, Value: 100}, + {ID: 2923, Value: 100}, + {ID: 2928, Value: 100}, + {ID: 2929, Value: 100}, + {ID: 2930, Value: 100}, + {ID: 2931, Value: 100}, + {ID: 2932, Value: 100}, + {ID: 2933, Value: 100}, + {ID: 2934, Value: 100}, + {ID: 2935, Value: 100}, + {ID: 2942, Value: 100}, + {ID: 2946, Value: 100}, + {ID: 2948, Value: 100}, + {ID: 2949, Value: 100}, + {ID: 2950, Value: 100}, + {ID: 2951, Value: 100}, + {ID: 2960, Value: 100}, + {ID: 2961, Value: 100}, + {ID: 2962, Value: 100}, + {ID: 2963, Value: 100}, + {ID: 2964, Value: 100}, + {ID: 2965, Value: 100}, + {ID: 2968, Value: 100}, + {ID: 2970, Value: 100}, + {ID: 2971, Value: 100}, + {ID: 2972, Value: 100}, + {ID: 2973, Value: 100}, + {ID: 2974, Value: 100}, + {ID: 2975, Value: 100}, + {ID: 2976, Value: 100}, + {ID: 2977, Value: 100}, + {ID: 2978, Value: 100}, + {ID: 2979, Value: 100}, + {ID: 2980, Value: 100}, + {ID: 2981, Value: 100}, + {ID: 2982, Value: 100}, + {ID: 2983, Value: 100}, + {ID: 2988, Value: 100}, + {ID: 2990, Value: 100}, + {ID: 2991, Value: 100}, + {ID: 3000, Value: 100}, + {ID: 3001, Value: 100}, + {ID: 3002, Value: 100}, + {ID: 3003, Value: 100}, + {ID: 3004, Value: 100}, + {ID: 3005, Value: 100}, + {ID: 3006, Value: 100}, + {ID: 3007, Value: 100}, + {ID: 3008, Value: 100}, + {ID: 3009, Value: 100}, + {ID: 3010, Value: 100}, + {ID: 3011, Value: 100}, + {ID: 3012, Value: 100}, + {ID: 3013, Value: 100}, + {ID: 3014, Value: 100}, + {ID: 3015, Value: 100}, + {ID: 3016, Value: 100}, + {ID: 3017, Value: 100}, + {ID: 3018, Value: 100}, + {ID: 3019, Value: 100}, + {ID: 3020, Value: 100}, + {ID: 3021, Value: 100}, + {ID: 3022, Value: 100}, + {ID: 3023, Value: 100}, + {ID: 3024, Value: 100}, + {ID: 3025, Value: 100}, + {ID: 3026, Value: 100}, + {ID: 3027, Value: 100}, + {ID: 3028, Value: 100}, + {ID: 3029, Value: 100}, + {ID: 3030, Value: 100}, + {ID: 3031, Value: 100}, + {ID: 3032, Value: 100}, + {ID: 3033, Value: 100}, + {ID: 3034, Value: 100}, + {ID: 3035, Value: 100}, + {ID: 3036, Value: 100}, + {ID: 3037, Value: 100}, + {ID: 3038, Value: 100}, + {ID: 3039, Value: 100}, + {ID: 3040, Value: 300}, + {ID: 3041, Value: 300}, + {ID: 3042, Value: 300}, + {ID: 3043, Value: 300}, + {ID: 3044, Value: 300}, + {ID: 3045, Value: 300}, + {ID: 3046, Value: 300}, + {ID: 3047, Value: 300}, + {ID: 3048, Value: 100}, + {ID: 3049, Value: 100}, + {ID: 3050, Value: 100}, + {ID: 3051, Value: 100}, + {ID: 3052, Value: 100}, + {ID: 3053, Value: 100}, + {ID: 3054, Value: 300}, + {ID: 3055, Value: 300}, + {ID: 3056, Value: 100}, + {ID: 3057, Value: 100}, + {ID: 3058, Value: 100}, + {ID: 3059, Value: 100}, + {ID: 3060, Value: 100}, + {ID: 3061, Value: 100}, + {ID: 3062, Value: 100}, + {ID: 3063, Value: 100}, + {ID: 3064, Value: 100}, + {ID: 3065, Value: 100}, + {ID: 3066, Value: 100}, + {ID: 3067, Value: 100}, + {ID: 3068, Value: 100}, + {ID: 3069, Value: 100}, + {ID: 3070, Value: 100}, + {ID: 3071, Value: 100}, + {ID: 3328, Value: 100}, + {ID: 3329, Value: 100}, + {ID: 3330, Value: 100}, + {ID: 3331, Value: 100}, + {ID: 3332, Value: 100}, + {ID: 3333, Value: 100}, + {ID: 3334, Value: 100}, + {ID: 3335, Value: 100}, + {ID: 3336, Value: 100}, + {ID: 3337, Value: 100}, + {ID: 3338, Value: 100}, + {ID: 3339, Value: 100}, + {ID: 3340, Value: 100}, + {ID: 3341, Value: 100}, + {ID: 3342, Value: 100}, + {ID: 3343, Value: 100}, + {ID: 3344, Value: 100}, + {ID: 3345, Value: 100}, + {ID: 3346, Value: 100}, + {ID: 3347, Value: 100}, + {ID: 3348, Value: 100}, + {ID: 3349, Value: 100}, + {ID: 3350, Value: 100}, + {ID: 3351, Value: 100}, + {ID: 3358, Value: 100}, + {ID: 3360, Value: 100}, + {ID: 3361, Value: 100}, + {ID: 3362, Value: 100}, + {ID: 3363, Value: 100}, + {ID: 3364, Value: 100}, + {ID: 3365, Value: 100}, + {ID: 3366, Value: 100}, + {ID: 3367, Value: 100}, + {ID: 3368, Value: 100}, + {ID: 3369, Value: 100}, + {ID: 3370, Value: 100}, + {ID: 3371, Value: 100}, + {ID: 3372, Value: 100}, + {ID: 3373, Value: 100}, + {ID: 3374, Value: 100}, + {ID: 3375, Value: 100}, + {ID: 3376, Value: 100}, + {ID: 3377, Value: 100}, + {ID: 3378, Value: 100}, + {ID: 3379, Value: 100}, + {ID: 3380, Value: 100}, + {ID: 3381, Value: 100}, + {ID: 3382, Value: 100}, + {ID: 3383, Value: 100}, + {ID: 3384, Value: 100}, + {ID: 3385, Value: 100}, + {ID: 3386, Value: 100}, + {ID: 3387, Value: 100}, + {ID: 3388, Value: 100}, + {ID: 3389, Value: 100}, + {ID: 3390, Value: 100}, + {ID: 3391, Value: 100}, + {ID: 3416, Value: 100}, + {ID: 3417, Value: 100}, + {ID: 3418, Value: 100}, + {ID: 3419, Value: 100}, + {ID: 3420, Value: 100}, + {ID: 3421, Value: 100}, + {ID: 3422, Value: 100}, + {ID: 3423, Value: 100}, + } + //offset := uint16(time.Now().Unix()) + offset := uint16(1766) + bf.WriteUint16(offset) + bf.WriteUint16(uint16(len(tuneValues))) + for i := range tuneValues { + bf.WriteUint16(tuneValues[i].ID) + bf.WriteUint16(offset) + bf.WriteUint32(0xD4D4D400) + bf.WriteUint16(tuneValues[i].Value ^ offset) + } + vsQuestItems := []uint16{1580, 1581, 1582, 1583, 1584, 1585, 1587, 1588, 1589, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604} vsQuestBets := []struct { IsTicket bool @@ -123,10 +600,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {false, 5000}, {false, 10000}, } - - data, _ := hex.DecodeString("06E601CF051406E6D4D4D40007CA02F006E6D4D4D4000685051506E6D4D4D40007CA051206E6D4D4D40007CA051306E6D4D4D40007CA02DC06E6D4D4D40006E202D806E6D4D4D40006E202A406E6D4D4D40006E5026806E6D4D4D40006E3027406E6D4D4D40006E3027006E6D4D4D40006E4026506E6D4D4D40006E602E006E6D4D4D40006EE02E706E6D4D4D40006E70B4006E6D4D4D40006E602E206E6D4D4D400068202E506E6D4D4D400068206C706E6D4D4D40006E706B606E6D4D4D40006E706D706E6D4D4D40006E706F206E6D4D4D40006E706DD06E6D4D4D40006E706D306E6D4D4D40006E706FC06E6D4D4D40006E706B806E6D4D4D40006E706CE06E6D4D4D40006E706FD06E6D4D4D40006E706A506E6D4D4D40006E7051906E6D4D4D40006EE02E606E6D4D4D40006700B4106E6D4D4D40006E60B4E06E6D4D4D40006E60B4F06E6D4D4D40006E60B4C06E6D4D4D40006E60B4D06E6D4D4D40006E60B4A06E6D4D4D40006E60B4B06E6D4D4D40006E60B4806E6D4D4D40006E60B4906E6D4D4D40006E60B5606E6D4D4D40006E60B5706E6D4D4D40006E60B5406E6D4D4D40006E60B2606E6D4D4D40006E60B2706E6D4D4D40006E602DE06E6D4D4D40006E702DF06E6D4D4D40006E70B2406E6D4D4D40006E60B2506E6D4D4D40006E60A3006E6D4D4D400062E0A3106E6D4D4D400062E0A3E06E6D4D4D400062E0B2206E6D4D4D40006E60B2306E6D4D4D40006E60B2006E6D4D4D40006E60B2106E6D4D4D40006E60B2E06E6D4D4D40006E60B2F06E6D4D4D40006E6051A06E6D4D4D4000682051B06E6D4D4D400077602CD06E6D4D4D40006BC0B2C06E6D4D4D40006E60A3F06E6D4D4D400062E0A3C06E6D4D4D400062E0A3D06E6D4D4D400062E0A3A06E6D4D4D400062E0A3B06E6D4D4D400062E0A3806E6D4D4D400062E0A3906E6D4D4D400062E0A0606E6D4D4D400062E0A0706E6D4D4D400062E0A0406E6D4D4D400062E0A0506E6D4D4D400062E0A0206E6D4D4D400062E0A0306E6D4D4D400062E0A0006E6D4D4D400062E0A0106E6D4D4D400062E0A0E06E6D4D4D400062E0A0F06E6D4D4D400062E0A0C06E6D4D4D400062E0A0D06E6D4D4D400062E0A0A06E6D4D4D400062E0A0B06E6D4D4D400062E0A0806E6D4D4D400062E0A0906E6D4D4D400062E0A1606E6D4D4D40007CA0A1706E6D4D4D40007CA0A1406E6D4D4D40007CA0A1506E6D4D4D40007CA0A1206E6D4D4D40007CA0A1306E6D4D4D40007CA0A1006E6D4D4D40007CA0A1106E6D4D4D40007CA0A1E06E6D4D4D40007CA0A1F06E6D4D4D40007CA0A1C06E6D4D4D40007CA0A1D06E6D4D4D40007CA0A1A06E6D4D4D40007CA0A1B06E6D4D4D40007CA0A1806E6D4D4D40007CA0A1906E6D4D4D40007CA0BE606E6D4D4D40007CA0BE706E6D4D4D40007CA0BE406E6D4D4D40007CA0BE506E6D4D4D40007CA0BE206E6D4D4D40007CA0B2D06E6D4D4D40006E60B2A06E6D4D4D40006E60BE306E6D4D4D40007CA02D606E6D4D4D40007CA029F06E6D4D4D400062E0B9406E6D4D4D40006820BE006E6D4D4D40007CA0BE106E6D4D4D40007CA0BEE06E6D4D4D40007CA0BEF06E6D4D4D40007CA02C106E6D4D4D400C5B602CE06E6D4D4D400C5B602CF06E6D4D4D400674E02CC06E6D4D4D400674E051006E6D4D4D400062E02FA06E6D4D4D400062E02CA06E6D4D4D40006B602CB06E6D4D4D40006A0051106E6D4D4D400062E02FD06E6D4D4D400062E0B9506E6D4D4D40006820B9206E6D4D4D40006820B9306E6D4D4D40006820B9006E6D4D4D40006820B9106E6D4D4D40006820B9E06E6D4D4D40006820B9F06E6D4D4D40006820BEC06E6D4D4D40006820BED06E6D4D4D40006820BEA06E6D4D4D40006820BEB06E6D4D4D40006820BE806E6D4D4D40006820BE906E6D4D4D40006820BF606E6D4D4D40006820BF706E6D4D4D40006820BF406E6D4D4D40006820BF506E6D4D4D40006820BF206E6D4D4D40006820BF306E6D4D4D40006820BF006E6D4D4D40006820BF106E6D4D4D400068202DB06E6D4D4D40006E70B9C06E6D4D4D40006820BFE06E6D4D4D40006820BFF06E6D4D4D400068202A706E6D4D4D40006E70B9D06E6D4D4D40006820BFC06E6D4D4D400068202D106E6D4D4D40006E702DD06E6D4D4D40006E402DA06E6D4D4D40006EC02D906E6D4D4D40006E402A606E6D4D4D40006EC02A506E6D4D4D40006E402A206E6D4D4D40006EC02A106E6D4D4D40006E402AE06E6D4D4D40006EC02AD06E6D4D4D40006E402AA06E6D4D4D40006EC02A906E6D4D4D40006E402B606E6D4D4D40006EC0BFD06E6D4D4D40006820BFA06E6D4D4D40006820BFB06E6D4D4D40006820BF806E6D4D4D40006820BF906E6D4D4D40006820BC606E6D4D4D40006820BC706E6D4D4D40006820BC406E6D4D4D40006820BC506E6D4D4D40006820BC206E6D4D4D40006820BC306E6D4D4D40006820BC006E6D4D4D40006820BC106E6D4D4D40006820BCE06E6D4D4D40006820BCF06E6D4D4D40006820BCC06E6D4D4D40006820BCD06E6D4D4D40006820BCA06E6D4D4D40006820BCB06E6D4D4D40006820BC806E6D4D4D40006820BC906E6D4D4D40006820BD606E6D4D4D40006820BD706E6D4D4D40006820BD406E6D4D4D40006820BD506E6D4D4D40006820BD206E6D4D4D40006820BD306E6D4D4D40006820BD006E6D4D4D40006820BD106E6D4D4D40006820BDE06E6D4D4D40006820BDF06E6D4D4D40006820BDC06E6D4D4D40006820BDD06E6D4D4D40006820BDA06E6D4D4D40006820BDB06E6D4D4D40006820B9A06E6D4D4D40006820BD806E6D4D4D40006820BD906E6D4D4D40006820BA606E6D4D4D40006820BA706E6D4D4D40006820BA406E6D4D4D40006820BA506E6D4D4D40006820BA206E6D4D4D40006820BA306E6D4D4D40006820BA006E6D4D4D40006820BA106E6D4D4D40006820BAE06E6D4D4D40006820BAF06E6D4D4D40006820BAC06E6D4D4D40006820BBE06E6D4D4D40006820BBF06E6D4D4D40006820BBC06E6D4D4D40006820BBD06E6D4D4D40006820BBA06E6D4D4D40006820BBB06E6D4D4D40006820BB806E6D4D4D40006820BB906E6D4D4D40006820B8606E6D4D4D40006820B8706E6D4D4D40006820B8406E6D4D4D40006820B8506E6D4D4D40006820B8206E6D4D4D400068202D706E6D4D4D40007CA02D406E6D4D4D40007CA026E06E6D4D4D40007CA0B9B06E6D4D4D40006820B9806E6D4D4D40006820B6A06E6D4D4D40006820B6B06E6D4D4D4000682029C06E6D4D4D40006E60B6806E6D4D4D4000682029D06E6D4D4D40006E60B6906E6D4D4D40006820A6E06E6D4D4D40006E60A6F06E6D4D4D40006E60A6C06E6D4D4D40006E60A6D06E6D4D4D40006E60A6A06E6D4D4D40006E60A6B06E6D4D4D40006E60A6806E6D4D4D40006E60A6906E6D4D4D40006E60A7606E6D4D4D40006E60A7706E6D4D4D40006E602E406E6D4D4D40005010A7406E6D4D4D40006E60A7506E6D4D4D40006E602D006E6D4D4D40006E60A7206E6D4D4D40006E6026606E6D4D4D400028C0A4406E6D4D4D40006E60A4506E6D4D4D40006E6026C06E6D4D4D40006E7026D06E6D4D4D40006E5026A06E6D4D4D40006E3026B06E6D4D4D40006E70A4206E6D4D4D40006E6026906E6D4D4D40006E7027606E6D4D4D40006E5027706E6D4D4D40006E50A4306E6D4D4D40006E6027506E6D4D4D40006E7027206E6D4D4D40006E7027306E6D4D4D40006E70A4006E6D4D4D40006E60A4106E6D4D4D40006E60A4E06E6D4D4D40006E60A4F06E6D4D4D40006E60A4C06E6D4D4D40006E60A4D06E6D4D4D40006E60A4A06E6D4D4D40006E60A4B06E6D4D4D40006E60A4806E6D4D4D40006E6029E06E6D4D4D40006E602A306E6D4D4D40006E402A006E6D4D4D40006E302AF06E6D4D4D40006E402AC06E6D4D4D40006E302AB06E6D4D4D40006E402A806E6D4D4D40006E3027106E6D4D4D40006E2027E06E6D4D4D40006EC027F06E6D4D4D40006E2027C06E6D4D4D40006EC027D06E6D4D4D40006E40B7606E6D4D4D40006820B7706E6D4D4D40006820B7406E6D4D4D40006820B7506E6D4D4D40006820B7206E6D4D4D40006820B7306E6D4D4D40006820B7006E6D4D4D40006820B7106E6D4D4D40006820B7E06E6D4D4D40006820B3C06E6D4D4D40006E60D3406E6D4D4D40006820D3506E6D4D4D40006820B3D06E6D4D4D40006E6026706E6D4D4D40006E60D5E06E6D4D4D40006820D5F06E6D4D4D40006820D5C06E6D4D4D40006820D5D06E6D4D4D40006820D5A06E6D4D4D40006820D5B06E6D4D4D40006820D5806E6D4D4D40006820D5906E6D4D4D40006820D2606E6D4D4D40006820D2706E6D4D4D40006820D2406E6D4D4D40006820D2506E6D4D4D40006820D2206E6D4D4D40006820D3206E6D4D4D40006820D3306E6D4D4D40006820D3006E6D4D4D40006820D3106E6D4D4D40006820D3E06E6D4D4D40006820D2306E6D4D4D40006820D2006E6D4D4D40006820D2106E6D4D4D40006820D2E06E6D4D4D40006820D2F06E6D4D4D40006820D2C06E6D4D4D40006820D2D06E6D4D4D40006820D2A06E6D4D4D40006820D2B06E6D4D4D40006820D2806E6D4D4D40006820D2906E6D4D4D40006820D3606E6D4D4D40006820D3706E6D4D4D400068202E306E6D4D4D40006F802E106E6D4D4D40006820D3F06E6D4D4D40006820D0A06E6D4D4D40006820D0B06E6D4D4D40006820D0806E6D4D4D40006820D0906E6D4D4D40006820D1606E6D4D4D40006820D1706E6D4D4D40006820D1406E6D4D4D40006820D1506E6D4D4D40006820D1206E6D4D4D40006820D3C06E6D4D4D400068202B406E6D4D4D40006E60D1306E6D4D4D40006820D1006E6D4D4D40006820D1106E6D4D4D40006820D1E06E6D4D4D40006820AE006E6D4D4D40006820AE106E6D4D4D40006820AEE06E6D4D4D40006820AEF06E6D4D4D40006820AEC06E6D4D4D40006820AED06E6D4D4D40006820AEA06E6D4D4D40006820AEB06E6D4D4D40006820AE806E6D4D4D40006820AE906E6D4D4D40006820AF606E6D4D4D4000682026406E6D4D4D40006E60AF706E6D4D4D40006820B3A06E6D4D4D40006E60AB206E6D4D4D40006E60B3B06E6D4D4D40006E60D3D06E6D4D4D40006820D3A06E6D4D4D40006820D3B06E6D4D4D40006820AB306E6D4D4D40006E60AB006E6D4D4D40006E60AB106E6D4D4D40006E60ABE06E6D4D4D40006E60ABF06E6D4D4D40006E60ABC06E6D4D4D40006E60ABD06E6D4D4D40006E60ABA06E6D4D4D40006E60ABB06E6D4D4D40006E60AB806E6D4D4D40006E60AB906E6D4D4D40006E60A8606E6D4D4D40006E60A8806E6D4D4D40006E60A8906E6D4D4D40006E60A9606E6D4D4D40006E60A9706E6D4D4D40006E60A9406E6D4D4D40006E60A9506E6D4D4D40006E60A9206E6D4D4D40006E60A9306E6D4D4D40006E60A9006E6D4D4D40006E60A9106E6D4D4D40006E60A9E06E6D4D4D40006E60A9F06E6D4D4D40006E60A9C06E6D4D4D40006E60D3806E6D4D4D40006820D3906E6D4D4D40006820D0606E6D4D4D40006820D0706E6D4D4D40006820D0406E6D4D4D40006820D0506E6D4D4D40006820D0206E6D4D4D40006820D0306E6D4D4D40006820D0006E6D4D4D40006820D0106E6D4D4D40006820D0E06E6D4D4D40006820D0F06E6D4D4D40006820D0C06E6D4D4D40006820D0D06E6D4D4D40006820B3806E6D4D4D40006E60B3906E6D4D4D40006E60B0606E6D4D4D40006E60B0706E6D4D4D40006E60B0406E6D4D4D40006E60B0506E6D4D4D40006E60B0206E6D4D4D40006E60B0306E6D4D4D40006E60B0006E6D4D4D40006E60B1206E6D4D4D40006E60B1306E6D4D4D40006E60B1006E6D4D4D40006E60B1106E6D4D4D40006E60B1E06E6D4D4D40006E60B1F06E6D4D4D40006E60B1C06E6D4D4D40006E60B1D06E6D4D4D40006E60B1A06E6D4D4D40006E60B1B06E6D4D4D40006E60B1806E6D4D4D40006E60B1906E6D4D4D40006E608E606E6D4D4D40006E6029B06E6D4D4D40006F20AF406E6D4D4D4000682026006E6D4D4D40006E70AC606E6D4D4D40006820AC706E6D4D4D40006820AC406E6D4D4D40006820AC506E6D4D4D40006820AC206E6D4D4D40006820AC306E6D4D4D40006820AC006E6D4D4D40006820AC106E6D4D4D40006820ACE06E6D4D4D40006820ACF06E6D4D4D40006820ACC06E6D4D4D40006820ACD06E6D4D4D40006820ACA06E6D4D4D4000682027A06E6D4D4D40006E30ADC06E6D4D4D40006820ADD06E6D4D4D40006820ADA06E6D4D4D40006820ADB06E6D4D4D40006820AD806E6D4D4D40006820AD906E6D4D4D40006820AA606E6D4D4D40006820AA706E6D4D4D40006820AA406E6D4D4D40006820AA506E6D4D4D40006820AA206E6D4D4D40006820AA306E6D4D4D40006820AA006E6D4D4D4000682") - bf.WriteBytes(data) - bf.WriteUint16(uint16(len(vsQuestItems))) bf.WriteUint32(uint32(len(vsQuestBets))) bf.WriteUint16(0) // Unk From 9aae992f648596c4f534c5a409286f40cfd0426e Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 13 May 2023 16:04:13 +1000 Subject: [PATCH 06/99] tie into live time --- server/channelserver/handlers_quest.go | 712 ++++++++++++------------- 1 file changed, 356 insertions(+), 356 deletions(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index f941fca3f..72259ae32 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -8,6 +8,7 @@ import ( "io" "os" "path/filepath" + "time" ) func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { @@ -115,332 +116,105 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { ID uint16 Value uint16 }{ - {ID: 608, Value: 1}, - {ID: 612, Value: 0}, - {ID: 613, Value: 0}, - {ID: 614, Value: 1130}, - {ID: 615, Value: 0}, - {ID: 616, Value: 5}, - {ID: 617, Value: 1}, - {ID: 618, Value: 5}, - {ID: 619, Value: 1}, - {ID: 620, Value: 1}, - {ID: 621, Value: 3}, - {ID: 622, Value: 300}, - {ID: 624, Value: 2}, - {ID: 625, Value: 4}, - {ID: 626, Value: 1}, - {ID: 627, Value: 1}, - {ID: 628, Value: 5}, - {ID: 629, Value: 1}, - {ID: 630, Value: 3}, - {ID: 631, Value: 3}, - {ID: 634, Value: 5}, - {ID: 636, Value: 10}, - {ID: 637, Value: 2}, - {ID: 638, Value: 10}, - {ID: 639, Value: 4}, - {ID: 667, Value: 20}, - {ID: 668, Value: 0}, - {ID: 669, Value: 0}, - {ID: 670, Value: 0}, - {ID: 671, Value: 200}, - {ID: 672, Value: 5}, - {ID: 673, Value: 2}, - {ID: 674, Value: 10}, - {ID: 675, Value: 2}, - {ID: 676, Value: 3}, - {ID: 677, Value: 2}, - {ID: 678, Value: 10}, - {ID: 679, Value: 1}, - {ID: 680, Value: 5}, - {ID: 681, Value: 2}, - {ID: 682, Value: 10}, - {ID: 683, Value: 2}, - {ID: 684, Value: 5}, - {ID: 685, Value: 2}, - {ID: 686, Value: 10}, - {ID: 687, Value: 2}, - {ID: 692, Value: 0}, - {ID: 694, Value: 10}, - {ID: 705, Value: 50000}, - {ID: 714, Value: 80}, - {ID: 715, Value: 70}, - {ID: 716, Value: 25000}, - {ID: 717, Value: 90}, - {ID: 718, Value: 50000}, - {ID: 719, Value: 25000}, - {ID: 720, Value: 0}, - {ID: 721, Value: 1}, - {ID: 724, Value: 300}, - {ID: 726, Value: 300}, - {ID: 727, Value: 300}, - {ID: 728, Value: 4}, - {ID: 729, Value: 2}, - {ID: 730, Value: 10}, - {ID: 731, Value: 1}, - {ID: 732, Value: 4}, - {ID: 733, Value: 2}, - {ID: 734, Value: 1}, - {ID: 735, Value: 1}, - {ID: 736, Value: 8}, - {ID: 737, Value: 100}, - {ID: 738, Value: 100}, - {ID: 739, Value: 30}, - {ID: 740, Value: 999}, - {ID: 741, Value: 100}, - {ID: 742, Value: 150}, - {ID: 743, Value: 1}, - {ID: 752, Value: 99}, - {ID: 762, Value: 200}, - {ID: 765, Value: 200}, - {ID: 1296, Value: 200}, - {ID: 1297, Value: 200}, - {ID: 1298, Value: 300}, - {ID: 1299, Value: 300}, - {ID: 1300, Value: 300}, - {ID: 1301, Value: 300}, - {ID: 1305, Value: 8}, - {ID: 1306, Value: 100}, - {ID: 1307, Value: 400}, - {ID: 1701, Value: 1}, - {ID: 1718, Value: 1}, - {ID: 1720, Value: 1}, - {ID: 1735, Value: 1}, - {ID: 1742, Value: 1}, - {ID: 1747, Value: 1}, - {ID: 1751, Value: 1}, - {ID: 1757, Value: 1}, - {ID: 1778, Value: 1}, - {ID: 1788, Value: 1}, - {ID: 1789, Value: 1}, - {ID: 2278, Value: 0}, - {ID: 2560, Value: 200}, - {ID: 2561, Value: 200}, - {ID: 2562, Value: 200}, - {ID: 2563, Value: 200}, - {ID: 2564, Value: 200}, - {ID: 2565, Value: 200}, - {ID: 2566, Value: 200}, - {ID: 2567, Value: 200}, - {ID: 2568, Value: 200}, - {ID: 2569, Value: 200}, - {ID: 2570, Value: 200}, - {ID: 2571, Value: 200}, - {ID: 2572, Value: 200}, - {ID: 2573, Value: 200}, - {ID: 2574, Value: 200}, - {ID: 2575, Value: 200}, - {ID: 2576, Value: 300}, - {ID: 2577, Value: 300}, - {ID: 2578, Value: 300}, - {ID: 2579, Value: 300}, - {ID: 2580, Value: 300}, - {ID: 2581, Value: 300}, - {ID: 2582, Value: 300}, - {ID: 2583, Value: 300}, - {ID: 2584, Value: 300}, - {ID: 2585, Value: 300}, - {ID: 2586, Value: 300}, - {ID: 2587, Value: 300}, - {ID: 2588, Value: 300}, - {ID: 2589, Value: 300}, - {ID: 2590, Value: 300}, - {ID: 2591, Value: 300}, - {ID: 2608, Value: 200}, - {ID: 2609, Value: 200}, - {ID: 2616, Value: 200}, - {ID: 2617, Value: 200}, - {ID: 2618, Value: 200}, - {ID: 2619, Value: 200}, - {ID: 2620, Value: 200}, - {ID: 2621, Value: 200}, - {ID: 2622, Value: 200}, - {ID: 2623, Value: 200}, - {ID: 2624, Value: 0}, - {ID: 2625, Value: 0}, - {ID: 2626, Value: 0}, - {ID: 2627, Value: 0}, - {ID: 2628, Value: 0}, - {ID: 2629, Value: 0}, - {ID: 2632, Value: 0}, - {ID: 2634, Value: 0}, - {ID: 2635, Value: 0}, - {ID: 2636, Value: 0}, - {ID: 2637, Value: 0}, - {ID: 2638, Value: 0}, - {ID: 2639, Value: 0}, - {ID: 2664, Value: 0}, - {ID: 2665, Value: 0}, - {ID: 2666, Value: 0}, - {ID: 2667, Value: 0}, - {ID: 2668, Value: 0}, - {ID: 2669, Value: 0}, - {ID: 2670, Value: 0}, - {ID: 2671, Value: 0}, - {ID: 2674, Value: 0}, - {ID: 2676, Value: 0}, - {ID: 2677, Value: 0}, - {ID: 2678, Value: 0}, - {ID: 2679, Value: 0}, - {ID: 2694, Value: 0}, - {ID: 2696, Value: 0}, - {ID: 2697, Value: 0}, - {ID: 2704, Value: 0}, - {ID: 2705, Value: 0}, - {ID: 2706, Value: 0}, - {ID: 2707, Value: 0}, - {ID: 2708, Value: 0}, - {ID: 2709, Value: 0}, - {ID: 2710, Value: 0}, - {ID: 2711, Value: 0}, - {ID: 2716, Value: 0}, - {ID: 2718, Value: 0}, - {ID: 2719, Value: 0}, - {ID: 2720, Value: 100}, - {ID: 2722, Value: 100}, - {ID: 2723, Value: 100}, - {ID: 2724, Value: 100}, - {ID: 2725, Value: 100}, - {ID: 2726, Value: 100}, - {ID: 2727, Value: 100}, - {ID: 2736, Value: 0}, - {ID: 2737, Value: 0}, - {ID: 2738, Value: 0}, - {ID: 2739, Value: 0}, - {ID: 2744, Value: 0}, - {ID: 2745, Value: 0}, - {ID: 2746, Value: 0}, - {ID: 2747, Value: 0}, - {ID: 2748, Value: 0}, - {ID: 2749, Value: 0}, - {ID: 2750, Value: 0}, - {ID: 2751, Value: 0}, - {ID: 2752, Value: 100}, - {ID: 2753, Value: 100}, - {ID: 2754, Value: 100}, - {ID: 2755, Value: 100}, - {ID: 2756, Value: 100}, - {ID: 2757, Value: 100}, - {ID: 2758, Value: 100}, - {ID: 2759, Value: 100}, - {ID: 2762, Value: 100}, - {ID: 2764, Value: 100}, - {ID: 2765, Value: 100}, - {ID: 2766, Value: 100}, - {ID: 2767, Value: 100}, - {ID: 2776, Value: 100}, - {ID: 2777, Value: 100}, - {ID: 2778, Value: 100}, - {ID: 2779, Value: 100}, - {ID: 2780, Value: 100}, - {ID: 2781, Value: 100}, - {ID: 2784, Value: 100}, - {ID: 2785, Value: 100}, - {ID: 2792, Value: 100}, - {ID: 2793, Value: 100}, - {ID: 2794, Value: 100}, - {ID: 2795, Value: 100}, - {ID: 2796, Value: 100}, - {ID: 2797, Value: 100}, - {ID: 2798, Value: 100}, - {ID: 2799, Value: 100}, - {ID: 2804, Value: 100}, - {ID: 2806, Value: 100}, - {ID: 2807, Value: 100}, - {ID: 2816, Value: 0}, - {ID: 2818, Value: 0}, - {ID: 2819, Value: 0}, - {ID: 2820, Value: 0}, - {ID: 2821, Value: 0}, - {ID: 2822, Value: 0}, - {ID: 2823, Value: 0}, - {ID: 2832, Value: 0}, - {ID: 2833, Value: 0}, - {ID: 2834, Value: 0}, - {ID: 2835, Value: 0}, - {ID: 2840, Value: 0}, - {ID: 2841, Value: 0}, - {ID: 2842, Value: 0}, - {ID: 2843, Value: 0}, - {ID: 2844, Value: 0}, - {ID: 2845, Value: 0}, - {ID: 2846, Value: 0}, - {ID: 2847, Value: 0}, - {ID: 2848, Value: 0}, - {ID: 2849, Value: 0}, - {ID: 2850, Value: 0}, - {ID: 2851, Value: 0}, - {ID: 2852, Value: 0}, - {ID: 2853, Value: 0}, - {ID: 2854, Value: 0}, - {ID: 2855, Value: 0}, - {ID: 2858, Value: 0}, - {ID: 2860, Value: 0}, - {ID: 2861, Value: 0}, - {ID: 2862, Value: 0}, - {ID: 2863, Value: 0}, - {ID: 2872, Value: 0}, - {ID: 2873, Value: 0}, - {ID: 2874, Value: 0}, - {ID: 2875, Value: 0}, - {ID: 2876, Value: 0}, - {ID: 2877, Value: 0}, - {ID: 2880, Value: 0}, - {ID: 2881, Value: 0}, - {ID: 2888, Value: 0}, - {ID: 2889, Value: 0}, - {ID: 2890, Value: 0}, - {ID: 2891, Value: 0}, - {ID: 2892, Value: 0}, - {ID: 2893, Value: 0}, - {ID: 2894, Value: 0}, - {ID: 2895, Value: 0}, - {ID: 2900, Value: 0}, - {ID: 2902, Value: 0}, - {ID: 2903, Value: 0}, - {ID: 2920, Value: 100}, - {ID: 2921, Value: 100}, - {ID: 2922, Value: 100}, - {ID: 2923, Value: 100}, - {ID: 2928, Value: 100}, - {ID: 2929, Value: 100}, - {ID: 2930, Value: 100}, - {ID: 2931, Value: 100}, - {ID: 2932, Value: 100}, - {ID: 2933, Value: 100}, - {ID: 2934, Value: 100}, - {ID: 2935, Value: 100}, - {ID: 2942, Value: 100}, - {ID: 2946, Value: 100}, - {ID: 2948, Value: 100}, - {ID: 2949, Value: 100}, - {ID: 2950, Value: 100}, - {ID: 2951, Value: 100}, - {ID: 2960, Value: 100}, - {ID: 2961, Value: 100}, - {ID: 2962, Value: 100}, - {ID: 2963, Value: 100}, - {ID: 2964, Value: 100}, - {ID: 2965, Value: 100}, - {ID: 2968, Value: 100}, - {ID: 2970, Value: 100}, - {ID: 2971, Value: 100}, - {ID: 2972, Value: 100}, - {ID: 2973, Value: 100}, - {ID: 2974, Value: 100}, - {ID: 2975, Value: 100}, - {ID: 2976, Value: 100}, - {ID: 2977, Value: 100}, - {ID: 2978, Value: 100}, - {ID: 2979, Value: 100}, - {ID: 2980, Value: 100}, - {ID: 2981, Value: 100}, - {ID: 2982, Value: 100}, - {ID: 2983, Value: 100}, - {ID: 2988, Value: 100}, - {ID: 2990, Value: 100}, - {ID: 2991, Value: 100}, + {ID: 20, Value: 1}, + {ID: 26, Value: 1}, + {ID: 27, Value: 1}, + {ID: 33, Value: 1}, + {ID: 40, Value: 1}, + {ID: 49, Value: 1}, + {ID: 53, Value: 1}, + {ID: 59, Value: 1}, + {ID: 67, Value: 1}, + {ID: 80, Value: 1}, + {ID: 94, Value: 1}, + {ID: 1010, Value: 300}, + {ID: 1011, Value: 300}, + {ID: 1012, Value: 300}, + {ID: 1013, Value: 300}, + {ID: 1014, Value: 200}, + {ID: 1015, Value: 200}, + {ID: 1020, Value: 100}, + {ID: 1021, Value: 400}, + {ID: 1023, Value: 8}, + {ID: 1024, Value: 150}, + {ID: 1025, Value: 1}, + {ID: 1026, Value: 999}, + {ID: 1027, Value: 100}, + {ID: 1028, Value: 100}, + {ID: 1029, Value: 30}, + {ID: 1030, Value: 8}, + {ID: 1031, Value: 100}, + {ID: 1046, Value: 99}, + {ID: 1051, Value: 200}, + {ID: 1052, Value: 200}, + {ID: 1063, Value: 50000}, + {ID: 1064, Value: 50000}, + {ID: 1065, Value: 25000}, + {ID: 1066, Value: 25000}, + {ID: 1067, Value: 90}, + {ID: 1068, Value: 80}, + {ID: 1069, Value: 70}, + {ID: 1072, Value: 300}, + {ID: 1073, Value: 300}, + {ID: 1074, Value: 300}, + {ID: 1078, Value: 0}, + {ID: 1079, Value: 1}, + {ID: 1080, Value: 1}, + {ID: 1081, Value: 1}, + {ID: 1082, Value: 4}, + {ID: 1083, Value: 2}, + {ID: 1084, Value: 10}, + {ID: 1085, Value: 1}, + {ID: 1086, Value: 4}, + {ID: 1087, Value: 2}, + {ID: 1088, Value: 10}, + {ID: 1089, Value: 1}, + {ID: 1090, Value: 3}, + {ID: 1091, Value: 2}, + {ID: 1092, Value: 10}, + {ID: 1093, Value: 2}, + {ID: 1094, Value: 5}, + {ID: 1095, Value: 2}, + {ID: 1096, Value: 10}, + {ID: 1097, Value: 2}, + {ID: 1098, Value: 5}, + {ID: 1099, Value: 2}, + {ID: 1100, Value: 10}, + {ID: 1101, Value: 2}, + {ID: 1102, Value: 5}, + {ID: 1103, Value: 2}, + {ID: 1104, Value: 10}, + {ID: 1106, Value: 0}, + {ID: 1144, Value: 0}, + {ID: 1145, Value: 200}, + {ID: 1146, Value: 0}, + {ID: 1147, Value: 0}, + {ID: 1149, Value: 20}, + {ID: 1152, Value: 1130}, + {ID: 1153, Value: 0}, + {ID: 1154, Value: 0}, + {ID: 1155, Value: 0}, + {ID: 1158, Value: 1}, + {ID: 1160, Value: 300}, + {ID: 1162, Value: 1}, + {ID: 1163, Value: 3}, + {ID: 1164, Value: 5}, + {ID: 1165, Value: 1}, + {ID: 1166, Value: 5}, + {ID: 1167, Value: 1}, + {ID: 1168, Value: 3}, + {ID: 1169, Value: 3}, + {ID: 1170, Value: 5}, + {ID: 1171, Value: 1}, + {ID: 1172, Value: 1}, + {ID: 1173, Value: 1}, + {ID: 1174, Value: 2}, + {ID: 1175, Value: 4}, + {ID: 1176, Value: 10}, + {ID: 1177, Value: 4}, + {ID: 1178, Value: 10}, + {ID: 1179, Value: 2}, + {ID: 1180, Value: 5}, {ID: 3000, Value: 100}, {ID: 3001, Value: 100}, {ID: 3002, Value: 100}, @@ -481,22 +255,22 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3037, Value: 100}, {ID: 3038, Value: 100}, {ID: 3039, Value: 100}, - {ID: 3040, Value: 300}, - {ID: 3041, Value: 300}, - {ID: 3042, Value: 300}, - {ID: 3043, Value: 300}, - {ID: 3044, Value: 300}, - {ID: 3045, Value: 300}, - {ID: 3046, Value: 300}, - {ID: 3047, Value: 300}, + {ID: 3040, Value: 100}, + {ID: 3041, Value: 100}, + {ID: 3042, Value: 100}, + {ID: 3043, Value: 100}, + {ID: 3044, Value: 100}, + {ID: 3045, Value: 100}, + {ID: 3046, Value: 100}, + {ID: 3047, Value: 100}, {ID: 3048, Value: 100}, {ID: 3049, Value: 100}, {ID: 3050, Value: 100}, {ID: 3051, Value: 100}, {ID: 3052, Value: 100}, {ID: 3053, Value: 100}, - {ID: 3054, Value: 300}, - {ID: 3055, Value: 300}, + {ID: 3054, Value: 100}, + {ID: 3055, Value: 100}, {ID: 3056, Value: 100}, {ID: 3057, Value: 100}, {ID: 3058, Value: 100}, @@ -506,23 +280,149 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3062, Value: 100}, {ID: 3063, Value: 100}, {ID: 3064, Value: 100}, - {ID: 3065, Value: 100}, - {ID: 3066, Value: 100}, - {ID: 3067, Value: 100}, - {ID: 3068, Value: 100}, - {ID: 3069, Value: 100}, - {ID: 3070, Value: 100}, - {ID: 3071, Value: 100}, - {ID: 3328, Value: 100}, - {ID: 3329, Value: 100}, - {ID: 3330, Value: 100}, - {ID: 3331, Value: 100}, - {ID: 3332, Value: 100}, - {ID: 3333, Value: 100}, - {ID: 3334, Value: 100}, - {ID: 3335, Value: 100}, - {ID: 3336, Value: 100}, - {ID: 3337, Value: 100}, + {ID: 3078, Value: 100}, + {ID: 3079, Value: 100}, + {ID: 3080, Value: 100}, + {ID: 3081, Value: 100}, + {ID: 3082, Value: 100}, + {ID: 3083, Value: 100}, + {ID: 3084, Value: 100}, + {ID: 3085, Value: 100}, + {ID: 3086, Value: 100}, + {ID: 3087, Value: 100}, + {ID: 3088, Value: 100}, + {ID: 3089, Value: 100}, + {ID: 3090, Value: 100}, + {ID: 3104, Value: 100}, + {ID: 3105, Value: 100}, + {ID: 3106, Value: 100}, + {ID: 3107, Value: 100}, + {ID: 3108, Value: 100}, + {ID: 3109, Value: 100}, + {ID: 3110, Value: 100}, + {ID: 3111, Value: 100}, + {ID: 3112, Value: 100}, + {ID: 3113, Value: 100}, + {ID: 3114, Value: 100}, + {ID: 3115, Value: 100}, + {ID: 3116, Value: 100}, + {ID: 3130, Value: 100}, + {ID: 3131, Value: 100}, + {ID: 3132, Value: 100}, + {ID: 3133, Value: 100}, + {ID: 3134, Value: 100}, + {ID: 3135, Value: 100}, + {ID: 3136, Value: 100}, + {ID: 3137, Value: 100}, + {ID: 3138, Value: 100}, + {ID: 3139, Value: 100}, + {ID: 3140, Value: 100}, + {ID: 3141, Value: 100}, + {ID: 3142, Value: 100}, + {ID: 3156, Value: 0}, + {ID: 3157, Value: 0}, + {ID: 3158, Value: 0}, + {ID: 3159, Value: 0}, + {ID: 3160, Value: 0}, + {ID: 3161, Value: 0}, + {ID: 3162, Value: 0}, + {ID: 3163, Value: 0}, + {ID: 3164, Value: 0}, + {ID: 3165, Value: 0}, + {ID: 3166, Value: 0}, + {ID: 3167, Value: 0}, + {ID: 3168, Value: 0}, + {ID: 3182, Value: 0}, + {ID: 3183, Value: 0}, + {ID: 3184, Value: 0}, + {ID: 3185, Value: 0}, + {ID: 3186, Value: 0}, + {ID: 3187, Value: 0}, + {ID: 3188, Value: 0}, + {ID: 3189, Value: 0}, + {ID: 3190, Value: 0}, + {ID: 3191, Value: 0}, + {ID: 3192, Value: 0}, + {ID: 3193, Value: 0}, + {ID: 3194, Value: 0}, + {ID: 3208, Value: 0}, + {ID: 3209, Value: 0}, + {ID: 3210, Value: 0}, + {ID: 3211, Value: 0}, + {ID: 3212, Value: 0}, + {ID: 3213, Value: 0}, + {ID: 3214, Value: 0}, + {ID: 3215, Value: 0}, + {ID: 3216, Value: 0}, + {ID: 3217, Value: 0}, + {ID: 3218, Value: 0}, + {ID: 3219, Value: 0}, + {ID: 3220, Value: 0}, + {ID: 3234, Value: 0}, + {ID: 3235, Value: 0}, + {ID: 3236, Value: 0}, + {ID: 3237, Value: 0}, + {ID: 3238, Value: 0}, + {ID: 3239, Value: 0}, + {ID: 3240, Value: 0}, + {ID: 3241, Value: 0}, + {ID: 3242, Value: 0}, + {ID: 3243, Value: 0}, + {ID: 3244, Value: 0}, + {ID: 3245, Value: 0}, + {ID: 3246, Value: 0}, + {ID: 3286, Value: 200}, + {ID: 3287, Value: 200}, + {ID: 3288, Value: 200}, + {ID: 3289, Value: 200}, + {ID: 3290, Value: 200}, + {ID: 3291, Value: 200}, + {ID: 3292, Value: 200}, + {ID: 3293, Value: 200}, + {ID: 3294, Value: 200}, + {ID: 3295, Value: 200}, + {ID: 3296, Value: 200}, + {ID: 3297, Value: 200}, + {ID: 3298, Value: 200}, + {ID: 3299, Value: 200}, + {ID: 3300, Value: 200}, + {ID: 3301, Value: 200}, + {ID: 3302, Value: 200}, + {ID: 3303, Value: 200}, + {ID: 3304, Value: 200}, + {ID: 3305, Value: 200}, + {ID: 3306, Value: 200}, + {ID: 3307, Value: 200}, + {ID: 3308, Value: 200}, + {ID: 3309, Value: 200}, + {ID: 3310, Value: 200}, + {ID: 3311, Value: 200}, + {ID: 3312, Value: 300}, + {ID: 3313, Value: 300}, + {ID: 3314, Value: 300}, + {ID: 3315, Value: 300}, + {ID: 3316, Value: 300}, + {ID: 3317, Value: 300}, + {ID: 3318, Value: 300}, + {ID: 3319, Value: 300}, + {ID: 3320, Value: 300}, + {ID: 3321, Value: 300}, + {ID: 3322, Value: 300}, + {ID: 3323, Value: 300}, + {ID: 3324, Value: 300}, + {ID: 3325, Value: 300}, + {ID: 3326, Value: 300}, + {ID: 3327, Value: 300}, + {ID: 3328, Value: 300}, + {ID: 3329, Value: 300}, + {ID: 3330, Value: 300}, + {ID: 3331, Value: 300}, + {ID: 3332, Value: 300}, + {ID: 3333, Value: 300}, + {ID: 3334, Value: 300}, + {ID: 3335, Value: 300}, + {ID: 3336, Value: 300}, + {ID: 3337, Value: 300}, {ID: 3338, Value: 100}, {ID: 3339, Value: 100}, {ID: 3340, Value: 100}, @@ -537,7 +437,14 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3349, Value: 100}, {ID: 3350, Value: 100}, {ID: 3351, Value: 100}, + {ID: 3352, Value: 100}, + {ID: 3353, Value: 100}, + {ID: 3354, Value: 100}, + {ID: 3355, Value: 100}, + {ID: 3356, Value: 100}, + {ID: 3357, Value: 100}, {ID: 3358, Value: 100}, + {ID: 3359, Value: 100}, {ID: 3360, Value: 100}, {ID: 3361, Value: 100}, {ID: 3362, Value: 100}, @@ -570,6 +477,17 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3389, Value: 100}, {ID: 3390, Value: 100}, {ID: 3391, Value: 100}, + {ID: 3392, Value: 100}, + {ID: 3393, Value: 100}, + {ID: 3394, Value: 100}, + {ID: 3395, Value: 100}, + {ID: 3396, Value: 100}, + {ID: 3397, Value: 100}, + {ID: 3398, Value: 100}, + {ID: 3399, Value: 100}, + {ID: 3400, Value: 100}, + {ID: 3401, Value: 100}, + {ID: 3402, Value: 100}, {ID: 3416, Value: 100}, {ID: 3417, Value: 100}, {ID: 3418, Value: 100}, @@ -578,13 +496,95 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3421, Value: 100}, {ID: 3422, Value: 100}, {ID: 3423, Value: 100}, + {ID: 3424, Value: 100}, + {ID: 3425, Value: 100}, + {ID: 3426, Value: 100}, + {ID: 3427, Value: 100}, + {ID: 3428, Value: 100}, + {ID: 3442, Value: 100}, + {ID: 3443, Value: 100}, + {ID: 3444, Value: 100}, + {ID: 3445, Value: 100}, + {ID: 3446, Value: 100}, + {ID: 3447, Value: 100}, + {ID: 3448, Value: 100}, + {ID: 3449, Value: 100}, + {ID: 3450, Value: 100}, + {ID: 3451, Value: 100}, + {ID: 3452, Value: 100}, + {ID: 3453, Value: 100}, + {ID: 3454, Value: 100}, + {ID: 3468, Value: 100}, + {ID: 3469, Value: 100}, + {ID: 3470, Value: 100}, + {ID: 3471, Value: 100}, + {ID: 3472, Value: 100}, + {ID: 3473, Value: 100}, + {ID: 3474, Value: 100}, + {ID: 3475, Value: 100}, + {ID: 3476, Value: 100}, + {ID: 3477, Value: 100}, + {ID: 3478, Value: 100}, + {ID: 3479, Value: 100}, + {ID: 3480, Value: 100}, + {ID: 3494, Value: 0}, + {ID: 3495, Value: 0}, + {ID: 3496, Value: 0}, + {ID: 3497, Value: 0}, + {ID: 3498, Value: 0}, + {ID: 3499, Value: 0}, + {ID: 3500, Value: 0}, + {ID: 3501, Value: 0}, + {ID: 3502, Value: 0}, + {ID: 3503, Value: 0}, + {ID: 3504, Value: 0}, + {ID: 3505, Value: 0}, + {ID: 3506, Value: 0}, + {ID: 3520, Value: 0}, + {ID: 3521, Value: 0}, + {ID: 3522, Value: 0}, + {ID: 3523, Value: 0}, + {ID: 3524, Value: 0}, + {ID: 3525, Value: 0}, + {ID: 3526, Value: 0}, + {ID: 3527, Value: 0}, + {ID: 3528, Value: 0}, + {ID: 3529, Value: 0}, + {ID: 3530, Value: 0}, + {ID: 3531, Value: 0}, + {ID: 3532, Value: 0}, + {ID: 3546, Value: 0}, + {ID: 3547, Value: 0}, + {ID: 3548, Value: 0}, + {ID: 3549, Value: 0}, + {ID: 3550, Value: 0}, + {ID: 3551, Value: 0}, + {ID: 3552, Value: 0}, + {ID: 3553, Value: 0}, + {ID: 3554, Value: 0}, + {ID: 3555, Value: 0}, + {ID: 3556, Value: 0}, + {ID: 3557, Value: 0}, + {ID: 3558, Value: 0}, + {ID: 3572, Value: 0}, + {ID: 3573, Value: 0}, + {ID: 3574, Value: 0}, + {ID: 3575, Value: 0}, + {ID: 3576, Value: 0}, + {ID: 3577, Value: 0}, + {ID: 3578, Value: 0}, + {ID: 3579, Value: 0}, + {ID: 3580, Value: 0}, + {ID: 3581, Value: 0}, + {ID: 3582, Value: 0}, + {ID: 3583, Value: 0}, + {ID: 3584, Value: 0}, } - //offset := uint16(time.Now().Unix()) - offset := uint16(1766) + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) for i := range tuneValues { - bf.WriteUint16(tuneValues[i].ID) + bf.WriteUint16(tuneValues[i].ID ^ offset) bf.WriteUint16(offset) bf.WriteUint32(0xD4D4D400) bf.WriteUint16(tuneValues[i].Value ^ offset) From 9dd9931176175281c588950ca63d65a4c2ddbbfa Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 14 May 2023 15:34:33 +1000 Subject: [PATCH 07/99] add customisable tune values --- config.json | 4 +++- config/config.go | 24 +++++++++++++----------- server/channelserver/handlers_quest.go | 19 ++++++++++++++----- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/config.json b/config.json index fb6c27348..aa1521a74 100644 --- a/config.json +++ b/config.json @@ -42,7 +42,9 @@ "BonusQuestAllowance": 3, "DailyQuestAllowance": 1, "MezfesSoloTickets": 10, - "MezfesGroupTickets": 4 + "MezfesGroupTickets": 4, + "GUrgentRate": 10, + "EnableHiganjimaEvent": false }, "Discord": { "Enabled": false, diff --git a/config/config.go b/config/config.go index 5c9ed3750..a500a2d2f 100644 --- a/config/config.go +++ b/config/config.go @@ -61,17 +61,19 @@ type SaveDumpOptions struct { // GameplayOptions has various gameplay modifiers type GameplayOptions struct { - FeaturedWeapons int // Number of Active Feature weapons to generate daily - MaximumNP int // Maximum number of NP held by a player - MaximumRP uint16 // Maximum number of RP held by a player - DisableLoginBoost bool // Disables the Login Boost system - DisableBoostTime bool // Disables the daily NetCafe Boost Time - BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for - GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking - BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily - DailyQuestAllowance uint32 // Number of Daily Quests to allow daily - MezfesSoloTickets uint32 // Number of solo tickets given weekly - MezfesGroupTickets uint32 // Number of group tickets given weekly + FeaturedWeapons int // Number of Active Feature weapons to generate daily + MaximumNP int // Maximum number of NP held by a player + MaximumRP uint16 // Maximum number of RP held by a player + DisableLoginBoost bool // Disables the Login Boost system + DisableBoostTime bool // Disables the daily NetCafe Boost Time + BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for + GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking + BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily + DailyQuestAllowance uint32 // Number of Daily Quests to allow daily + MezfesSoloTickets uint32 // Number of solo tickets given weekly + MezfesGroupTickets uint32 // Number of group tickets given weekly + GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning + EnableHiganjimaEvent bool // Enables the Higanjima event } // Discord holds the discord integration config. diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 72259ae32..cbeb88cad 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -107,15 +107,17 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { } return nil }) - if err != nil || totalCount == 0 { + if err != nil { doAckBufSucceed(s, pkt.AckHandle, make([]byte, 18)) return } - tuneValues := []struct { + type tuneValue struct { ID uint16 Value uint16 - }{ + } + + tuneValues := []tuneValue{ {ID: 20, Value: 1}, {ID: 26, Value: 1}, {ID: 27, Value: 1}, @@ -141,7 +143,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1026, Value: 999}, {ID: 1027, Value: 100}, {ID: 1028, Value: 100}, - {ID: 1029, Value: 30}, {ID: 1030, Value: 8}, {ID: 1031, Value: 100}, {ID: 1046, Value: 99}, @@ -185,7 +186,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1103, Value: 2}, {ID: 1104, Value: 10}, {ID: 1106, Value: 0}, - {ID: 1144, Value: 0}, {ID: 1145, Value: 200}, {ID: 1146, Value: 0}, {ID: 1147, Value: 0}, @@ -580,6 +580,15 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3583, Value: 0}, {ID: 3584, Value: 0}, } + + tuneValues = append(tuneValues, tuneValue{1029, s.server.erupeConfig.GameplayOptions.GUrgentRate}) + + if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent { + tuneValues = append(tuneValues, tuneValue{1144, 1}) + } else { + tuneValues = append(tuneValues, tuneValue{1144, 0}) + } + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) From 2a7454d0ad92470b3097a361b6257cec7f7d249d Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 14 May 2023 15:50:11 +1000 Subject: [PATCH 08/99] add customisable tune values --- config.json | 3 ++- config/config.go | 3 ++- server/channelserver/handlers_quest.go | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/config.json b/config.json index aa1521a74..b057d1700 100644 --- a/config.json +++ b/config.json @@ -44,7 +44,8 @@ "MezfesSoloTickets": 10, "MezfesGroupTickets": 4, "GUrgentRate": 10, - "EnableHiganjimaEvent": false + "EnableHiganjimaEvent": false, + "EnableNierEvent": false }, "Discord": { "Enabled": false, diff --git a/config/config.go b/config/config.go index a500a2d2f..7666a069b 100644 --- a/config/config.go +++ b/config/config.go @@ -73,7 +73,8 @@ type GameplayOptions struct { MezfesSoloTickets uint32 // Number of solo tickets given weekly MezfesGroupTickets uint32 // Number of group tickets given weekly GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning - EnableHiganjimaEvent bool // Enables the Higanjima event + EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar + EnableNierEvent bool // Enables the Nier event in the Rasta Bar } // Discord holds the discord integration config. diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index cbeb88cad..4fd272927 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -191,7 +191,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1147, Value: 0}, {ID: 1149, Value: 20}, {ID: 1152, Value: 1130}, - {ID: 1153, Value: 0}, {ID: 1154, Value: 0}, {ID: 1155, Value: 0}, {ID: 1158, Value: 1}, @@ -589,6 +588,12 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{1144, 0}) } + if s.server.erupeConfig.GameplayOptions.EnableNierEvent { + tuneValues = append(tuneValues, tuneValue{1153, 1}) + } else { + tuneValues = append(tuneValues, tuneValue{1153, 0}) + } + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) From d243a8c598b6ac87121a263c667ea415d4642ca1 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 17 May 2023 22:18:18 +1000 Subject: [PATCH 09/99] add customisable tune values --- config.json | 3 ++ config/config.go | 31 ++++++------ server/channelserver/handlers_quest.go | 69 ++++++-------------------- 3 files changed, 36 insertions(+), 67 deletions(-) diff --git a/config.json b/config.json index b057d1700..ea2deb1fb 100644 --- a/config.json +++ b/config.json @@ -44,6 +44,9 @@ "MezfesSoloTickets": 10, "MezfesGroupTickets": 4, "GUrgentRate": 10, + "GRPMultiplier": 1.00, + "GSRPMultiplier": 1.00, + "GZennyMultiplier": 1.00, "EnableHiganjimaEvent": false, "EnableNierEvent": false }, diff --git a/config/config.go b/config/config.go index 7666a069b..c7740b8e5 100644 --- a/config/config.go +++ b/config/config.go @@ -61,20 +61,23 @@ type SaveDumpOptions struct { // GameplayOptions has various gameplay modifiers type GameplayOptions struct { - FeaturedWeapons int // Number of Active Feature weapons to generate daily - MaximumNP int // Maximum number of NP held by a player - MaximumRP uint16 // Maximum number of RP held by a player - DisableLoginBoost bool // Disables the Login Boost system - DisableBoostTime bool // Disables the daily NetCafe Boost Time - BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for - GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking - BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily - DailyQuestAllowance uint32 // Number of Daily Quests to allow daily - MezfesSoloTickets uint32 // Number of solo tickets given weekly - MezfesGroupTickets uint32 // Number of group tickets given weekly - GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning - EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar - EnableNierEvent bool // Enables the Nier event in the Rasta Bar + FeaturedWeapons int // Number of Active Feature weapons to generate daily + MaximumNP int // Maximum number of NP held by a player + MaximumRP uint16 // Maximum number of RP held by a player + DisableLoginBoost bool // Disables the Login Boost system + DisableBoostTime bool // Disables the daily NetCafe Boost Time + BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for + GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking + BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily + DailyQuestAllowance uint32 // Number of Daily Quests to allow daily + MezfesSoloTickets uint32 // Number of solo tickets given weekly + MezfesGroupTickets uint32 // Number of group tickets given weekly + GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning + GRPMultiplier float32 // Adjusts the multiplier of G Rank Points rewarded for quest completion + GSRPMultiplier float32 // Adjusts the multiplier of G Skill Rank Points rewarded for quest completion + GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion + EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar + EnableNierEvent bool // Enables the Nier event in the Rasta Bar } // Discord holds the discord integration config. diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 4fd272927..9be713ae7 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -240,58 +240,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3023, Value: 100}, {ID: 3024, Value: 100}, {ID: 3025, Value: 100}, - {ID: 3026, Value: 100}, - {ID: 3027, Value: 100}, - {ID: 3028, Value: 100}, - {ID: 3029, Value: 100}, - {ID: 3030, Value: 100}, - {ID: 3031, Value: 100}, - {ID: 3032, Value: 100}, - {ID: 3033, Value: 100}, - {ID: 3034, Value: 100}, - {ID: 3035, Value: 100}, - {ID: 3036, Value: 100}, - {ID: 3037, Value: 100}, - {ID: 3038, Value: 100}, - {ID: 3039, Value: 100}, - {ID: 3040, Value: 100}, - {ID: 3041, Value: 100}, - {ID: 3042, Value: 100}, - {ID: 3043, Value: 100}, - {ID: 3044, Value: 100}, - {ID: 3045, Value: 100}, - {ID: 3046, Value: 100}, - {ID: 3047, Value: 100}, - {ID: 3048, Value: 100}, - {ID: 3049, Value: 100}, - {ID: 3050, Value: 100}, - {ID: 3051, Value: 100}, - {ID: 3052, Value: 100}, - {ID: 3053, Value: 100}, - {ID: 3054, Value: 100}, - {ID: 3055, Value: 100}, - {ID: 3056, Value: 100}, - {ID: 3057, Value: 100}, - {ID: 3058, Value: 100}, - {ID: 3059, Value: 100}, - {ID: 3060, Value: 100}, - {ID: 3061, Value: 100}, - {ID: 3062, Value: 100}, - {ID: 3063, Value: 100}, - {ID: 3064, Value: 100}, - {ID: 3078, Value: 100}, - {ID: 3079, Value: 100}, - {ID: 3080, Value: 100}, - {ID: 3081, Value: 100}, - {ID: 3082, Value: 100}, - {ID: 3083, Value: 100}, - {ID: 3084, Value: 100}, - {ID: 3085, Value: 100}, - {ID: 3086, Value: 100}, - {ID: 3087, Value: 100}, - {ID: 3088, Value: 100}, - {ID: 3089, Value: 100}, - {ID: 3090, Value: 100}, {ID: 3104, Value: 100}, {ID: 3105, Value: 100}, {ID: 3106, Value: 100}, @@ -594,13 +542,28 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{1153, 0}) } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3026, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplier * 100)}) + } + + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3039, uint16(s.server.erupeConfig.GameplayOptions.GSRPMultiplier * 100)}) + } + + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3052, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplier * 100)}) + } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3078, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplier * 100)}) + } + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) for i := range tuneValues { bf.WriteUint16(tuneValues[i].ID ^ offset) bf.WriteUint16(offset) - bf.WriteUint32(0xD4D4D400) + bf.WriteBytes(make([]byte, 4)) bf.WriteUint16(tuneValues[i].Value ^ offset) } From 7d7da7e146685a76807b1c51eec6fd4d309fb099 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 17 May 2023 22:32:20 +1000 Subject: [PATCH 10/99] add customisable tune values --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_quest.go | 33 ++++++-------------------- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/config.json b/config.json index ea2deb1fb..1e8e2ebce 100644 --- a/config.json +++ b/config.json @@ -47,6 +47,7 @@ "GRPMultiplier": 1.00, "GSRPMultiplier": 1.00, "GZennyMultiplier": 1.00, + "MaterialMultiplier": 1.00, "EnableHiganjimaEvent": false, "EnableNierEvent": false }, diff --git a/config/config.go b/config/config.go index c7740b8e5..18ff33ccb 100644 --- a/config/config.go +++ b/config/config.go @@ -76,6 +76,7 @@ type GameplayOptions struct { GRPMultiplier float32 // Adjusts the multiplier of G Rank Points rewarded for quest completion GSRPMultiplier float32 // Adjusts the multiplier of G Skill Rank Points rewarded for quest completion GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion + MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar } diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 9be713ae7..dea2d1486 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -240,32 +240,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3023, Value: 100}, {ID: 3024, Value: 100}, {ID: 3025, Value: 100}, - {ID: 3104, Value: 100}, - {ID: 3105, Value: 100}, - {ID: 3106, Value: 100}, - {ID: 3107, Value: 100}, - {ID: 3108, Value: 100}, - {ID: 3109, Value: 100}, - {ID: 3110, Value: 100}, - {ID: 3111, Value: 100}, - {ID: 3112, Value: 100}, - {ID: 3113, Value: 100}, - {ID: 3114, Value: 100}, - {ID: 3115, Value: 100}, - {ID: 3116, Value: 100}, - {ID: 3130, Value: 100}, - {ID: 3131, Value: 100}, - {ID: 3132, Value: 100}, - {ID: 3133, Value: 100}, - {ID: 3134, Value: 100}, - {ID: 3135, Value: 100}, - {ID: 3136, Value: 100}, - {ID: 3137, Value: 100}, - {ID: 3138, Value: 100}, - {ID: 3139, Value: 100}, - {ID: 3140, Value: 100}, - {ID: 3141, Value: 100}, - {ID: 3142, Value: 100}, {ID: 3156, Value: 0}, {ID: 3157, Value: 0}, {ID: 3158, Value: 0}, @@ -557,6 +531,13 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{i + 3078, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplier * 100)}) } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3104, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplier * 100)}) + } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3130, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplier * 100)}) + } + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) From f40196b530449d4cb213870680492b9dd32e02c2 Mon Sep 17 00:00:00 2001 From: wish Date: Tue, 23 May 2023 21:53:53 +1000 Subject: [PATCH 11/99] add EarthStatusOverride --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers.go | 22 ++++++++++------------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config.json b/config.json index fb6c27348..f76b172f4 100644 --- a/config.json +++ b/config.json @@ -26,6 +26,7 @@ "MezFesAlt": false, "DisableTokenCheck": false, "QuestDebugTools": false, + "EarthStatusOverride": 0, "SaveDumps": { "Enabled": true, "OutputDir": "savedata" diff --git a/config/config.go b/config/config.go index 5c9ed3750..6ca3b431e 100644 --- a/config/config.go +++ b/config/config.go @@ -51,6 +51,7 @@ type DevModeOptions struct { MezFesAlt bool // Swaps out Volpakkun for Tokotoko DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) QuestDebugTools bool // Enable various quest debug logs + EarthStatusOverride int32 SaveDumps SaveDumpOptions } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index dc285d9aa..95b2ddde3 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1608,18 +1608,16 @@ func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) - - // TODO(Andoryuuta): Track down format for this data, - // it can somehow be parsed as 8*uint32 chunks if the header is right. - /* - BEFORE ack-refactor: - resp := byteframe.NewByteFrame() - resp.WriteUint32(0) - resp.WriteUint32(0) - - s.QueueAck(pkt.AckHandle, resp.Data()) - */ - doAckBufSucceed(s, pkt.AckHandle, []byte{}) + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start + bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End + bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) + bf.WriteInt32(21) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {} From 99919d0243411d30c2f1a5f0b434911f773312d0 Mon Sep 17 00:00:00 2001 From: wish Date: Tue, 23 May 2023 21:55:32 +1000 Subject: [PATCH 12/99] remove unused value --- server/channelserver/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 95b2ddde3..454894cf1 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1612,7 +1612,7 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) - bf.WriteInt32(21) + bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) From e814bfec688d27c93d25df04fa4f1e4ac74a3b77 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 07:29:10 +1000 Subject: [PATCH 13/99] add DisableRoad GameplayOption --- config.json | 3 ++- config/config.go | 1 + server/channelserver/handlers_quest.go | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index bd7f46828..81afee12a 100644 --- a/config.json +++ b/config.json @@ -50,7 +50,8 @@ "GZennyMultiplier": 1.00, "MaterialMultiplier": 1.00, "EnableHiganjimaEvent": false, - "EnableNierEvent": false + "EnableNierEvent": false, + "DisableRoad": false }, "Discord": { "Enabled": false, diff --git a/config/config.go b/config/config.go index 0dde81c10..34a52ca12 100644 --- a/config/config.go +++ b/config/config.go @@ -80,6 +80,7 @@ type GameplayOptions struct { MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar + DisableRoad bool // Disables the Hunting Road } // Discord holds the discord integration config. diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index dea2d1486..c01e76a36 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -192,7 +192,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1149, Value: 20}, {ID: 1152, Value: 1130}, {ID: 1154, Value: 0}, - {ID: 1155, Value: 0}, {ID: 1158, Value: 1}, {ID: 1160, Value: 300}, {ID: 1162, Value: 1}, @@ -516,6 +515,12 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{1153, 0}) } + if s.server.erupeConfig.GameplayOptions.DisableRoad { + tuneValues = append(tuneValues, tuneValue{1155, 1}) + } else { + tuneValues = append(tuneValues, tuneValue{1155, 0}) + } + for i := uint16(0); i < 13; i++ { tuneValues = append(tuneValues, tuneValue{i + 3026, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplier * 100)}) } From 4c5c7b1c94a0519fc36bac5460234ee07ff7bcad Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 12:00:05 +1000 Subject: [PATCH 14/99] add ExtraCarves GameplayOption --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_quest.go | 65 ++++++-------------------- 3 files changed, 15 insertions(+), 52 deletions(-) diff --git a/config.json b/config.json index 81afee12a..be735b144 100644 --- a/config.json +++ b/config.json @@ -49,6 +49,7 @@ "GSRPMultiplier": 1.00, "GZennyMultiplier": 1.00, "MaterialMultiplier": 1.00, + "ExtraCarves": 0, "EnableHiganjimaEvent": false, "EnableNierEvent": false, "DisableRoad": false diff --git a/config/config.go b/config/config.go index 34a52ca12..7ec8ae74c 100644 --- a/config/config.go +++ b/config/config.go @@ -78,6 +78,7 @@ type GameplayOptions struct { GSRPMultiplier float32 // Adjusts the multiplier of G Skill Rank Points rewarded for quest completion GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion + ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar DisableRoad bool // Disables the Hunting Road diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index c01e76a36..7367da875 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -239,58 +239,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3023, Value: 100}, {ID: 3024, Value: 100}, {ID: 3025, Value: 100}, - {ID: 3156, Value: 0}, - {ID: 3157, Value: 0}, - {ID: 3158, Value: 0}, - {ID: 3159, Value: 0}, - {ID: 3160, Value: 0}, - {ID: 3161, Value: 0}, - {ID: 3162, Value: 0}, - {ID: 3163, Value: 0}, - {ID: 3164, Value: 0}, - {ID: 3165, Value: 0}, - {ID: 3166, Value: 0}, - {ID: 3167, Value: 0}, - {ID: 3168, Value: 0}, - {ID: 3182, Value: 0}, - {ID: 3183, Value: 0}, - {ID: 3184, Value: 0}, - {ID: 3185, Value: 0}, - {ID: 3186, Value: 0}, - {ID: 3187, Value: 0}, - {ID: 3188, Value: 0}, - {ID: 3189, Value: 0}, - {ID: 3190, Value: 0}, - {ID: 3191, Value: 0}, - {ID: 3192, Value: 0}, - {ID: 3193, Value: 0}, - {ID: 3194, Value: 0}, - {ID: 3208, Value: 0}, - {ID: 3209, Value: 0}, - {ID: 3210, Value: 0}, - {ID: 3211, Value: 0}, - {ID: 3212, Value: 0}, - {ID: 3213, Value: 0}, - {ID: 3214, Value: 0}, - {ID: 3215, Value: 0}, - {ID: 3216, Value: 0}, - {ID: 3217, Value: 0}, - {ID: 3218, Value: 0}, - {ID: 3219, Value: 0}, - {ID: 3220, Value: 0}, - {ID: 3234, Value: 0}, - {ID: 3235, Value: 0}, - {ID: 3236, Value: 0}, - {ID: 3237, Value: 0}, - {ID: 3238, Value: 0}, - {ID: 3239, Value: 0}, - {ID: 3240, Value: 0}, - {ID: 3241, Value: 0}, - {ID: 3242, Value: 0}, - {ID: 3243, Value: 0}, - {ID: 3244, Value: 0}, - {ID: 3245, Value: 0}, - {ID: 3246, Value: 0}, {ID: 3286, Value: 200}, {ID: 3287, Value: 200}, {ID: 3288, Value: 200}, @@ -543,6 +491,19 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{i + 3130, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplier * 100)}) } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3156, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3182, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3208, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + } + for i := uint16(0); i < 13; i++ { + tuneValues = append(tuneValues, tuneValue{i + 3234, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + } + offset := uint16(time.Now().Unix()) bf.WriteUint16(offset) bf.WriteUint16(uint16(len(tuneValues))) From 9278bfee1855d27a0a791590dc487010254bb1f8 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 12:00:51 +1000 Subject: [PATCH 15/99] add comments to tune values --- server/channelserver/handlers_quest.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 7367da875..e368739f6 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -140,7 +140,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1023, Value: 8}, {ID: 1024, Value: 150}, {ID: 1025, Value: 1}, - {ID: 1026, Value: 999}, + {ID: 1026, Value: 999}, // get_grank_cap {ID: 1027, Value: 100}, {ID: 1028, Value: 100}, {ID: 1030, Value: 8}, @@ -152,12 +152,12 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1064, Value: 50000}, {ID: 1065, Value: 25000}, {ID: 1066, Value: 25000}, - {ID: 1067, Value: 90}, - {ID: 1068, Value: 80}, - {ID: 1069, Value: 70}, - {ID: 1072, Value: 300}, - {ID: 1073, Value: 300}, - {ID: 1074, Value: 300}, + {ID: 1067, Value: 90}, // get_lobby_member_upper_for_making_room Lv1? + {ID: 1068, Value: 80}, // get_lobby_member_upper_for_making_room Lv2? + {ID: 1069, Value: 70}, // get_lobby_member_upper_for_making_room Lv3? + {ID: 1072, Value: 300}, // get_rate_premium_ravi_tama + {ID: 1073, Value: 300}, // get_rate_premium_ravi_ax_tama + {ID: 1074, Value: 300}, // get_rate_premium_ravi_g_tama {ID: 1078, Value: 0}, {ID: 1079, Value: 1}, {ID: 1080, Value: 1}, From 00d51e3e0bd3a13b02b4165cea0d13edd7173148 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 12:45:28 +1000 Subject: [PATCH 16/99] remove redundant conversion --- server/channelserver/handlers_quest.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index e368739f6..b267c6128 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -492,16 +492,16 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { } for i := uint16(0); i < 13; i++ { - tuneValues = append(tuneValues, tuneValue{i + 3156, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + tuneValues = append(tuneValues, tuneValue{i + 3156, s.server.erupeConfig.GameplayOptions.ExtraCarves}) } for i := uint16(0); i < 13; i++ { - tuneValues = append(tuneValues, tuneValue{i + 3182, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + tuneValues = append(tuneValues, tuneValue{i + 3182, s.server.erupeConfig.GameplayOptions.ExtraCarves}) } for i := uint16(0); i < 13; i++ { - tuneValues = append(tuneValues, tuneValue{i + 3208, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + tuneValues = append(tuneValues, tuneValue{i + 3208, s.server.erupeConfig.GameplayOptions.ExtraCarves}) } for i := uint16(0); i < 13; i++ { - tuneValues = append(tuneValues, tuneValue{i + 3234, uint16(s.server.erupeConfig.GameplayOptions.ExtraCarves)}) + tuneValues = append(tuneValues, tuneValue{i + 3234, s.server.erupeConfig.GameplayOptions.ExtraCarves}) } offset := uint16(time.Now().Unix()) From 4e09726d9785c59625564a3e71725860e1c91d78 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 12:48:11 +1000 Subject: [PATCH 17/99] add EarthStatus override options --- config.json | 2 ++ config/config.go | 32 +++++++++++++++++--------------- server/channelserver/handlers.go | 4 ++-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/config.json b/config.json index be735b144..73df5d53c 100644 --- a/config.json +++ b/config.json @@ -27,6 +27,8 @@ "DisableTokenCheck": false, "QuestDebugTools": false, "EarthStatusOverride": 0, + "EarthIDOverride": 0, + "EarthMonsterOverride": 0, "SaveDumps": { "Enabled": true, "OutputDir": "savedata" diff --git a/config/config.go b/config/config.go index 7ec8ae74c..d5efb9b94 100644 --- a/config/config.go +++ b/config/config.go @@ -38,21 +38,23 @@ type Config struct { // DevModeOptions holds various debug/temporary options for use while developing Erupe. type DevModeOptions struct { - AutoCreateAccount bool // Automatically create accounts if they don't exist - CleanDB bool // Automatically wipes the DB on server reset. - MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. - LogInboundMessages bool // Log all messages sent to the server - LogOutboundMessages bool // Log all messages sent to the clients - MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled - DivaEvent int // Diva Defense event status - FestaEvent int // Hunter's Festa event status - TournamentEvent int // VS Tournament event status - MezFesEvent bool // MezFes status - MezFesAlt bool // Swaps out Volpakkun for Tokotoko - DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) - QuestDebugTools bool // Enable various quest debug logs - EarthStatusOverride int32 - SaveDumps SaveDumpOptions + AutoCreateAccount bool // Automatically create accounts if they don't exist + CleanDB bool // Automatically wipes the DB on server reset. + MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. + LogInboundMessages bool // Log all messages sent to the server + LogOutboundMessages bool // Log all messages sent to the clients + MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled + DivaEvent int // Diva Defense event status + FestaEvent int // Hunter's Festa event status + TournamentEvent int // VS Tournament event status + MezFesEvent bool // MezFes status + MezFesAlt bool // Swaps out Volpakkun for Tokotoko + DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) + QuestDebugTools bool // Enable various quest debug logs + EarthStatusOverride int32 + EarthIDOverride int32 + EarthMonsterOverride int32 + SaveDumps SaveDumpOptions } type SaveDumpOptions struct { diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 454894cf1..70627e957 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1612,8 +1612,8 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) - bf.WriteInt32(0) - bf.WriteInt32(0) + bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride) + bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride) bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) From 64344ee2ee37dcaf2019b09986bee0433fc55e40 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 14:41:35 +1000 Subject: [PATCH 18/99] parse and stub various packets --- network/mhfpacket/msg_mhf_caravan_my_rank.go | 21 +++++-- network/mhfpacket/msg_mhf_caravan_my_score.go | 29 +++++++-- network/mhfpacket/msg_mhf_caravan_ranking.go | 21 +++++-- network/mhfpacket/msg_mhf_get_seibattle.go | 17 +++--- network/mhfpacket/msg_mhf_present_box.go | 8 +-- server/channelserver/handlers_caravan.go | 59 ++++++++++++++++++- server/channelserver/handlers_tower.go | 40 ++++++++++++- 7 files changed, 159 insertions(+), 36 deletions(-) diff --git a/network/mhfpacket/msg_mhf_caravan_my_rank.go b/network/mhfpacket/msg_mhf_caravan_my_rank.go index 3eb0074d4..d3e261caa 100644 --- a/network/mhfpacket/msg_mhf_caravan_my_rank.go +++ b/network/mhfpacket/msg_mhf_caravan_my_rank.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfCaravanMyRank represents the MSG_MHF_CARAVAN_MY_RANK -type MsgMhfCaravanMyRank struct{} +type MsgMhfCaravanMyRank struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID { @@ -18,7 +23,11 @@ func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfCaravanMyRank) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_caravan_my_score.go b/network/mhfpacket/msg_mhf_caravan_my_score.go index bb83d0992..dfa2333b4 100644 --- a/network/mhfpacket/msg_mhf_caravan_my_score.go +++ b/network/mhfpacket/msg_mhf_caravan_my_score.go @@ -1,15 +1,24 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfCaravanMyScore represents the MSG_MHF_CARAVAN_MY_SCORE -type MsgMhfCaravanMyScore struct{} +type MsgMhfCaravanMyScore struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 + Unk3 int32 + Unk4 uint32 + Unk5 int32 + Unk6 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfCaravanMyScore) Opcode() network.PacketID { @@ -18,7 +27,15 @@ func (m *MsgMhfCaravanMyScore) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfCaravanMyScore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadInt32() + m.Unk6 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_caravan_ranking.go b/network/mhfpacket/msg_mhf_caravan_ranking.go index 7b5564bb6..1f86771af 100644 --- a/network/mhfpacket/msg_mhf_caravan_ranking.go +++ b/network/mhfpacket/msg_mhf_caravan_ranking.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfCaravanRanking represents the MSG_MHF_CARAVAN_RANKING -type MsgMhfCaravanRanking struct{} +type MsgMhfCaravanRanking struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfCaravanRanking) Opcode() network.PacketID { @@ -18,7 +23,11 @@ func (m *MsgMhfCaravanRanking) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfCaravanRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_get_seibattle.go b/network/mhfpacket/msg_mhf_get_seibattle.go index 6a7a80380..1398b477d 100644 --- a/network/mhfpacket/msg_mhf_get_seibattle.go +++ b/network/mhfpacket/msg_mhf_get_seibattle.go @@ -1,20 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetSeibattle represents the MSG_MHF_GET_SEIBATTLE type MsgMhfGetSeibattle struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 Unk0 uint8 - Unk1 uint8 - Unk2 uint32 // Some shared ID with MSG_SYS_RECORD_LOG, world ID? + Type uint8 + GuildID uint32 Unk3 uint8 Unk4 uint16 } @@ -28,8 +27,8 @@ func (m *MsgMhfGetSeibattle) Opcode() network.PacketID { func (m *MsgMhfGetSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() - m.Unk2 = bf.ReadUint32() + m.Type = bf.ReadUint8() + m.GuildID = bf.ReadUint32() m.Unk3 = bf.ReadUint8() m.Unk4 = bf.ReadUint16() return nil diff --git a/network/mhfpacket/msg_mhf_present_box.go b/network/mhfpacket/msg_mhf_present_box.go index c3da92e31..d0064799c 100644 --- a/network/mhfpacket/msg_mhf_present_box.go +++ b/network/mhfpacket/msg_mhf_present_box.go @@ -18,8 +18,7 @@ type MsgMhfPresentBox struct { Unk4 uint32 Unk5 uint32 Unk6 uint32 - Unk7 uint32 - Unk8 uint32 + Unk7 []uint32 } // Opcode returns the ID associated with this packet type. @@ -37,8 +36,9 @@ func (m *MsgMhfPresentBox) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientC m.Unk4 = bf.ReadUint32() m.Unk5 = bf.ReadUint32() m.Unk6 = bf.ReadUint32() - m.Unk7 = bf.ReadUint32() - m.Unk8 = bf.ReadUint32() + for i := uint32(0); i < m.Unk2; i++ { + m.Unk7 = append(m.Unk7, bf.ReadUint32()) + } return nil } diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index 86cf73249..87a45ce49 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -2,6 +2,7 @@ package channelserver import ( "encoding/hex" + "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" ) @@ -31,8 +32,60 @@ func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) { doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCaravanMyScore) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) // Entries -func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {} + /* + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteUint32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + */ -func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {} + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCaravanRanking) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) // Entries + + /* RYOUDAN + bf.WriteInt32(1) + bf.WriteUint32(2) + bf.WriteBytes(stringsupport.PaddedString("Test", 26, true)) + */ + + /* PERSONAL + bf.WriteInt32(1) + bf.WriteBytes(stringsupport.PaddedString("Test", 14, true)) + */ + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCaravanMyRank) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) // Entries + + /* + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + */ + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 0a2675812..b4525c93b 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -2,6 +2,7 @@ package channelserver import ( "encoding/hex" + "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" ) @@ -86,12 +87,47 @@ func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) // Entries + + /* + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteUint32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + */ + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPresentBox) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(0) // Entries + + /* + bf.WriteUint32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + */ + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { From 07035775716f35e0dd9db72f77fc11412dc18591 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 14:57:32 +1000 Subject: [PATCH 19/99] fix errors --- server/channelserver/handlers_caravan.go | 2 -- server/channelserver/handlers_tower.go | 16 +++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index 87a45ce49..d2db36243 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -43,8 +43,6 @@ func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { /* bf.WriteInt32(0) bf.WriteInt32(0) - bf.WriteUint32(0) - bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) */ diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index b4525c93b..d5766772b 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -91,16 +91,14 @@ func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket bf.WriteUint32(0) bf.WriteUint32(0) bf.WriteUint32(0) - bf.WriteUint32(0) // Entries + bf.WriteUint32(1) // Entries - /* - bf.WriteInt32(0) - bf.WriteInt32(0) - bf.WriteUint32(0) - bf.WriteInt32(0) - bf.WriteInt32(0) - bf.WriteInt32(0) - */ + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteUint32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } From 430f27cfc38937d074e86be1715d3e6d45c8fc3e Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 16:01:16 +1000 Subject: [PATCH 20/99] decode various Ryoudama packets --- network/mhfpacket/msg_mhf_get_ryoudama.go | 8 +-- network/mhfpacket/msg_mhf_get_tiny_bin.go | 14 ++-- network/mhfpacket/msg_mhf_post_tiny_bin.go | 6 +- server/channelserver/handlers_caravan.go | 77 +++++++++++++++++++--- 4 files changed, 83 insertions(+), 22 deletions(-) diff --git a/network/mhfpacket/msg_mhf_get_ryoudama.go b/network/mhfpacket/msg_mhf_get_ryoudama.go index 2cffc3bdc..91d1566af 100644 --- a/network/mhfpacket/msg_mhf_get_ryoudama.go +++ b/network/mhfpacket/msg_mhf_get_ryoudama.go @@ -11,8 +11,8 @@ import ( // MsgMhfGetRyoudama represents the MSG_MHF_GET_RYOUDAMA type MsgMhfGetRyoudama struct { AckHandle uint32 - Unk0 uint8 - Unk1 uint8 + Request1 uint8 + Request2 uint8 GuildID uint32 Unk3 uint8 } @@ -25,8 +25,8 @@ func (m *MsgMhfGetRyoudama) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetRyoudama) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() + m.Request1 = bf.ReadUint8() + m.Request2 = bf.ReadUint8() m.GuildID = bf.ReadUint32() m.Unk3 = bf.ReadUint8() return nil diff --git a/network/mhfpacket/msg_mhf_get_tiny_bin.go b/network/mhfpacket/msg_mhf_get_tiny_bin.go index 8f76eb1a1..4db9b05b9 100644 --- a/network/mhfpacket/msg_mhf_get_tiny_bin.go +++ b/network/mhfpacket/msg_mhf_get_tiny_bin.go @@ -1,19 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetTinyBin represents the MSG_MHF_GET_TINY_BIN type MsgMhfGetTinyBin struct { // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 - Unk0 uint16 + Unk0 uint8 Unk1 uint8 + Unk2 uint8 } // Opcode returns the ID associated with this packet type. @@ -24,8 +25,9 @@ func (m *MsgMhfGetTinyBin) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() + m.Unk0 = bf.ReadUint8() m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint8() return nil } diff --git a/network/mhfpacket/msg_mhf_post_tiny_bin.go b/network/mhfpacket/msg_mhf_post_tiny_bin.go index 7c709d1e4..dd464d18d 100644 --- a/network/mhfpacket/msg_mhf_post_tiny_bin.go +++ b/network/mhfpacket/msg_mhf_post_tiny_bin.go @@ -11,9 +11,10 @@ import ( // MsgMhfPostTinyBin represents the MSG_MHF_POST_TINY_BIN type MsgMhfPostTinyBin struct { AckHandle uint32 - Unk0 uint16 + Unk0 uint8 Unk1 uint8 Unk2 uint8 + Unk3 uint8 Data []byte } @@ -25,9 +26,10 @@ func (m *MsgMhfPostTinyBin) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() + m.Unk0 = bf.ReadUint8() m.Unk1 = bf.ReadUint8() m.Unk2 = bf.ReadUint8() + m.Unk3 = bf.ReadUint8() m.Data = bf.ReadBytes(uint(bf.ReadUint16())) return nil } diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index d2db36243..fcd77dfa9 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -1,22 +1,79 @@ package channelserver import ( - "encoding/hex" "erupe-ce/common/byteframe" + "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" ) +type RyoudamaReward struct { + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 + Unk3 uint16 + Unk4 uint16 + Unk5 uint16 +} + +type RyoudamaKeyScore struct { + Unk0 uint8 + Unk1 int32 +} + +type RyoudamaCharInfo struct { + CID uint32 + Unk0 int32 + Name string +} + +type RyoudamaBoostInfo struct { + Unk0 uint32 + Unk1 uint32 +} + +type Ryoudama struct { + Reward []RyoudamaReward + KeyScore []RyoudamaKeyScore + CharInfo []RyoudamaCharInfo + BoostInfo []RyoudamaBoostInfo + Score []int32 +} + func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRyoudama) - // likely guild related - // REQ: 00 04 13 53 8F 18 00 - // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 01 FE 4E - // REQ: 00 06 13 53 8F 18 00 - // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 - // REQ: 00 05 13 53 8F 18 00 - // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 0E 2A 15 9E CC 00 00 00 01 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 1E 55 B0 2F 00 00 00 01 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 2A 15 9E CC 00 00 00 02 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 03 D5 30 56 00 00 00 02 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 3F 57 76 9F 00 00 00 03 93 56 92 6E 96 B3 97 70 00 00 00 00 00 00 38 D9 0E C4 00 00 00 03 87 64 83 78 83 42 00 00 00 00 00 00 00 00 23 F3 B9 77 00 00 00 04 82 B3 82 CC 82 DC 82 E9 81 99 00 00 00 00 3F 1B 17 9C 00 00 00 04 82 B1 82 A4 82 BD 00 00 00 00 00 00 00 00 00 B9 F9 C0 00 00 00 05 82 CD 82 E9 82 A9 00 00 00 00 00 00 00 00 23 9F 9A EA 00 00 00 05 83 70 83 62 83 4C 83 83 83 49 00 00 00 00 38 D9 0E C4 00 00 00 06 87 64 83 78 83 42 00 00 00 00 00 00 00 00 1E 55 B0 2F 00 00 00 06 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 03 D5 30 56 00 00 00 07 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 02 D3 B8 77 00 00 00 07 6F 77 6C 32 35 32 35 00 00 00 00 00 00 00 - data, _ := hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) + bf.WriteUint32(0) + bf.WriteUint32(0) + + ryoudama := Ryoudama{ + Score: []int32{0}, + } + switch pkt.Request2 { + case 4: + bf.WriteUint32(uint32(len(ryoudama.Score))) + for _, score := range ryoudama.Score { + bf.WriteInt32(score) + } + case 5: + bf.WriteUint32(uint32(len(ryoudama.CharInfo))) + for _, info := range ryoudama.CharInfo { + bf.WriteUint32(info.CID) + bf.WriteInt32(info.Unk0) + bf.WriteBytes(stringsupport.PaddedString(info.Name, 14, true)) + } + case 6: + bf.WriteUint32(uint32(len(ryoudama.BoostInfo))) + for _, info := range ryoudama.BoostInfo { + bf.WriteUint32(info.Unk0) + bf.WriteUint32(info.Unk1) + } + default: + bf.WriteUint32(0) + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} From acdd9cf0db6194eb1e4d2c2a584a9be299c74e3e Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 28 May 2023 16:07:06 +1000 Subject: [PATCH 21/99] decode various Ryoudama packets --- server/channelserver/handlers_caravan.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index fcd77dfa9..547019e68 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -4,6 +4,7 @@ import ( "erupe-ce/common/byteframe" "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" + "time" ) type RyoudamaReward struct { @@ -27,8 +28,8 @@ type RyoudamaCharInfo struct { } type RyoudamaBoostInfo struct { - Unk0 uint32 - Unk1 uint32 + Start time.Time + End time.Time } type Ryoudama struct { @@ -47,9 +48,7 @@ func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) bf.WriteUint32(0) - ryoudama := Ryoudama{ - Score: []int32{0}, - } + ryoudama := Ryoudama{Score: []int32{0}} switch pkt.Request2 { case 4: bf.WriteUint32(uint32(len(ryoudama.Score))) @@ -66,8 +65,8 @@ func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { case 6: bf.WriteUint32(uint32(len(ryoudama.BoostInfo))) for _, info := range ryoudama.BoostInfo { - bf.WriteUint32(info.Unk0) - bf.WriteUint32(info.Unk1) + bf.WriteUint32(uint32(info.Start.Unix())) + bf.WriteUint32(uint32(info.End.Unix())) } default: bf.WriteUint32(0) From 3d0316e6697376ab6150c319cd8fb29ebf2d65e0 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 12:29:08 +1000 Subject: [PATCH 22/99] add GCPMultiplier GameplayOption --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_quest.go | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 73df5d53c..69fc89689 100644 --- a/config.json +++ b/config.json @@ -47,6 +47,7 @@ "MezfesSoloTickets": 10, "MezfesGroupTickets": 4, "GUrgentRate": 10, + "GCPMultiplier": 1.00, "GRPMultiplier": 1.00, "GSRPMultiplier": 1.00, "GZennyMultiplier": 1.00, diff --git a/config/config.go b/config/config.go index d5efb9b94..4b48fc76c 100644 --- a/config/config.go +++ b/config/config.go @@ -76,6 +76,7 @@ type GameplayOptions struct { MezfesSoloTickets uint32 // Number of solo tickets given weekly MezfesGroupTickets uint32 // Number of group tickets given weekly GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning + GCPMultiplier float32 // Adjusts the multiplier of GCP rewarded for quest completion GRPMultiplier float32 // Adjusts the multiplier of G Rank Points rewarded for quest completion GSRPMultiplier float32 // Adjusts the multiplier of G Skill Rank Points rewarded for quest completion GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index b267c6128..09a44e71f 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -135,7 +135,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1013, Value: 300}, {ID: 1014, Value: 200}, {ID: 1015, Value: 200}, - {ID: 1020, Value: 100}, {ID: 1021, Value: 400}, {ID: 1023, Value: 8}, {ID: 1024, Value: 150}, @@ -449,6 +448,8 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 3584, Value: 0}, } + tuneValues = append(tuneValues, tuneValue{1020, uint16(s.server.erupeConfig.GameplayOptions.GCPMultiplier * 100)}) + tuneValues = append(tuneValues, tuneValue{1029, s.server.erupeConfig.GameplayOptions.GUrgentRate}) if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent { From 813dc5747b4c76f7616c54974a2492e169abfe18 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 13:33:10 +1000 Subject: [PATCH 23/99] add DisableHunterNavi GameplayOption --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_quest.go | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/config.json b/config.json index 69fc89689..30164ec4c 100644 --- a/config.json +++ b/config.json @@ -53,6 +53,7 @@ "GZennyMultiplier": 1.00, "MaterialMultiplier": 1.00, "ExtraCarves": 0, + "DisableHunterNavi": false, "EnableHiganjimaEvent": false, "EnableNierEvent": false, "DisableRoad": false diff --git a/config/config.go b/config/config.go index 4b48fc76c..f52cc73c5 100644 --- a/config/config.go +++ b/config/config.go @@ -82,6 +82,7 @@ type GameplayOptions struct { GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses + DisableHunterNavi bool // Disables the Hunter Navi EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar DisableRoad bool // Disables the Hunting Road diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 09a44e71f..aea016b8d 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -452,6 +452,10 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{1029, s.server.erupeConfig.GameplayOptions.GUrgentRate}) + if s.server.erupeConfig.GameplayOptions.DisableHunterNavi { + tuneValues = append(tuneValues, tuneValue{1037, 1}) + } + if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent { tuneValues = append(tuneValues, tuneValue{1144, 1}) } else { From f52c9e58fcf385d8125bdbc80d98a24ecec59428 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 14:01:07 +1000 Subject: [PATCH 24/99] add comments --- server/channelserver/handlers_quest.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index aea016b8d..162148c20 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -144,6 +144,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1028, Value: 100}, {ID: 1030, Value: 8}, {ID: 1031, Value: 100}, + {ID: 1032, Value: 0}, // isValid_partner {ID: 1046, Value: 99}, {ID: 1051, Value: 200}, {ID: 1052, Value: 200}, @@ -190,7 +191,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1147, Value: 0}, {ID: 1149, Value: 20}, {ID: 1152, Value: 1130}, - {ID: 1154, Value: 0}, + {ID: 1154, Value: 0}, // isDisabled_object_season {ID: 1158, Value: 1}, {ID: 1160, Value: 300}, {ID: 1162, Value: 1}, From d16600a1f4a1cabd0206e9d197c7d4a8a8a765bb Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 14:50:42 +1000 Subject: [PATCH 25/99] add comments --- server/channelserver/handlers_quest.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 162148c20..e16d7bc08 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -187,8 +187,8 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1104, Value: 10}, {ID: 1106, Value: 0}, {ID: 1145, Value: 200}, - {ID: 1146, Value: 0}, - {ID: 1147, Value: 0}, + {ID: 1146, Value: 0}, // isTower_invisible + {ID: 1147, Value: 0}, // isVenom_playable {ID: 1149, Value: 20}, {ID: 1152, Value: 1130}, {ID: 1154, Value: 0}, // isDisabled_object_season From ba1eea81e7ba4cb783d3406e7464825a57f0d72c Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 16:04:17 +1000 Subject: [PATCH 26/99] prevent save error crashes --- server/channelserver/handlers.go | 2 +- server/channelserver/handlers_character.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 95b2ddde3..1c189f5fb 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -245,7 +245,7 @@ func logoutPlayer(s *Session) { removeSessionFromStage(s) saveData, err := GetCharacterSaveData(s, s.charID) - if err != nil { + if err != nil || saveData == nil { s.logger.Error("Failed to get savedata") return } diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 165580fe7..a53d4c42a 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -81,6 +81,10 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) return nil, err } + if len(saveData.decompSave) < pointerKQF { + return nil, err + } + saveData.updateStructWithSaveData() return saveData, nil From d16acbc824f97ac5103a47e2f5993206f39aa172 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 16:06:19 +1000 Subject: [PATCH 27/99] rewrite default Earth data --- server/channelserver/handlers.go | 140 +++++++++++++++++-------------- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 70627e957..3f19cd99c 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1609,8 +1609,8 @@ func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) bf := byteframe.NewByteFrame() - bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start - bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End + bf.WriteUint32(uint32(TimeWeekStart().Add(time.Hour * -24).Unix())) // Start + bf.WriteUint32(uint32(TimeWeekNext().Add(time.Hour * 24).Unix())) // End bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride) @@ -1624,71 +1624,42 @@ func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEarthValue) - var earthValues []struct{ Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 } - if pkt.ReqType == 3 { - earthValues = []struct { - Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 - }{ - // TW identical to JP - { - Unk0: 0x03E9, - Unk1: 0x24, - }, - { - Unk0: 0x2329, - Unk1: 0x03, - }, - { - Unk0: 0x232A, - Unk1: 0x0A, - Unk2: 0x012C, - }, + type EarthValues struct { + Value []uint32 + } + + var earthValues []EarthValues + switch pkt.ReqType { + case 1: + earthValues = []EarthValues{ + {[]uint32{1, 312, 0, 0, 0, 0}}, + {[]uint32{2, 99, 0, 0, 0, 0}}, } - } else if pkt.ReqType == 2 { - earthValues = []struct { - Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 - }{ - // JP response was empty - { - Unk0: 0x01, - Unk1: 0x168B, - }, - { - Unk0: 0x02, - Unk1: 0x0737, - }, + case 2: + earthValues = []EarthValues{ + {[]uint32{1, 5771, 0, 0, 0, 0}}, + {[]uint32{2, 1847, 0, 0, 0, 0}}, } - } else if pkt.ReqType == 1 { - earthValues = []struct { - Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 - }{ - // JP simply sent 01 and 02 respectively - { - Unk0: 0x01, - Unk1: 0x0138, - }, - { - Unk0: 0x02, - Unk1: 0x63, - }, + case 3: + earthValues = []EarthValues{ + {[]uint32{1001, 36, 0, 0, 0, 0}}, + {[]uint32{9001, 3, 0, 0, 0, 0}}, + {[]uint32{9002, 10, 300, 0, 0, 0}}, } } - resp := byteframe.NewByteFrame() - resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. - resp.WriteUint32(0) // Unk - resp.WriteUint32(0) // Unk - resp.WriteUint32(uint32(len(earthValues))) // value count - for _, v := range earthValues { - resp.WriteUint32(v.Unk0) - resp.WriteUint32(v.Unk1) - resp.WriteUint32(v.Unk2) - resp.WriteUint32(v.Unk3) - resp.WriteUint32(v.Unk4) - resp.WriteUint32(v.Unk5) + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(uint32(len(earthValues))) + for _, i := range earthValues { + for _, j := range i.Value { + bf.WriteUint32(j) + } } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} @@ -1703,7 +1674,54 @@ func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetSeibattle) - stubGetNoResults(s, pkt.AckHandle) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) // Unk + bf.WriteUint32(0) // Unk + bf.WriteUint32(0) // Unk + bf.WriteUint32(1) // Entries + + switch pkt.Type { + case 1: // Timetable + bf.Seek(-4, 1) + bf.WriteUint32(3) + + bf.WriteUint32(uint32(TimeMidnight().Unix())) + bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) + + bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) + bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) + + bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) + bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 24).Unix())) + case 2: // Reward + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 16)) + return + case 3: // Key score? + bf.WriteUint8(0) + bf.WriteInt32(0) + case 4: // Career? + bf.WriteUint16(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + case 5: // Opponent? + bf.WriteInt32(1) + bf.WriteInt8(1) + case 6: // Convention result? + bf.WriteUint32(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + case 7: // Char score? + bf.WriteUint32(0) + case 8: // Cur result? + bf.WriteUint32(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + bf.WriteUint16(0) + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} From fbecbfa5712a29cb30f874361ba25139c0f6f095 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 10 Jun 2023 23:09:50 +1000 Subject: [PATCH 28/99] rewrite Earth packet handlers --- network/mhfpacket/msg_mhf_get_gem_info.go | 18 +- server/channelserver/handlers.go | 201 ++++++++++++++++------ server/channelserver/handlers_caravan.go | 50 ++---- server/channelserver/handlers_tower.go | 126 +++++++------- 4 files changed, 240 insertions(+), 155 deletions(-) diff --git a/network/mhfpacket/msg_mhf_get_gem_info.go b/network/mhfpacket/msg_mhf_get_gem_info.go index 36eb7948e..28638bfd2 100644 --- a/network/mhfpacket/msg_mhf_get_gem_info.go +++ b/network/mhfpacket/msg_mhf_get_gem_info.go @@ -11,8 +11,13 @@ import ( // MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO type MsgMhfGetGemInfo struct { AckHandle uint32 - Unk uint32 - Unk1 []byte + Unk0 uint32 + Unk1 uint32 + Unk2 int32 + Unk3 int32 + Unk4 int32 + Unk5 int32 + Unk6 int32 } // Opcode returns the ID associated with this packet type. @@ -23,8 +28,13 @@ func (m *MsgMhfGetGemInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk = bf.ReadUint32() - m.Unk1 = bf.ReadBytes(24) + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadInt32() + m.Unk5 = bf.ReadInt32() + m.Unk6 = bf.ReadInt32() return nil } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 3f19cd99c..26cd3355b 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -38,6 +38,18 @@ func stubGetNoResults(s *Session, ackHandle uint32) { doAckBufSucceed(s, ackHandle, resp.Data()) } +func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) { + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint32(uint32(len(data))) + for i := range data { + bf.WriteBytes(data[i].Data()) + } + doAckBufSucceed(s, ackHandle, bf.Data()) +} + func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { s.QueueSendMHF(&mhfpacket.MsgSysAck{ AckHandle: ackHandle, @@ -1648,18 +1660,15 @@ func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { } } - bf := byteframe.NewByteFrame() - bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(uint32(len(earthValues))) + var data []*byteframe.ByteFrame for _, i := range earthValues { + bf := byteframe.NewByteFrame() for _, j := range i.Value { bf.WriteUint32(j) } + data = append(data, bf) } - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} @@ -1672,56 +1681,142 @@ func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} +type SeibattleTimetable struct { + Start time.Time + End time.Time +} + +type SeibattleKeyScore struct { + Unk0 uint8 + Unk1 int32 +} + +type SeibattleCareer struct { + Unk0 uint16 + Unk1 uint16 + Unk2 uint16 +} + +type SeibattleOpponent struct { + Unk0 int32 + Unk1 int8 +} + +type SeibattleConventionResult struct { + Unk0 uint32 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 + Unk4 uint16 +} + +type SeibattleCharScore struct { + Unk0 uint32 +} + +type SeibattleCurResult struct { + Unk0 uint32 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 +} + +type Seibattle struct { + Timetable []SeibattleTimetable + KeyScore []SeibattleKeyScore + Career []SeibattleCareer + Opponent []SeibattleOpponent + ConventionResult []SeibattleConventionResult + CharScore []SeibattleCharScore + CurResult []SeibattleCurResult +} + func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetSeibattle) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) // Unk - bf.WriteUint32(0) // Unk - bf.WriteUint32(0) // Unk - bf.WriteUint32(1) // Entries - - switch pkt.Type { - case 1: // Timetable - bf.Seek(-4, 1) - bf.WriteUint32(3) - - bf.WriteUint32(uint32(TimeMidnight().Unix())) - bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) - - bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) - bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) - - bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) - bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 24).Unix())) - case 2: // Reward - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 16)) - return - case 3: // Key score? - bf.WriteUint8(0) - bf.WriteInt32(0) - case 4: // Career? - bf.WriteUint16(0) - bf.WriteUint16(0) - bf.WriteUint16(0) - case 5: // Opponent? - bf.WriteInt32(1) - bf.WriteInt8(1) - case 6: // Convention result? - bf.WriteUint32(0) - bf.WriteUint16(0) - bf.WriteUint16(0) - bf.WriteUint16(0) - bf.WriteUint16(0) - case 7: // Char score? - bf.WriteUint32(0) - case 8: // Cur result? - bf.WriteUint32(0) - bf.WriteUint16(0) - bf.WriteUint16(0) - bf.WriteUint16(0) + var data []*byteframe.ByteFrame + seibattle := Seibattle{ + Timetable: []SeibattleTimetable{ + {TimeMidnight(), TimeMidnight().Add(time.Hour * 8)}, + {TimeMidnight().Add(time.Hour * 8), TimeMidnight().Add(time.Hour * 16)}, + {TimeMidnight().Add(time.Hour * 16), TimeMidnight().Add(time.Hour * 24)}, + }, + KeyScore: []SeibattleKeyScore{ + {0, 0}, + }, + Career: []SeibattleCareer{ + {0, 0, 0}, + }, + Opponent: []SeibattleOpponent{ + {1, 1}, + }, + ConventionResult: []SeibattleConventionResult{ + {0, 0, 0, 0, 0}, + }, + CharScore: []SeibattleCharScore{ + {0}, + }, + CurResult: []SeibattleCurResult{ + {0, 0, 0, 0}, + }, } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + switch pkt.Type { + case 1: + for _, timetable := range seibattle.Timetable { + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(timetable.Start.Unix())) + bf.WriteUint32(uint32(timetable.End.Unix())) + data = append(data, bf) + } + case 3: // Key score? + for _, keyScore := range seibattle.KeyScore { + bf := byteframe.NewByteFrame() + bf.WriteUint8(keyScore.Unk0) + bf.WriteInt32(keyScore.Unk1) + data = append(data, bf) + } + case 4: // Career? + for _, career := range seibattle.Career { + bf := byteframe.NewByteFrame() + bf.WriteUint16(career.Unk0) + bf.WriteUint16(career.Unk1) + bf.WriteUint16(career.Unk2) + data = append(data, bf) + } + case 5: // Opponent? + for _, opponent := range seibattle.Opponent { + bf := byteframe.NewByteFrame() + bf.WriteInt32(opponent.Unk0) + bf.WriteInt8(opponent.Unk1) + data = append(data, bf) + } + case 6: // Convention result? + for _, conventionResult := range seibattle.ConventionResult { + bf := byteframe.NewByteFrame() + bf.WriteUint32(conventionResult.Unk0) + bf.WriteUint16(conventionResult.Unk1) + bf.WriteUint16(conventionResult.Unk2) + bf.WriteUint16(conventionResult.Unk3) + bf.WriteUint16(conventionResult.Unk4) + data = append(data, bf) + } + case 7: // Char score? + for _, charScore := range seibattle.CharScore { + bf := byteframe.NewByteFrame() + bf.WriteUint32(charScore.Unk0) + data = append(data, bf) + } + case 8: // Cur result? + for _, curResult := range seibattle.CurResult { + bf := byteframe.NewByteFrame() + bf.WriteUint32(curResult.Unk0) + bf.WriteUint16(curResult.Unk1) + bf.WriteUint16(curResult.Unk2) + bf.WriteUint16(curResult.Unk3) + data = append(data, bf) + } + } + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index 547019e68..c90f44812 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -42,37 +42,32 @@ type Ryoudama struct { func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRyoudama) - - bf := byteframe.NewByteFrame() - bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) - bf.WriteUint32(0) - bf.WriteUint32(0) - + var data []*byteframe.ByteFrame ryoudama := Ryoudama{Score: []int32{0}} switch pkt.Request2 { case 4: - bf.WriteUint32(uint32(len(ryoudama.Score))) for _, score := range ryoudama.Score { + bf := byteframe.NewByteFrame() bf.WriteInt32(score) + data = append(data, bf) } case 5: - bf.WriteUint32(uint32(len(ryoudama.CharInfo))) for _, info := range ryoudama.CharInfo { + bf := byteframe.NewByteFrame() bf.WriteUint32(info.CID) bf.WriteInt32(info.Unk0) bf.WriteBytes(stringsupport.PaddedString(info.Name, 14, true)) + data = append(data, bf) } case 6: - bf.WriteUint32(uint32(len(ryoudama.BoostInfo))) for _, info := range ryoudama.BoostInfo { + bf := byteframe.NewByteFrame() bf.WriteUint32(uint32(info.Start.Unix())) bf.WriteUint32(uint32(info.End.Unix())) + data = append(data, bf) } - default: - bf.WriteUint32(0) } - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} @@ -90,30 +85,19 @@ func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCaravanMyScore) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) // Entries - + var data []*byteframe.ByteFrame /* bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) */ - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCaravanRanking) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) // Entries - + var data []*byteframe.ByteFrame /* RYOUDAN bf.WriteInt32(1) bf.WriteUint32(2) @@ -124,22 +108,16 @@ func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(1) bf.WriteBytes(stringsupport.PaddedString("Test", 14, true)) */ - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCaravanMyRank) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) // Entries - + var data []*byteframe.ByteFrame /* bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) */ - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index d5766772b..1bec51dde 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -8,50 +8,43 @@ import ( func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) - var data []byte - var err error - /* - type: - 1 == TOWER_RANK_POINT, - 2 == GET_OWN_TOWER_SKILL - 3 == GET_OWN_TOWER_LEVEL_V3 - 4 == TOWER_TOUHA_HISTORY - 5 = ? + var data []*byteframe.ByteFrame + type TowerInfo struct { + TRP []uint64 + TowerSkill [][]byte // 132 bytes + TowerHistory [][]byte // 20 bytes + } - [] = type - req - resp + towerInfo := TowerInfo{ + TRP: []uint64{0}, + TowerSkill: [][]byte{make([]byte, 132)}, + TowerHistory: [][]byte{make([]byte, 20)}, + } - 01 1d 01 fc 00 09 [00 00 00 01] 00 00 00 02 00 00 00 00 - 00 12 01 fc 00 09 01 00 00 18 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 + // Example data + // towerInfo.TowerSkill[0], _ = hex.DecodeString("0000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - 01 1d 01 fc 00 0a [00 00 00 02] 00 00 00 00 00 00 00 00 - 00 12 01 fc 00 0a 01 00 00 94 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - 01 1d 01 ff 00 0f [00 00 00 04] 00 00 00 00 00 00 00 00 - 00 12 01 ff 00 0f 01 00 00 24 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - 01 1d 01 fc 00 0b [00 00 00 05] 00 00 00 00 00 00 00 00 - 00 12 01 fc 00 0b 01 00 00 10 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 00 - */ switch pkt.InfoType { - case mhfpacket.TowerInfoTypeTowerRankPoint: - data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") - case mhfpacket.TowerInfoTypeGetOwnTowerSkill: - //data, err = hex.DecodeString("0A218EAD000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - data, err = hex.DecodeString("0A218EAD0000000000000000000000010000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - case mhfpacket.TowerInfoTypeGetOwnTowerLevelV3: - panic("No known response values for GetOwnTowerLevelV3") - case mhfpacket.TowerInfoTypeTowerTouhaHistory: - data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000000000000000000000000000") - case mhfpacket.TowerInfoTypeUnk5: - data, err = hex.DecodeString("0A218EAD000000000000000000000000") + case 1: + for _, trp := range towerInfo.TRP { + bf := byteframe.NewByteFrame() + bf.WriteUint64(trp) + data = append(data, bf) + } + case 2: + for _, skills := range towerInfo.TowerSkill { + bf := byteframe.NewByteFrame() + bf.WriteBytes(skills) + data = append(data, bf) + } + case 4: + for _, history := range towerInfo.TowerHistory { + bf := byteframe.NewByteFrame() + bf.WriteBytes(history) + data = append(data, bf) + } } - - if err != nil { - stubGetNoResults(s, pkt.AckHandle) - } - doAckBufSucceed(s, pkt.AckHandle, data) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { @@ -85,32 +78,37 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} +type WeeklySeibatuRankingReward struct { + Unk0 int32 + Unk1 int32 + Unk2 uint32 + Unk3 int32 + Unk4 int32 + Unk5 int32 +} + func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(1) // Entries - - bf.WriteInt32(0) - bf.WriteInt32(0) - bf.WriteUint32(0) - bf.WriteInt32(0) - bf.WriteInt32(0) - bf.WriteInt32(0) - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + var data []*byteframe.ByteFrame + weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{ + {0, 0, 0, 0, 0, 0}, + } + for _, reward := range weeklySeibatuRankingRewards { + bf := byteframe.NewByteFrame() + bf.WriteInt32(reward.Unk0) + bf.WriteInt32(reward.Unk1) + bf.WriteUint32(reward.Unk2) + bf.WriteInt32(reward.Unk3) + bf.WriteInt32(reward.Unk4) + bf.WriteInt32(reward.Unk5) + data = append(data, bf) + } + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPresentBox) - bf := byteframe.NewByteFrame() - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) // Entries - + var data []*byteframe.ByteFrame /* bf.WriteUint32(0) bf.WriteInt32(0) @@ -124,13 +122,17 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) */ - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGemInfo) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + var data []*byteframe.ByteFrame + /* + bf.WriteUint16(0) + bf.WriteUint16(0) + */ + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} From 2c8391b5a47373a36c128a027a4a1e81530fb9c6 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 11 Jun 2023 18:51:56 +1000 Subject: [PATCH 29/99] various Tower changes --- common/stringsupport/string_convert.go | 21 +++ network/mhfpacket/msg_mhf_get_tower_info.go | 11 -- network/mhfpacket/msg_mhf_post_gem_info.go | 29 +++- network/mhfpacket/msg_mhf_post_tower_info.go | 47 +++--- patch-schema/tower.sql | 12 ++ server/channelserver/handlers.go | 11 -- server/channelserver/handlers_tower.go | 166 ++++++++++++++++--- 7 files changed, 225 insertions(+), 72 deletions(-) create mode 100644 patch-schema/tower.sql diff --git a/common/stringsupport/string_convert.go b/common/stringsupport/string_convert.go index 53ed2ec69..452c85321 100644 --- a/common/stringsupport/string_convert.go +++ b/common/stringsupport/string_convert.go @@ -2,6 +2,7 @@ package stringsupport import ( "bytes" + "fmt" "io" "strconv" "strings" @@ -96,3 +97,23 @@ func CSVElems(csv string) []int { } return r } + +func CSVGetIndex(csv string, i int) int { + s := CSVElems(csv) + if i < len(s) { + return s[i] + } + return 0 +} + +func CSVSetIndex(csv string, i int, v int) string { + s := CSVElems(csv) + if i < len(s) { + s[i] = v + } + var r []string + for j := 0; j < len(s); j++ { + r = append(r, fmt.Sprintf(`%d`, s[j])) + } + return strings.Join(r, ",") +} diff --git a/network/mhfpacket/msg_mhf_get_tower_info.go b/network/mhfpacket/msg_mhf_get_tower_info.go index a0b686485..4041e26e4 100644 --- a/network/mhfpacket/msg_mhf_get_tower_info.go +++ b/network/mhfpacket/msg_mhf_get_tower_info.go @@ -8,19 +8,8 @@ import ( "erupe-ce/network/clientctx" ) -// The server sends different responses based on these values. -const ( - TowerInfoTypeUnk0 = iota - TowerInfoTypeTowerRankPoint - TowerInfoTypeGetOwnTowerSkill - TowerInfoTypeGetOwnTowerLevelV3 - TowerInfoTypeTowerTouhaHistory - TowerInfoTypeUnk5 -) - // MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO type MsgMhfGetTowerInfo struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 InfoType uint32 // Requested response type Unk0 uint32 diff --git a/network/mhfpacket/msg_mhf_post_gem_info.go b/network/mhfpacket/msg_mhf_post_gem_info.go index 13a0a9a0d..2e89b89b7 100644 --- a/network/mhfpacket/msg_mhf_post_gem_info.go +++ b/network/mhfpacket/msg_mhf_post_gem_info.go @@ -1,15 +1,24 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostGemInfo represents the MSG_MHF_POST_GEM_INFO -type MsgMhfPostGemInfo struct{} +type MsgMhfPostGemInfo struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 + Unk3 int32 + Unk4 int32 + Unk5 int32 + Unk6 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { @@ -18,7 +27,15 @@ func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadInt32() + m.Unk5 = bf.ReadInt32() + m.Unk6 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_post_tower_info.go b/network/mhfpacket/msg_mhf_post_tower_info.go index 7719086ff..3499d1f98 100644 --- a/network/mhfpacket/msg_mhf_post_tower_info.go +++ b/network/mhfpacket/msg_mhf_post_tower_info.go @@ -1,28 +1,26 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostTowerInfo represents the MSG_MHF_POST_TOWER_INFO type MsgMhfPostTowerInfo struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 - Unk0 uint32 + InfoType uint32 Unk1 uint32 - Unk2 uint32 - Unk3 uint32 - Unk4 uint32 - Unk5 uint32 - Unk6 uint32 - Unk7 uint32 - Unk8 uint32 - Unk9 uint32 - Unk10 uint32 + Unk2 int32 + Unk3 int32 + Unk4 int32 + Unk5 int32 + Unk6 int32 + Unk7 int32 + Unk8 int32 + Unk9 int64 } // Opcode returns the ID associated with this packet type. @@ -33,17 +31,16 @@ func (m *MsgMhfPostTowerInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() + m.InfoType = bf.ReadUint32() m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadUint32() - m.Unk3 = bf.ReadUint32() - m.Unk4 = bf.ReadUint32() - m.Unk5 = bf.ReadUint32() - m.Unk6 = bf.ReadUint32() - m.Unk7 = bf.ReadUint32() - m.Unk8 = bf.ReadUint32() - m.Unk9 = bf.ReadUint32() - m.Unk10 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadInt32() + m.Unk5 = bf.ReadInt32() + m.Unk6 = bf.ReadInt32() + m.Unk7 = bf.ReadInt32() + m.Unk8 = bf.ReadInt32() + m.Unk9 = bf.ReadInt64() return nil } diff --git a/patch-schema/tower.sql b/patch-schema/tower.sql new file mode 100644 index 000000000..661393c27 --- /dev/null +++ b/patch-schema/tower.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS tower ( + char_id INT, + tr INT, + trp INT, + tsp INT, + zone1 INT, + skills TEXT DEFAULT '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,0,0,0,0,0,0,0,0,0,0,0' +); + +END; \ No newline at end of file diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 5081bb2c4..ed00f2275 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -27,17 +27,6 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) { doAckBufSucceed(s, ackHandle, enumBf.Data()) } -// Temporary function to just return no results for many MSG_MHF_GET* packets. -func stubGetNoResults(s *Session, ackHandle uint32) { - resp := byteframe.NewByteFrame() - resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?) - resp.WriteUint32(0) // Unk - resp.WriteUint32(0) // Unk - resp.WriteUint32(0) // Entry count - - doAckBufSucceed(s, ackHandle, resp.Data()) -} - func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) { bf := byteframe.NewByteFrame() bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 1bec51dde..3fb859b9a 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -1,46 +1,97 @@ package channelserver import ( - "encoding/hex" "erupe-ce/common/byteframe" + "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" ) +type TowerInfoTRP struct { + TR int32 + TRP int32 +} + +type TowerInfoSkill struct { + TSP int32 + Unk1 []int16 // 40 +} + +type TowerInfoHistory struct { + Unk0 []int16 // 5 + Unk1 []int16 // 5 +} + +type TowerInfoLevel struct { + Zone1 int32 + Unk1 int32 + Unk2 int32 + Unk3 int32 +} + func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) var data []*byteframe.ByteFrame type TowerInfo struct { - TRP []uint64 - TowerSkill [][]byte // 132 bytes - TowerHistory [][]byte // 20 bytes + TRP []TowerInfoTRP + Skill []TowerInfoSkill + History []TowerInfoHistory + Level []TowerInfoLevel } towerInfo := TowerInfo{ - TRP: []uint64{0}, - TowerSkill: [][]byte{make([]byte, 132)}, - TowerHistory: [][]byte{make([]byte, 20)}, + TRP: []TowerInfoTRP{{0, 0}}, + Skill: []TowerInfoSkill{{0, make([]int16, 40)}}, + History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}}, + Level: []TowerInfoLevel{{0, 0, 0, 0}}, } - // Example data - // towerInfo.TowerSkill[0], _ = hex.DecodeString("0000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + tempSkills := "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,0,0,0,0,0,0,0,0,0,0,0" + + err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(zone1, 0), skills FROM tower WHERE char_id=$1 + `, s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Zone1, &tempSkills) + if err != nil { + s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID) + } + + for i, skill := range stringsupport.CSVElems(tempSkills) { + towerInfo.Skill[0].Unk1[i] = int16(skill) + } switch pkt.InfoType { case 1: for _, trp := range towerInfo.TRP { bf := byteframe.NewByteFrame() - bf.WriteUint64(trp) + bf.WriteInt32(trp.TR) + bf.WriteInt32(trp.TRP) data = append(data, bf) } case 2: - for _, skills := range towerInfo.TowerSkill { + for _, skills := range towerInfo.Skill { bf := byteframe.NewByteFrame() - bf.WriteBytes(skills) + bf.WriteInt32(skills.TSP) + for i := range skills.Unk1 { + bf.WriteInt16(skills.Unk1[i]) + } data = append(data, bf) } case 4: - for _, history := range towerInfo.TowerHistory { + for _, history := range towerInfo.History { bf := byteframe.NewByteFrame() - bf.WriteBytes(history) + for i := range history.Unk0 { + bf.WriteInt16(history.Unk0[i]) + } + for i := range history.Unk1 { + bf.WriteInt16(history.Unk1[i]) + } + data = append(data, bf) + } + case 5: + for _, level := range towerInfo.Level { + bf := byteframe.NewByteFrame() + bf.WriteInt32(level.Zone1) + bf.WriteInt32(level.Unk1) + bf.WriteInt32(level.Unk2) + bf.WriteInt32(level.Unk3) data = append(data, bf) } } @@ -49,9 +100,55 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) + switch pkt.InfoType { + case 2: + skills := "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,0,0,0,0,0,0,0,0,0,0,0" + s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills) + s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Unk2), stringsupport.CSVGetIndex(skills, int(pkt.Unk2))+1), pkt.Unk5, s.charID) + case 7: + s.server.db.Exec(`UPDATE tower SET tr=$1, trp=$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.Unk3, pkt.Unk4, pkt.Unk8, s.charID) + } doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } +type TenrouiraiCharScore struct { + Score int32 + Name string +} + +type TenrouiraiProgress struct { + Unk0 uint8 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 +} + +type TenrouiraiTicket struct { + Unk0 uint8 + Unk1 uint32 + Unk2 uint32 +} + +type TenrouiraiData struct { + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 + Unk3 uint16 + Unk4 uint8 + Unk5 uint8 + Unk6 uint8 + Unk7 uint8 + Unk8 uint8 + Unk9 uint8 +} + +type Tenrouirai struct { + CharScore []TenrouiraiCharScore + Progress []TenrouiraiProgress + Ticket []TenrouiraiTicket + Data []TenrouiraiData +} + func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { // if the game gets bad responses for this it breaks the ability to save pkt := p.(*mhfpacket.MsgMhfGetTenrouirai) @@ -125,14 +222,45 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { doAckEarthSucceed(s, pkt.AckHandle, data) } +type GemInfo struct { + Unk0 uint16 + Unk1 uint16 +} + +type GemHistory struct { + Unk0 uint16 + Unk1 uint16 + Unk2 uint32 + Unk3 string +} + func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGemInfo) var data []*byteframe.ByteFrame - /* - bf.WriteUint16(0) - bf.WriteUint16(0) - */ + gemInfo := []GemInfo{} + gemHistory := []GemHistory{} + switch pkt.Unk0 { + case 1: + for _, history := range gemHistory { + bf := byteframe.NewByteFrame() + bf.WriteUint16(history.Unk0) + bf.WriteUint16(history.Unk1) + bf.WriteUint32(history.Unk2) + bf.WriteBytes(stringsupport.PaddedString(history.Unk3, 14, true)) + data = append(data, bf) + } + default: + for _, info := range gemInfo { + bf := byteframe.NewByteFrame() + bf.WriteUint16(info.Unk0) + bf.WriteUint16(info.Unk1) + data = append(data, bf) + } + } doAckEarthSucceed(s, pkt.AckHandle, data) } -func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostGemInfo) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} From 75d5ceed4f3558491bf33c878352a761300a9ce5 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 12 Jun 2023 00:01:20 +1000 Subject: [PATCH 30/99] various Tower changes --- network/mhfpacket/msg_mhf_post_gem_info.go | 20 ++--- network/mhfpacket/msg_mhf_post_tenrouirai.go | 44 ++++++---- network/mhfpacket/msg_mhf_post_tower_info.go | 20 ++--- patch-schema/tower.sql | 3 +- server/channelserver/handlers_tower.go | 92 +++++++++++++++++--- 5 files changed, 127 insertions(+), 52 deletions(-) diff --git a/network/mhfpacket/msg_mhf_post_gem_info.go b/network/mhfpacket/msg_mhf_post_gem_info.go index 2e89b89b7..d487670fc 100644 --- a/network/mhfpacket/msg_mhf_post_gem_info.go +++ b/network/mhfpacket/msg_mhf_post_gem_info.go @@ -11,12 +11,12 @@ import ( // MsgMhfPostGemInfo represents the MSG_MHF_POST_GEM_INFO type MsgMhfPostGemInfo struct { AckHandle uint32 - Unk0 uint32 + Op uint32 Unk1 uint32 - Unk2 int32 - Unk3 int32 - Unk4 int32 - Unk5 int32 + Gem int32 + Quantity int32 + CID int32 + Message int32 Unk6 int32 } @@ -28,12 +28,12 @@ func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() + m.Op = bf.ReadUint32() m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadInt32() - m.Unk3 = bf.ReadInt32() - m.Unk4 = bf.ReadInt32() - m.Unk5 = bf.ReadInt32() + m.Gem = bf.ReadInt32() + m.Quantity = bf.ReadInt32() + m.CID = bf.ReadInt32() + m.Message = bf.ReadInt32() m.Unk6 = bf.ReadInt32() return nil } diff --git a/network/mhfpacket/msg_mhf_post_tenrouirai.go b/network/mhfpacket/msg_mhf_post_tenrouirai.go index d4b4fdc71..91b8d1b6e 100644 --- a/network/mhfpacket/msg_mhf_post_tenrouirai.go +++ b/network/mhfpacket/msg_mhf_post_tenrouirai.go @@ -1,22 +1,26 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostTenrouirai represents the MSG_MHF_POST_TENROUIRAI -type MsgMhfPostTenrouirai struct{ - AckHandle uint32 - Unk0 uint16 - Unk1 uint32 - Unk2 uint32 - Unk3 uint32 - Unk4 uint32 - Unk5 uint8 +type MsgMhfPostTenrouirai struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + GuildID uint32 + Unk3 uint8 + Unk4 uint16 + Unk5 uint16 + Unk6 uint16 + Unk7 uint16 + Unk8 uint16 + Unk9 uint16 } // Opcode returns the ID associated with this packet type. @@ -27,12 +31,16 @@ func (m *MsgMhfPostTenrouirai) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() - m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadUint32() - m.Unk3 = bf.ReadUint32() - m.Unk4 = bf.ReadUint32() - m.Unk5 = bf.ReadUint8() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.GuildID = bf.ReadUint32() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint16() + m.Unk5 = bf.ReadUint16() + m.Unk6 = bf.ReadUint16() + m.Unk7 = bf.ReadUint16() + m.Unk8 = bf.ReadUint16() + m.Unk9 = bf.ReadUint16() return nil } diff --git a/network/mhfpacket/msg_mhf_post_tower_info.go b/network/mhfpacket/msg_mhf_post_tower_info.go index 3499d1f98..a574f6c6e 100644 --- a/network/mhfpacket/msg_mhf_post_tower_info.go +++ b/network/mhfpacket/msg_mhf_post_tower_info.go @@ -13,13 +13,13 @@ type MsgMhfPostTowerInfo struct { AckHandle uint32 InfoType uint32 Unk1 uint32 - Unk2 int32 - Unk3 int32 - Unk4 int32 - Unk5 int32 + Skill int32 + TR int32 + TRP int32 + Cost int32 Unk6 int32 Unk7 int32 - Unk8 int32 + Zone1 int32 Unk9 int64 } @@ -33,13 +33,13 @@ func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie m.AckHandle = bf.ReadUint32() m.InfoType = bf.ReadUint32() m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadInt32() - m.Unk3 = bf.ReadInt32() - m.Unk4 = bf.ReadInt32() - m.Unk5 = bf.ReadInt32() + m.Skill = bf.ReadInt32() + m.TR = bf.ReadInt32() + m.TRP = bf.ReadInt32() + m.Cost = bf.ReadInt32() m.Unk6 = bf.ReadInt32() m.Unk7 = bf.ReadInt32() - m.Unk8 = bf.ReadInt32() + m.Zone1 = bf.ReadInt32() m.Unk9 = bf.ReadInt64() return nil } diff --git a/patch-schema/tower.sql b/patch-schema/tower.sql index 661393c27..d1a6c1556 100644 --- a/patch-schema/tower.sql +++ b/patch-schema/tower.sql @@ -6,7 +6,8 @@ CREATE TABLE IF NOT EXISTS tower ( trp INT, tsp INT, zone1 INT, - skills TEXT DEFAULT '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,0,0,0,0,0,0,0,0,0,0,0' + skills TEXT DEFAULT '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,0,0,0,0,0,0,0,0,0,0,0', + gems TEXT DEFAULT '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' ); END; \ No newline at end of file diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 3fb859b9a..13a16cc7b 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -1,6 +1,8 @@ package channelserver import ( + "go.uber.org/zap" + "erupe-ce/common/byteframe" "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" @@ -100,15 +102,32 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) + + if s.server.erupeConfig.DevModeOptions.QuestDebugTools { + s.logger.Debug( + p.Opcode().String(), + zap.Uint32("InfoType", pkt.InfoType), + zap.Uint32("Unk1", pkt.Unk1), + zap.Int32("Skill", pkt.Skill), + zap.Int32("TR", pkt.TR), + zap.Int32("TRP", pkt.TRP), + zap.Int32("Cost", pkt.Cost), + zap.Int32("Unk6", pkt.Unk6), + zap.Int32("Unk7", pkt.Unk7), + zap.Int32("Zone1", pkt.Zone1), + zap.Int64("Unk9", pkt.Unk9), + ) + } + switch pkt.InfoType { case 2: skills := "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,0,0,0,0,0,0,0,0,0,0,0" s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills) - s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Unk2), stringsupport.CSVGetIndex(skills, int(pkt.Unk2))+1), pkt.Unk5, s.charID) + s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID) case 7: - s.server.db.Exec(`UPDATE tower SET tr=$1, trp=$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.Unk3, pkt.Unk4, pkt.Unk8, s.charID) + s.server.db.Exec(`UPDATE tower SET tr=$1, trp=trp+$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.TR, pkt.TRP, pkt.Zone1, s.charID) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type TenrouiraiCharScore struct { @@ -170,7 +189,24 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTenrouirai) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + + if s.server.erupeConfig.DevModeOptions.QuestDebugTools { + s.logger.Debug( + p.Opcode().String(), + zap.Uint8("Unk0", pkt.Unk0), + zap.Uint8("Unk1", pkt.Unk1), + zap.Uint32("GuildID", pkt.GuildID), + zap.Uint8("Unk3", pkt.Unk3), + zap.Uint16("Unk4", pkt.Unk4), + zap.Uint16("Unk5", pkt.Unk5), + zap.Uint16("Unk6", pkt.Unk6), + zap.Uint16("Unk7", pkt.Unk7), + zap.Uint16("Unk8", pkt.Unk8), + zap.Uint16("Unk9", pkt.Unk9), + ) + } + + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} @@ -223,8 +259,8 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { } type GemInfo struct { - Unk0 uint16 - Unk1 uint16 + Gem uint16 + Quantity uint16 } type GemHistory struct { @@ -239,8 +275,22 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { var data []*byteframe.ByteFrame gemInfo := []GemInfo{} gemHistory := []GemHistory{} + + tempGems := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&tempGems) + for i, v := range stringsupport.CSVElems(tempGems) { + gemInfo = append(gemInfo, GemInfo{uint16(((i / 3) * 256) + ((i % 3) + 1)), uint16(v)}) + } + switch pkt.Unk0 { case 1: + for _, info := range gemInfo { + bf := byteframe.NewByteFrame() + bf.WriteUint16(info.Gem) + bf.WriteUint16(info.Quantity) + data = append(data, bf) + } + default: for _, history := range gemHistory { bf := byteframe.NewByteFrame() bf.WriteUint16(history.Unk0) @@ -249,18 +299,34 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { bf.WriteBytes(stringsupport.PaddedString(history.Unk3, 14, true)) data = append(data, bf) } - default: - for _, info := range gemInfo { - bf := byteframe.NewByteFrame() - bf.WriteUint16(info.Unk0) - bf.WriteUint16(info.Unk1) - data = append(data, bf) - } } doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostGemInfo) + + if s.server.erupeConfig.DevModeOptions.QuestDebugTools { + s.logger.Debug( + p.Opcode().String(), + zap.Uint32("Op", pkt.Op), + zap.Uint32("Unk1", pkt.Unk1), + zap.Int32("Gem", pkt.Gem), + zap.Int32("Quantity", pkt.Quantity), + zap.Int32("CID", pkt.CID), + zap.Int32("Message", pkt.Message), + zap.Int32("Unk6", pkt.Unk6), + ) + } + + gems := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&gems) + switch pkt.Op { + case 1: // Add gem + i := int(((pkt.Gem / 256) * 3) + (((pkt.Gem - ((pkt.Gem / 256) * 256)) - 1) % 3)) + s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID) + case 2: // Transfer gem + // no way im doing this for now + } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } From 03dde7d60db05fa5f73dbad77f8b484bd7684e4b Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 12 Jun 2023 00:05:51 +1000 Subject: [PATCH 31/99] various Tower changes --- network/mhfpacket/msg_mhf_get_tenrouirai.go | 25 ++++---- server/channelserver/handlers_tower.go | 70 +++++++++++++++++---- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/network/mhfpacket/msg_mhf_get_tenrouirai.go b/network/mhfpacket/msg_mhf_get_tenrouirai.go index da460add9..a4784e39b 100644 --- a/network/mhfpacket/msg_mhf_get_tenrouirai.go +++ b/network/mhfpacket/msg_mhf_get_tenrouirai.go @@ -1,20 +1,21 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetTenrouirai represents the MSG_MHF_GET_TENROUIRAI type MsgMhfGetTenrouirai struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 - Unk0 uint16 - Unk1 uint32 - Unk2 uint16 + Unk0 uint8 + Unk1 uint8 + GuildID uint32 + Unk3 uint8 + Unk4 uint8 } // Opcode returns the ID associated with this packet type. @@ -25,9 +26,11 @@ func (m *MsgMhfGetTenrouirai) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() - m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadUint16() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.GuildID = bf.ReadUint32() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint8() return nil } diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 13a16cc7b..22a6a34d4 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -169,22 +169,66 @@ type Tenrouirai struct { } func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { - // if the game gets bad responses for this it breaks the ability to save pkt := p.(*mhfpacket.MsgMhfGetTenrouirai) - var data []byte - var err error - if pkt.Unk0 == 1 { - data, err = hex.DecodeString("0A218EAD000000000000000000000001010000000000060010") - } else if pkt.Unk2 == 4 { - data, err = hex.DecodeString("0A218EAD0000000000000000000000210101005000000202010102020104001000000202010102020106003200000202010002020104000C003202020101020201030032000002020101020202059C4000000202010002020105C35000320202010102020201003C00000202010102020203003200000201010001020203002800320201010101020204000C00000201010101020206002800000201010001020101003C00320201020101020105C35000000301020101020106003200000301020001020104001000320301020101020105C350000003010201010202030028000003010200010201030032003203010201010202059C4000000301020101010206002800000301020001010201003C00320301020101010206003200000301020101010204000C000003010200010101010050003203010201010101059C40000003010201010101030032000003010200010101040010003203010001010101060032000003010001010102030028000003010001010101010050003203010000010102059C4000000301000001010206002800000301000001010010") - } else { - data = []byte{0x00, 0x00, 0x00, 0x00} - s.logger.Info("GET_TENROUIRAI request for unknown type") + var data []*byteframe.ByteFrame + + tenrouirai := Tenrouirai{ + Data: []TenrouiraiData{ + {1, 1, 80, 0, 2, 2, 1, 1, 2, 2}, + {1, 4, 16, 0, 2, 2, 1, 1, 2, 2}, + {1, 6, 50, 0, 2, 2, 1, 0, 2, 2}, + {1, 4, 12, 50, 2, 2, 1, 1, 2, 2}, + {1, 3, 50, 0, 2, 2, 1, 1, 2, 2}, + {2, 5, 40000, 0, 2, 2, 1, 0, 2, 2}, + {1, 5, 50000, 50, 2, 2, 1, 1, 2, 2}, + {2, 1, 60, 0, 2, 2, 1, 1, 2, 2}, + {2, 3, 50, 0, 2, 1, 1, 0, 1, 2}, + {2, 3, 40, 50, 2, 1, 1, 1, 1, 2}, + {2, 4, 12, 0, 2, 1, 1, 1, 1, 2}, + {2, 6, 40, 0, 2, 1, 1, 0, 1, 2}, + {1, 1, 60, 50, 2, 1, 2, 1, 1, 2}, + {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, + {1, 6, 50, 0, 3, 1, 2, 0, 1, 2}, + {1, 4, 16, 50, 3, 1, 2, 1, 1, 2}, + {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, + {2, 3, 40, 0, 3, 1, 2, 0, 1, 2}, + {1, 3, 50, 50, 3, 1, 2, 1, 1, 2}, + {2, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, + {2, 6, 40, 0, 3, 1, 2, 0, 1, 1}, + {2, 1, 60, 50, 3, 1, 2, 1, 1, 1}, + {2, 6, 50, 0, 3, 1, 2, 1, 1, 1}, + {2, 4, 12, 0, 3, 1, 2, 0, 1, 1}, + {1, 1, 80, 50, 3, 1, 2, 1, 1, 1}, + {1, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, + {1, 3, 50, 0, 3, 1, 2, 0, 1, 1}, + {1, 4, 16, 50, 3, 1, 0, 1, 1, 1}, + {1, 6, 50, 0, 3, 1, 0, 1, 1, 1}, + {2, 3, 40, 0, 3, 1, 0, 1, 1, 1}, + {1, 1, 80, 50, 3, 1, 0, 0, 1, 1}, + {2, 5, 40000, 0, 3, 1, 0, 0, 1, 1}, + {2, 6, 40, 0, 3, 1, 0, 0, 1, 1}, + }, } - if err != nil { - panic(err) + + switch pkt.Unk1 { + case 4: + for _, tdata := range tenrouirai.Data { + bf := byteframe.NewByteFrame() + bf.WriteUint8(tdata.Unk0) + bf.WriteUint8(tdata.Unk1) + bf.WriteUint16(tdata.Unk2) + bf.WriteUint16(tdata.Unk3) + bf.WriteUint8(tdata.Unk4) + bf.WriteUint8(tdata.Unk5) + bf.WriteUint8(tdata.Unk6) + bf.WriteUint8(tdata.Unk7) + bf.WriteUint8(tdata.Unk8) + bf.WriteUint8(tdata.Unk9) + data = append(data, bf) + } } - doAckBufSucceed(s, pkt.AckHandle, data) + + doAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { From d269d5f777509efd460759a12826001f47d2b394 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 12 Jun 2023 19:56:00 +1000 Subject: [PATCH 32/99] various Tower changes --- network/mhfpacket/msg_mhf_post_tenrouirai.go | 24 ++++----- server/channelserver/handlers_quest.go | 13 ++--- server/channelserver/handlers_tower.go | 52 +++++++++++++------- 3 files changed, 54 insertions(+), 35 deletions(-) diff --git a/network/mhfpacket/msg_mhf_post_tenrouirai.go b/network/mhfpacket/msg_mhf_post_tenrouirai.go index 91b8d1b6e..7edb751e5 100644 --- a/network/mhfpacket/msg_mhf_post_tenrouirai.go +++ b/network/mhfpacket/msg_mhf_post_tenrouirai.go @@ -15,12 +15,12 @@ type MsgMhfPostTenrouirai struct { Unk1 uint8 GuildID uint32 Unk3 uint8 - Unk4 uint16 - Unk5 uint16 - Unk6 uint16 - Unk7 uint16 - Unk8 uint16 - Unk9 uint16 + Floors uint16 + Antiques uint16 + Chests uint16 + Cats uint16 + TRP uint16 + Slays uint16 } // Opcode returns the ID associated with this packet type. @@ -35,12 +35,12 @@ func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli m.Unk1 = bf.ReadUint8() m.GuildID = bf.ReadUint32() m.Unk3 = bf.ReadUint8() - m.Unk4 = bf.ReadUint16() - m.Unk5 = bf.ReadUint16() - m.Unk6 = bf.ReadUint16() - m.Unk7 = bf.ReadUint16() - m.Unk8 = bf.ReadUint16() - m.Unk9 = bf.ReadUint16() + m.Floors = bf.ReadUint16() + m.Antiques = bf.ReadUint16() + m.Chests = bf.ReadUint16() + m.Cats = bf.ReadUint16() + m.TRP = bf.ReadUint16() + m.Slays = bf.ReadUint16() return nil } diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index e16d7bc08..8f40f7539 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -84,7 +84,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { var totalCount, returnedCount uint16 bf := byteframe.NewByteFrame() bf.WriteUint16(0) - err := filepath.Walk(fmt.Sprintf("%s/events/", s.server.erupeConfig.BinPath), func(path string, info os.FileInfo, err error) error { + filepath.Walk(fmt.Sprintf("%s/events/", s.server.erupeConfig.BinPath), func(path string, info os.FileInfo, err error) error { if err != nil { return err } else if info.IsDir() { @@ -107,10 +107,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { } return nil }) - if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 18)) - return - } type tuneValue struct { ID uint16 @@ -144,8 +140,13 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1028, Value: 100}, {ID: 1030, Value: 8}, {ID: 1031, Value: 100}, - {ID: 1032, Value: 0}, // isValid_partner + {ID: 1032, Value: 0}, // isValid_partner + {ID: 1044, Value: 200}, // get_rate_tload_time_out + {ID: 1045, Value: 0}, // get_rate_tower_treasure_preset {ID: 1046, Value: 99}, + {ID: 1048, Value: 0}, // get_rate_tower_log_disable + {ID: 1049, Value: 10}, // get_rate_tower_gem_max + {ID: 1050, Value: 1}, // get_rate_tower_gem_set {ID: 1051, Value: 200}, {ID: 1052, Value: 200}, {ID: 1063, Value: 50000}, diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 22a6a34d4..3da436370 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -136,10 +136,10 @@ type TenrouiraiCharScore struct { } type TenrouiraiProgress struct { - Unk0 uint8 - Unk1 uint16 - Unk2 uint16 - Unk3 uint16 + Completed uint8 + Mission1 uint16 + Mission2 uint16 + Mission3 uint16 } type TenrouiraiTicket struct { @@ -149,9 +149,15 @@ type TenrouiraiTicket struct { } type TenrouiraiData struct { - Unk0 uint8 - Unk1 uint8 - Unk2 uint16 + Zone uint8 + Mission uint8 + // 1 = Floors climbed + // 2 = Collect antiques + // 3 = Open chests + // 4 = Cats saved + // 5 = TRP acquisition + // 6 = Monster slays + Goal uint16 Unk3 uint16 Unk4 uint8 Unk5 uint8 @@ -173,6 +179,9 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { var data []*byteframe.ByteFrame tenrouirai := Tenrouirai{ + Progress: []TenrouiraiProgress{ + {1, 0, 0, 0}, + }, Data: []TenrouiraiData{ {1, 1, 80, 0, 2, 2, 1, 1, 2, 2}, {1, 4, 16, 0, 2, 2, 1, 1, 2, 2}, @@ -211,12 +220,12 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { } switch pkt.Unk1 { - case 4: + case 1: for _, tdata := range tenrouirai.Data { bf := byteframe.NewByteFrame() - bf.WriteUint8(tdata.Unk0) - bf.WriteUint8(tdata.Unk1) - bf.WriteUint16(tdata.Unk2) + bf.WriteUint8(tdata.Zone) + bf.WriteUint8(tdata.Mission) + bf.WriteUint16(tdata.Goal) bf.WriteUint16(tdata.Unk3) bf.WriteUint8(tdata.Unk4) bf.WriteUint8(tdata.Unk5) @@ -226,6 +235,15 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(tdata.Unk9) data = append(data, bf) } + case 4: + for _, progress := range tenrouirai.Progress { + bf := byteframe.NewByteFrame() + bf.WriteUint8(progress.Completed) + bf.WriteUint16(progress.Mission1) + bf.WriteUint16(progress.Mission2) + bf.WriteUint16(progress.Mission3) + data = append(data, bf) + } } doAckEarthSucceed(s, pkt.AckHandle, data) @@ -241,12 +259,12 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { zap.Uint8("Unk1", pkt.Unk1), zap.Uint32("GuildID", pkt.GuildID), zap.Uint8("Unk3", pkt.Unk3), - zap.Uint16("Unk4", pkt.Unk4), - zap.Uint16("Unk5", pkt.Unk5), - zap.Uint16("Unk6", pkt.Unk6), - zap.Uint16("Unk7", pkt.Unk7), - zap.Uint16("Unk8", pkt.Unk8), - zap.Uint16("Unk9", pkt.Unk9), + zap.Uint16("Floors", pkt.Floors), + zap.Uint16("Antiques", pkt.Antiques), + zap.Uint16("Chests", pkt.Chests), + zap.Uint16("Cats", pkt.Cats), + zap.Uint16("TRP", pkt.TRP), + zap.Uint16("Slays", pkt.Slays), ) } From 0b4108fb851a0fe0e348eaaa7eba18834d5af179 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 12 Jun 2023 23:23:53 +1000 Subject: [PATCH 33/99] various Conquest changes --- .../msg_mhf_get_break_seibatu_level_reward.go | 19 ++-- ...msg_mhf_get_fixed_seibatu_ranking_table.go | 25 +++-- .../msg_mhf_read_beat_level_all_ranking.go | 21 ++-- .../msg_mhf_read_beat_level_my_ranking.go | 23 +++-- server/channelserver/handlers.go | 30 ------ server/channelserver/handlers_seibattle.go | 98 +++++++++++++++++++ server/channelserver/handlers_tower.go | 30 ------ 7 files changed, 162 insertions(+), 84 deletions(-) create mode 100644 server/channelserver/handlers_seibattle.go diff --git a/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go b/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go index e6f0e9a56..601dd5cb2 100644 --- a/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go +++ b/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go @@ -1,15 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetBreakSeibatuLevelReward represents the MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD -type MsgMhfGetBreakSeibatuLevelReward struct{} +type MsgMhfGetBreakSeibatuLevelReward struct { + AckHandle uint32 + Unk0 uint32 + Unk1 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBreakSeibatuLevelReward) Opcode() network.PacketID { @@ -18,7 +22,10 @@ func (m *MsgMhfGetBreakSeibatuLevelReward) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBreakSeibatuLevelReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go b/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go index 52651c9d2..2d7cbbac4 100644 --- a/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go +++ b/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go @@ -1,15 +1,22 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetFixedSeibatuRankingTable represents the MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE -type MsgMhfGetFixedSeibatuRankingTable struct{} +type MsgMhfGetFixedSeibatuRankingTable struct { + AckHandle uint32 + Unk0 uint32 + Unk1 int32 + Unk2 int32 + Unk3 int32 + Unk4 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetFixedSeibatuRankingTable) Opcode() network.PacketID { @@ -18,7 +25,13 @@ func (m *MsgMhfGetFixedSeibatuRankingTable) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetFixedSeibatuRankingTable) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadInt32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go b/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go index 4d97df0d5..d9bf48a2c 100644 --- a/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go +++ b/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfReadBeatLevelAllRanking represents the MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING -type MsgMhfReadBeatLevelAllRanking struct{} +type MsgMhfReadBeatLevelAllRanking struct { + AckHandle uint32 + Unk0 uint32 + GuildID int32 + Unk2 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfReadBeatLevelAllRanking) Opcode() network.PacketID { @@ -18,7 +23,11 @@ func (m *MsgMhfReadBeatLevelAllRanking) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfReadBeatLevelAllRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.GuildID = bf.ReadInt32() + m.Unk2 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go b/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go index 4b713e8e7..e51bba318 100644 --- a/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go +++ b/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfReadBeatLevelMyRanking represents the MSG_MHF_READ_BEAT_LEVEL_MY_RANKING -type MsgMhfReadBeatLevelMyRanking struct{} +type MsgMhfReadBeatLevelMyRanking struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 []int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID { @@ -18,7 +23,13 @@ func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfReadBeatLevelMyRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + for i := 0; i < 16; i++ { + m.Unk2 = append(m.Unk2, bf.ReadInt32()) + } + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index ed00f2275..614b98da1 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1575,36 +1575,6 @@ func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfReadBeatLevel) - - // This response is fixed and will never change on JP, - // but I've left it dynamic for possible other client differences. - resp := byteframe.NewByteFrame() - for i := 0; i < int(pkt.ValidIDCount); i++ { - resp.WriteUint32(pkt.IDs[i]) - resp.WriteUint32(1) - resp.WriteUint32(1) - resp.WriteUint32(1) - } - - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) -} - -func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel) - - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) -} - -func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) {} - func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { diff --git a/server/channelserver/handlers_seibattle.go b/server/channelserver/handlers_seibattle.go new file mode 100644 index 000000000..4df05c67d --- /dev/null +++ b/server/channelserver/handlers_seibattle.go @@ -0,0 +1,98 @@ +package channelserver + +import ( + "erupe-ce/common/byteframe" + "erupe-ce/network/mhfpacket" +) + +func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBreakSeibatuLevelReward) + bf := byteframe.NewByteFrame() + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +type WeeklySeibatuRankingReward struct { + Unk0 int32 + Unk1 int32 + Unk2 uint32 + Unk3 int32 + Unk4 int32 + Unk5 int32 +} + +func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) + var data []*byteframe.ByteFrame + weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{ + {0, 0, 0, 0, 0, 0}, + } + for _, reward := range weeklySeibatuRankingRewards { + bf := byteframe.NewByteFrame() + bf.WriteInt32(reward.Unk0) + bf.WriteInt32(reward.Unk1) + bf.WriteUint32(reward.Unk2) + bf.WriteInt32(reward.Unk3) + bf.WriteInt32(reward.Unk4) + bf.WriteInt32(reward.Unk5) + data = append(data, bf) + } + doAckEarthSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetFixedSeibatuRankingTable) + bf := byteframe.NewByteFrame() + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteBytes(make([]byte, 32)) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadBeatLevel) + + // This response is fixed and will never change on JP, + // but I've left it dynamic for possible other client differences. + resp := byteframe.NewByteFrame() + for i := 0; i < int(pkt.ValidIDCount); i++ { + resp.WriteUint32(pkt.IDs[i]) + resp.WriteUint32(1) + resp.WriteUint32(1) + resp.WriteUint32(1) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel) + + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadBeatLevelAllRanking) + bf := byteframe.NewByteFrame() + bf.WriteUint32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + + for i := 0; i < 100; i++ { + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteBytes(make([]byte, 32)) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadBeatLevelMyRanking) + bf := byteframe.NewByteFrame() + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 3da436370..36e2cf45e 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -271,36 +271,6 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} - -type WeeklySeibatuRankingReward struct { - Unk0 int32 - Unk1 int32 - Unk2 uint32 - Unk3 int32 - Unk4 int32 - Unk5 int32 -} - -func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) - var data []*byteframe.ByteFrame - weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{ - {0, 0, 0, 0, 0, 0}, - } - for _, reward := range weeklySeibatuRankingRewards { - bf := byteframe.NewByteFrame() - bf.WriteInt32(reward.Unk0) - bf.WriteInt32(reward.Unk1) - bf.WriteUint32(reward.Unk2) - bf.WriteInt32(reward.Unk3) - bf.WriteInt32(reward.Unk4) - bf.WriteInt32(reward.Unk5) - data = append(data, bf) - } - doAckEarthSucceed(s, pkt.AckHandle, data) -} - func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPresentBox) var data []*byteframe.ByteFrame From b4df642ee3acb60adb1256ba9ca03af436a54ecc Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 18 Jun 2023 20:31:18 +1000 Subject: [PATCH 34/99] add ClientMode config option --- config.json | 1 + config/config.go | 26 ++++++- main.go | 64 ++++++++--------- network/mhfpacket/msg_mhf_enumerate_quest.go | 5 +- server/channelserver/handlers_cast_binary.go | 8 +-- server/channelserver/handlers_character.go | 73 ++++++++++++++------ server/channelserver/handlers_diva.go | 6 +- server/channelserver/handlers_event.go | 11 ++- server/channelserver/handlers_guild.go | 8 ++- server/channelserver/sys_channel_server.go | 4 +- server/discordbot/discord_bot.go | 4 +- server/entranceserver/entrance_server.go | 6 +- server/entranceserver/make_resp.go | 23 ++++-- server/signserver/sign_server.go | 4 +- server/signv2server/signv2_server.go | 4 +- 15 files changed, 169 insertions(+), 78 deletions(-) diff --git a/config.json b/config.json index 30164ec4c..1e09daddd 100644 --- a/config.json +++ b/config.json @@ -11,6 +11,7 @@ "PatchServerFile": "", "ScreenshotAPIURL": "", "DeleteOnSaveCorruption": false, + "ClientMode": "ZZ", "DevMode": true, "DevModeOptions": { "AutoCreateAccount": true, diff --git a/config/config.go b/config/config.go index f52cc73c5..9e96031a8 100644 --- a/config/config.go +++ b/config/config.go @@ -1,15 +1,28 @@ -package config +package _config import ( "fmt" "log" "net" "os" + "strings" "time" "github.com/spf13/viper" ) +type Mode string + +const ( + ZZ Mode = "ZZ" + Z2 Mode = "Z2" + Z1 Mode = "Z1" +) + +func (m Mode) String() string { + return string(m) +} + // Config holds the global server-wide config. type Config struct { Host string `mapstructure:"Host"` @@ -22,6 +35,7 @@ type Config struct { PatchServerFile string // File patch server override ScreenshotAPIURL string // Destination for screenshots uploaded to BBS DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion + ClientMode Mode DevMode bool DevModeOptions DevModeOptions @@ -170,7 +184,6 @@ func init() { if err != nil { preventClose(fmt.Sprintf("Failed to load config: %s", err.Error())) } - } // getOutboundIP4 gets the preferred outbound ip4 of this machine @@ -212,6 +225,15 @@ func LoadConfig() (*Config, error) { c.Host = getOutboundIP4().To4().String() } + switch strings.ToUpper(c.ClientMode.String()) { + case "Z1": + c.ClientMode = Z1 + case "Z2": + c.ClientMode = Z2 + default: + c.ClientMode = ZZ + } + return c, nil } diff --git a/main.go b/main.go index 0f104eccf..6f1abc011 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + _config "erupe-ce/config" "fmt" "net" "os" @@ -9,7 +10,6 @@ import ( "syscall" "time" - "erupe-ce/config" "erupe-ce/server/channelserver" "erupe-ce/server/discordbot" "erupe-ce/server/entranceserver" @@ -45,7 +45,8 @@ func main() { var err error var zapLogger *zap.Logger - if config.ErupeConfig.DevMode { + config := _config.ErupeConfig + if config.DevMode { zapLogger, _ = zap.NewDevelopment() } else { zapLogger, _ = zap.NewProduction() @@ -55,20 +56,21 @@ func main() { logger := zapLogger.Named("main") logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit())) + logger.Info(fmt.Sprintf("Client Mode: %s", config.ClientMode.String())) - if config.ErupeConfig.Database.Password == "" { + if config.Database.Password == "" { preventClose("Database password is blank") } - if net.ParseIP(config.ErupeConfig.Host) == nil { - ips, _ := net.LookupIP(config.ErupeConfig.Host) + if net.ParseIP(config.Host) == nil { + ips, _ := net.LookupIP(config.Host) for _, ip := range ips { if ip != nil { - config.ErupeConfig.Host = ip.String() + config.Host = ip.String() break } } - if net.ParseIP(config.ErupeConfig.Host) == nil { + if net.ParseIP(config.Host) == nil { preventClose("Invalid host address") } } @@ -76,10 +78,10 @@ func main() { // Discord bot var discordBot *discordbot.DiscordBot = nil - if config.ErupeConfig.Discord.Enabled { + if config.Discord.Enabled { bot, err := discordbot.NewDiscordBot(discordbot.Options{ Logger: logger, - Config: config.ErupeConfig, + Config: _config.ErupeConfig, }) if err != nil { @@ -102,11 +104,11 @@ func main() { // Create the postgres DB pool. connectString := fmt.Sprintf( "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", - config.ErupeConfig.Database.Host, - config.ErupeConfig.Database.Port, - config.ErupeConfig.Database.User, - config.ErupeConfig.Database.Password, - config.ErupeConfig.Database.Database, + config.Database.Host, + config.Database.Port, + config.Database.User, + config.Database.Password, + config.Database.Database, ) db, err := sqlx.Open("postgres", connectString) @@ -126,7 +128,7 @@ func main() { _ = db.MustExec("DELETE FROM servers") // Clean the DB if the option is on. - if config.ErupeConfig.DevMode && config.ErupeConfig.DevModeOptions.CleanDB { + if config.DevMode && config.DevModeOptions.CleanDB { logger.Info("Database: Started clearing...") cleanDB(db) logger.Info("Database: Finished clearing") @@ -139,11 +141,11 @@ func main() { // Entrance server. var entranceServer *entranceserver.Server - if config.ErupeConfig.Entrance.Enabled { + if config.Entrance.Enabled { entranceServer = entranceserver.NewServer( &entranceserver.Config{ Logger: logger.Named("entrance"), - ErupeConfig: config.ErupeConfig, + ErupeConfig: _config.ErupeConfig, DB: db, }) err = entranceServer.Start() @@ -158,11 +160,11 @@ func main() { // Sign server. var signServer *signserver.Server - if config.ErupeConfig.Sign.Enabled { + if config.Sign.Enabled { signServer = signserver.NewServer( &signserver.Config{ Logger: logger.Named("sign"), - ErupeConfig: config.ErupeConfig, + ErupeConfig: _config.ErupeConfig, DB: db, }) err = signServer.Start() @@ -176,11 +178,11 @@ func main() { // New Sign server var newSignServer *signv2server.Server - if config.ErupeConfig.SignV2.Enabled { + if config.SignV2.Enabled { newSignServer = signv2server.NewServer( &signv2server.Config{ Logger: logger.Named("sign"), - ErupeConfig: config.ErupeConfig, + ErupeConfig: _config.ErupeConfig, DB: db, }) err = newSignServer.Start() @@ -194,23 +196,23 @@ func main() { var channels []*channelserver.Server - if config.ErupeConfig.Channel.Enabled { + if config.Channel.Enabled { channelQuery := "" si := 0 ci := 0 count := 1 - for j, ee := range config.ErupeConfig.Entrance.Entries { + for j, ee := range config.Entrance.Entries { for i, ce := range ee.Channels { sid := (4096 + si*256) + (16 + ci) c := *channelserver.NewServer(&channelserver.Config{ ID: uint16(sid), Logger: logger.Named("channel-" + fmt.Sprint(count)), - ErupeConfig: config.ErupeConfig, + ErupeConfig: _config.ErupeConfig, DB: db, DiscordBot: discordBot, }) if ee.IP == "" { - c.IP = config.ErupeConfig.Host + c.IP = config.Host } else { c.IP = ee.IP } @@ -246,7 +248,7 @@ func main() { signal.Notify(c, os.Interrupt, syscall.SIGTERM) <-c - if !config.ErupeConfig.DisableSoftCrash { + if !config.DisableSoftCrash { for i := 0; i < 10; i++ { message := fmt.Sprintf("Shutting down in %d...", 10-i) for _, c := range channels { @@ -257,21 +259,21 @@ func main() { } } - if config.ErupeConfig.Channel.Enabled { + if config.Channel.Enabled { for _, c := range channels { c.Shutdown() } } - if config.ErupeConfig.Sign.Enabled { + if config.Sign.Enabled { signServer.Shutdown() } - if config.ErupeConfig.SignV2.Enabled { + if config.SignV2.Enabled { newSignServer.Shutdown() } - if config.ErupeConfig.Entrance.Enabled { + if config.Entrance.Enabled { entranceServer.Shutdown() } @@ -285,7 +287,7 @@ func wait() { } func preventClose(text string) { - if config.ErupeConfig.DisableSoftCrash { + if _config.ErupeConfig.DisableSoftCrash { os.Exit(0) } fmt.Println("\nFailed to start Erupe:\n" + text) diff --git a/network/mhfpacket/msg_mhf_enumerate_quest.go b/network/mhfpacket/msg_mhf_enumerate_quest.go index 7bf1e1355..5961cf152 100644 --- a/network/mhfpacket/msg_mhf_enumerate_quest.go +++ b/network/mhfpacket/msg_mhf_enumerate_quest.go @@ -2,6 +2,7 @@ package mhfpacket import ( "errors" + _config "erupe-ce/config" "erupe-ce/common/byteframe" "erupe-ce/network" @@ -30,7 +31,9 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli m.World = bf.ReadUint8() m.Counter = bf.ReadUint16() m.Offset = bf.ReadUint16() - m.Unk4 = bf.ReadUint8() + if _config.ErupeConfig.ClientMode != _config.Z1 { + m.Unk4 = bf.ReadUint8() + } return nil } diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 7c961b5e9..3a1f9d031 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -35,16 +35,16 @@ const ( BroadcastTypeWorld = 0x0a ) -var commands map[string]config.Command +var commands map[string]_config.Command func init() { - commands = make(map[string]config.Command) + commands = make(map[string]_config.Command) zapConfig := zap.NewDevelopmentConfig() zapConfig.DisableCaller = true zapLogger, _ := zapConfig.Build() defer zapLogger.Sync() logger := zapLogger.Named("commands") - cmds := config.ErupeConfig.Commands + cmds := _config.ErupeConfig.Commands for _, cmd := range cmds { commands[cmd.Name] = cmd if cmd.Enabled { @@ -55,7 +55,7 @@ func init() { } } -func sendDisabledCommandMessage(s *Session, cmd config.Command) { +func sendDisabledCommandMessage(s *Session, cmd _config.Command) { sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDisabled"], cmd.Name)) } diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index a53d4c42a..320d459a6 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -5,6 +5,7 @@ import ( "errors" "erupe-ce/common/bfutil" "erupe-ce/common/stringsupport" + _config "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/server/channelserver/compression/nullcomp" @@ -12,7 +13,8 @@ import ( ) const ( - pointerGender = 0x51 // +1 + pointerGender = 0x51 // +1 + pointerRP = 0x22D16 // +2 pointerHouseTier = 0x1FB6C // +5 pointerHouseData = 0x1FE01 // +195 @@ -26,6 +28,19 @@ const ( pointerHRP = 0x1FDF6 // +2 pointerGRP = 0x1FDFC // +4 pointerKQF = 0x23D20 // +8 + + pointerRPZ = 0x1A076 + pointerHouseTierZ = 0x16ECC + pointerHouseDataZ = 0x17161 + pointerBookshelfDataZ = 0x195F8 + pointerGalleryDataZ = 0x19680 + pointerToreDataZ = 0x17014 + pointerGardenDataZ = 0x19FB8 + pointerWeaponTypeZ = 0x16A75 + pointerWeaponIDZ = 0x1696A + pointerHRPZ = 0x17156 + pointerGRPZ = 0x1715C + pointerKQFZ = 0x1B080 ) type CharacterSaveData struct { @@ -81,10 +96,6 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) return nil, err } - if len(saveData.decompSave) < pointerKQF { - return nil, err - } - saveData.updateStructWithSaveData() return saveData, nil @@ -137,8 +148,13 @@ func (save *CharacterSaveData) Decompress() error { func (save *CharacterSaveData) updateSaveDataWithStruct() { rpBytes := make([]byte, 2) binary.LittleEndian.PutUint16(rpBytes, save.RP) - copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) - copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) + if _config.ErupeConfig.ClientMode == _config.ZZ { + copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) + copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) + } else { + copy(save.decompSave[pointerRPZ:pointerRPZ+2], rpBytes) + copy(save.decompSave[pointerKQFZ:pointerKQFZ+8], save.KQF) + } } // This will update the save struct with the values stored in the character save @@ -150,20 +166,37 @@ func (save *CharacterSaveData) updateStructWithSaveData() { save.Gender = false } if !save.IsNewCharacter { - save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2]) - save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5] - save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195] - save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576] - save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748] - save.ToreData = save.decompSave[pointerToreData : pointerToreData+240] - save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68] - save.WeaponType = save.decompSave[pointerWeaponType] - save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2]) - save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2]) - if save.HRP == uint16(999) { - save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4])) + if _config.ErupeConfig.ClientMode == _config.ZZ { + save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2]) + save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5] + save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195] + save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576] + save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748] + save.ToreData = save.decompSave[pointerToreData : pointerToreData+240] + save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68] + save.WeaponType = save.decompSave[pointerWeaponType] + save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2]) + save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2]) + if save.HRP == uint16(999) { + save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4])) + } + save.KQF = save.decompSave[pointerKQF : pointerKQF+8] + } else { + save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRPZ : pointerRPZ+2]) + save.HouseTier = save.decompSave[pointerHouseTierZ : pointerHouseTierZ+5] + save.HouseData = save.decompSave[pointerHouseDataZ : pointerHouseDataZ+195] + save.BookshelfData = save.decompSave[pointerBookshelfDataZ : pointerBookshelfDataZ+5576] + save.GalleryData = save.decompSave[pointerGalleryDataZ : pointerGalleryDataZ+1748] + save.ToreData = save.decompSave[pointerToreDataZ : pointerToreDataZ+240] + save.GardenData = save.decompSave[pointerGardenDataZ : pointerGardenDataZ+68] + save.WeaponType = save.decompSave[pointerWeaponTypeZ] + save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponIDZ : pointerWeaponIDZ+2]) + save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRPZ : pointerHRPZ+2]) + if save.HRP == uint16(999) { + save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRPZ : pointerGRPZ+4])) + } + save.KQF = save.decompSave[pointerKQFZ : pointerKQFZ+8] } - save.KQF = save.decompSave[pointerKQF : pointerKQF+8] } return } diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index 0daabe70c..10d0c0a2b 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -3,6 +3,7 @@ package channelserver import ( "encoding/hex" "erupe-ce/common/stringsupport" + _config "erupe-ce/config" "time" "erupe-ce/common/byteframe" @@ -80,7 +81,10 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint32(id) - for _, timestamp := range timestamps { + for i, timestamp := range timestamps { + if s.server.erupeConfig.ClientMode == _config.Z1 && i == 4 { + continue + } bf.WriteUint32(timestamp) } diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index bba4c1065..ffc1b895f 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -2,6 +2,7 @@ package channelserver import ( "erupe-ce/common/token" + _config "erupe-ce/config" "math" "time" @@ -90,14 +91,18 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { } func generateFeatureWeapons(count int) activeFeature { - if count > 14 { - count = 14 + max := 14 + if _config.ErupeConfig.ClientMode != _config.ZZ { + max = 13 + } + if count > max { + count = max } nums := make([]int, 0) var result int for len(nums) < count { rng := token.RNG() - num := rng.Intn(14) + num := rng.Intn(max) exist := false for _, v := range nums { if v == num { diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 09520d8c4..ec58c7487 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "encoding/json" "errors" + _config "erupe-ce/config" "fmt" "math" "sort" @@ -1390,7 +1391,12 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(member.CharID) bf.WriteUint16(member.HRP) bf.WriteUint16(member.GR) - bf.WriteUint16(member.WeaponID) + if s.server.erupeConfig.ClientMode != _config.ZZ { + // Magnet Spike crash workaround + bf.WriteUint16(0) + } else { + bf.WriteUint16(member.WeaponID) + } if member.WeaponType == 1 || member.WeaponType == 5 || member.WeaponType == 10 { // If weapon is ranged bf.WriteUint8(7) } else { diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index 309ed1af8..dccece844 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -22,7 +22,7 @@ type Config struct { Logger *zap.Logger DB *sqlx.DB DiscordBot *discordbot.DiscordBot - ErupeConfig *config.Config + ErupeConfig *_config.Config Name string Enable bool } @@ -43,7 +43,7 @@ type Server struct { Port uint16 logger *zap.Logger db *sqlx.DB - erupeConfig *config.Config + erupeConfig *_config.Config acceptConns chan net.Conn deleteConns chan net.Conn sessions map[net.Conn]*Session diff --git a/server/discordbot/discord_bot.go b/server/discordbot/discord_bot.go index fc5c41ce8..c082faf70 100644 --- a/server/discordbot/discord_bot.go +++ b/server/discordbot/discord_bot.go @@ -9,14 +9,14 @@ import ( type DiscordBot struct { Session *discordgo.Session - config *config.Config + config *_config.Config logger *zap.Logger MainGuild *discordgo.Guild RealtimeChannel *discordgo.Channel } type Options struct { - Config *config.Config + Config *_config.Config Logger *zap.Logger } diff --git a/server/entranceserver/entrance_server.go b/server/entranceserver/entrance_server.go index c0a4e852b..8b06be0e0 100644 --- a/server/entranceserver/entrance_server.go +++ b/server/entranceserver/entrance_server.go @@ -18,7 +18,7 @@ import ( type Server struct { sync.Mutex logger *zap.Logger - erupeConfig *config.Config + erupeConfig *_config.Config db *sqlx.DB listener net.Listener isShuttingDown bool @@ -28,7 +28,7 @@ type Server struct { type Config struct { Logger *zap.Logger DB *sqlx.DB - ErupeConfig *config.Config + ErupeConfig *_config.Config } // NewServer creates a new Server type. @@ -68,7 +68,7 @@ func (s *Server) Shutdown() { s.listener.Close() } -//acceptClients handles accepting new clients in a loop. +// acceptClients handles accepting new clients in a loop. func (s *Server) acceptClients() { for { conn, err := s.listener.Accept() diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 2d13709db..ac63a8ad5 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -3,13 +3,13 @@ package entranceserver import ( "encoding/binary" "encoding/hex" + _config "erupe-ce/config" "fmt" "net" "erupe-ce/common/stringsupport" "erupe-ce/common/byteframe" - "erupe-ce/config" "erupe-ce/server/channelserver" ) @@ -19,11 +19,17 @@ var season uint8 // Server Channels var currentplayers uint16 -func encodeServerInfo(config *config.Config, s *Server, local bool) []byte { +func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { serverInfos := config.Entrance.Entries bf := byteframe.NewByteFrame() for serverIdx, si := range serverInfos { + // Prevent MezFes Worlds displaying on Z1 + if config.ClientMode == _config.Z1 { + if si.Type == 6 { + continue + } + } sid := (4096 + serverIdx*256) + 16 err := s.db.QueryRow("SELECT season FROM servers WHERE server_id=$1", sid).Scan(&season) if err != nil { @@ -91,8 +97,17 @@ func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byt return bf.Data() } -func makeSv2Resp(config *config.Config, s *Server, local bool) []byte { +func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte { serverInfos := config.Entrance.Entries + // Decrease by the number of MezFes Worlds + var mf int + if config.ClientMode == _config.Z1 { + for _, si := range serverInfos { + if si.Type == 6 { + mf++ + } + } + } rawServerData := encodeServerInfo(config, s, local) if s.erupeConfig.DevMode && s.erupeConfig.DevModeOptions.LogOutboundMessages { @@ -100,7 +115,7 @@ func makeSv2Resp(config *config.Config, s *Server, local bool) []byte { } bf := byteframe.NewByteFrame() - bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)), 0x00)) + bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-mf), 0x00)) return bf.Data() } diff --git a/server/signserver/sign_server.go b/server/signserver/sign_server.go index fd4bd9bed..f93a6459a 100644 --- a/server/signserver/sign_server.go +++ b/server/signserver/sign_server.go @@ -16,14 +16,14 @@ import ( type Config struct { Logger *zap.Logger DB *sqlx.DB - ErupeConfig *config.Config + ErupeConfig *_config.Config } // Server is a MHF sign server. type Server struct { sync.Mutex logger *zap.Logger - erupeConfig *config.Config + erupeConfig *_config.Config sessions map[int]*Session db *sqlx.DB listener net.Listener diff --git a/server/signv2server/signv2_server.go b/server/signv2server/signv2_server.go index c00a4a641..c6db00b09 100644 --- a/server/signv2server/signv2_server.go +++ b/server/signv2server/signv2_server.go @@ -18,14 +18,14 @@ import ( type Config struct { Logger *zap.Logger DB *sqlx.DB - ErupeConfig *config.Config + ErupeConfig *_config.Config } // Server is the MHF custom launcher sign server. type Server struct { sync.Mutex logger *zap.Logger - erupeConfig *config.Config + erupeConfig *_config.Config db *sqlx.DB httpServer *http.Server isShuttingDown bool From a9c3f82903ec24dc31726081c5b7277fc0aee064 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 18 Jun 2023 20:33:39 +1000 Subject: [PATCH 35/99] add ClientMode config option --- server/channelserver/handlers_cast_binary.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 3a1f9d031..3e950657f 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -211,7 +211,7 @@ func parseChatCommand(s *Session, command string) { for _, course := range mhfcourse.Courses() { for _, alias := range course.Aliases() { if strings.ToLower(name) == strings.ToLower(alias) { - if slices.Contains(s.server.erupeConfig.Courses, config.Course{Name: course.Aliases()[0], Enabled: true}) { + if slices.Contains(s.server.erupeConfig.Courses, _config.Course{Name: course.Aliases()[0], Enabled: true}) { var delta, rightsInt uint32 if mhfcourse.CourseExists(course.ID, s.courses) { ei := slices.IndexFunc(s.courses, func(c mhfcourse.Course) bool { From 5464594c9857b23907e530be33a7f1b5948ecba8 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 18 Jun 2023 20:38:04 +1000 Subject: [PATCH 36/99] rename Zone to Block --- network/mhfpacket/msg_mhf_post_tower_info.go | 4 ++-- patch-schema/tower.sql | 3 ++- server/channelserver/handlers_tower.go | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/network/mhfpacket/msg_mhf_post_tower_info.go b/network/mhfpacket/msg_mhf_post_tower_info.go index a574f6c6e..3808777e5 100644 --- a/network/mhfpacket/msg_mhf_post_tower_info.go +++ b/network/mhfpacket/msg_mhf_post_tower_info.go @@ -19,7 +19,7 @@ type MsgMhfPostTowerInfo struct { Cost int32 Unk6 int32 Unk7 int32 - Zone1 int32 + Block1 int32 Unk9 int64 } @@ -39,7 +39,7 @@ func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie m.Cost = bf.ReadInt32() m.Unk6 = bf.ReadInt32() m.Unk7 = bf.ReadInt32() - m.Zone1 = bf.ReadInt32() + m.Block1 = bf.ReadInt32() m.Unk9 = bf.ReadInt64() return nil } diff --git a/patch-schema/tower.sql b/patch-schema/tower.sql index d1a6c1556..cab01c558 100644 --- a/patch-schema/tower.sql +++ b/patch-schema/tower.sql @@ -5,7 +5,8 @@ CREATE TABLE IF NOT EXISTS tower ( tr INT, trp INT, tsp INT, - zone1 INT, + block1 INT, + block2 INT, skills TEXT DEFAULT '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,0,0,0,0,0,0,0,0,0,0,0', gems TEXT DEFAULT '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' ); diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 36e2cf45e..2bc8bf72e 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -24,10 +24,10 @@ type TowerInfoHistory struct { } type TowerInfoLevel struct { - Zone1 int32 - Unk1 int32 - Unk2 int32 - Unk3 int32 + Floors int32 + Unk1 int32 + Unk2 int32 + Unk3 int32 } func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { @@ -44,13 +44,13 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { TRP: []TowerInfoTRP{{0, 0}}, Skill: []TowerInfoSkill{{0, make([]int16, 40)}}, History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}}, - Level: []TowerInfoLevel{{0, 0, 0, 0}}, + Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}}, } tempSkills := "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,0,0,0,0,0,0,0,0,0,0,0" - err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(zone1, 0), skills FROM tower WHERE char_id=$1 - `, s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Zone1, &tempSkills) + err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), skills FROM tower WHERE char_id=$1 + `, s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills) if err != nil { s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID) } @@ -90,7 +90,7 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { case 5: for _, level := range towerInfo.Level { bf := byteframe.NewByteFrame() - bf.WriteInt32(level.Zone1) + bf.WriteInt32(level.Floors) bf.WriteInt32(level.Unk1) bf.WriteInt32(level.Unk2) bf.WriteInt32(level.Unk3) @@ -114,7 +114,7 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { zap.Int32("Cost", pkt.Cost), zap.Int32("Unk6", pkt.Unk6), zap.Int32("Unk7", pkt.Unk7), - zap.Int32("Zone1", pkt.Zone1), + zap.Int32("Block1", pkt.Block1), zap.Int64("Unk9", pkt.Unk9), ) } @@ -125,7 +125,7 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills) s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID) case 7: - s.server.db.Exec(`UPDATE tower SET tr=$1, trp=trp+$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.TR, pkt.TRP, pkt.Zone1, s.charID) + s.server.db.Exec(`UPDATE tower SET tr=$1, trp=trp+$2, block1=block1+$3 WHERE char_id=$4`, pkt.TR, pkt.TRP, pkt.Block1, s.charID) } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } From 09295921104c22ffc8b4fae0a33f3864bbe8d040 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 19 Jun 2023 22:43:07 +1000 Subject: [PATCH 37/99] rework PaperData --- server/channelserver/handlers_data.go | 1386 ++++++++++++++++++++++++- 1 file changed, 1352 insertions(+), 34 deletions(-) diff --git a/server/channelserver/handlers_data.go b/server/channelserver/handlers_data.go index 64b14072c..ac8f7bf5c 100644 --- a/server/channelserver/handlers_data.go +++ b/server/channelserver/handlers_data.go @@ -1,12 +1,12 @@ package channelserver import ( - "encoding/hex" "erupe-ce/common/stringsupport" "fmt" "io" "os" "path/filepath" + "time" "erupe-ce/common/byteframe" "erupe-ce/network/mhfpacket" @@ -310,43 +310,1361 @@ func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) { doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } +var paperGiftData = map[uint32][]PaperGift{ + 6001: { + {11159, 1, 1, 5000}, + {11160, 1, 1, 3350}, + {11161, 1, 1, 1500}, + {11162, 1, 1, 100}, + {11163, 1, 1, 50}, + }, + 6002: { + {11159, 2, 1, 1800}, + {11160, 2, 1, 1200}, + {11161, 2, 1, 500}, + {11162, 1, 1, 50}, + {11037, 1, 1, 150}, + {11038, 1, 1, 150}, + {11044, 1, 1, 150}, + {11057, 1, 1, 150}, + {11059, 1, 1, 150}, + {11079, 1, 1, 150}, + {11098, 1, 1, 150}, + {11104, 1, 1, 150}, + {11117, 1, 1, 150}, + {11128, 1, 1, 150}, + {11133, 1, 1, 150}, + {11137, 1, 1, 150}, + {11143, 1, 1, 150}, + {11132, 1, 1, 150}, + {11039, 1, 1, 150}, + {11040, 1, 1, 150}, + {11049, 1, 1, 150}, + {11061, 1, 1, 150}, + {11063, 1, 1, 150}, + {11077, 1, 1, 150}, + {11099, 1, 1, 150}, + {11105, 1, 1, 150}, + {11129, 1, 1, 150}, + {11130, 1, 1, 150}, + {11131, 1, 1, 150}, + {11139, 1, 1, 150}, + {11145, 1, 1, 150}, + {11096, 1, 1, 150}, + {11041, 1, 1, 150}, + {11047, 1, 1, 150}, + {11054, 1, 1, 150}, + {11065, 1, 1, 150}, + {11068, 1, 1, 150}, + {11075, 1, 1, 150}, + {11100, 1, 1, 150}, + {11106, 1, 1, 150}, + {11119, 1, 1, 150}, + {11135, 1, 1, 150}, + {11136, 1, 1, 150}, + {11138, 1, 1, 150}, + {11088, 1, 1, 150}, + {10370, 1, 1, 150}, + {10368, 1, 1, 150}, + }, + 6010: { + {11159, 1, 1, 3700}, + {11160, 1, 1, 2900}, + {11161, 1, 1, 1300}, + {11453, 1, 1, 250}, + {11454, 1, 1, 250}, + {12055, 1, 1, 250}, + {12065, 1, 1, 250}, + {12058, 1, 1, 250}, + {12068, 1, 1, 250}, + {11774, 1, 1, 200}, + {11773, 1, 1, 400}, + }, + 6011: { + {11159, 1, 1, 3700}, + {11160, 1, 1, 2900}, + {11161, 1, 1, 1300}, + {11453, 1, 1, 250}, + {11454, 1, 1, 250}, + {12055, 1, 1, 250}, + {12065, 1, 1, 250}, + {12058, 1, 1, 250}, + {12068, 1, 1, 250}, + {11774, 1, 1, 200}, + {11773, 1, 1, 400}, + }, + 6012: { + {11159, 2, 1, 3500}, + {11160, 2, 1, 2900}, + {11161, 2, 1, 1300}, + {12508, 1, 1, 400}, + {11453, 1, 1, 200}, + {11454, 1, 1, 200}, + {12055, 1, 1, 200}, + {12065, 1, 1, 200}, + {12058, 1, 1, 200}, + {12068, 1, 1, 200}, + {11775, 1, 1, 400}, + {11776, 1, 1, 200}, + {11777, 1, 1, 100}, + }, + 7001: { + {11037, 1, 1, 290}, + {11038, 1, 1, 270}, + {11044, 1, 1, 270}, + {11057, 1, 1, 290}, + {11059, 1, 1, 290}, + {11079, 1, 1, 290}, + {11098, 1, 1, 280}, + {11104, 1, 1, 300}, + {11117, 1, 1, 280}, + {11128, 1, 1, 290}, + {11133, 1, 1, 290}, + {11137, 1, 1, 300}, + {11143, 1, 1, 290}, + {11132, 1, 1, 270}, + {11042, 1, 1, 47}, + {11045, 1, 1, 47}, + {11064, 1, 1, 47}, + {11062, 1, 1, 47}, + {11070, 1, 1, 48}, + {11101, 1, 1, 47}, + {11108, 1, 1, 47}, + {11109, 1, 1, 47}, + {11120, 1, 1, 47}, + {11122, 1, 1, 47}, + {11134, 1, 1, 47}, + {11141, 1, 1, 47}, + {11084, 1, 1, 47}, + {11087, 1, 1, 47}, + {11094, 1, 1, 47}, + {10374, 1, 1, 47}, + {10375, 1, 1, 47}, + {11051, 1, 1, 17}, + {11071, 1, 1, 16}, + {11076, 1, 1, 16}, + {11102, 1, 1, 17}, + {11124, 1, 1, 17}, + {11090, 1, 1, 17}, + {11159, 1, 1, 1200}, + {11159, 2, 1, 650}, + {11160, 1, 1, 800}, + {11160, 2, 1, 300}, + {11161, 1, 1, 100}, + {11161, 2, 1, 50}, + {11164, 1, 1, 100}, + {11162, 1, 1, 100}, + {11163, 1, 1, 100}, + {11158, 1, 1, 300}, + {11463, 1, 1, 300}, + {11356, 1, 1, 300}, + {11464, 1, 1, 300}, + {11357, 1, 1, 500}, + {11039, 1, 2, 300}, + {11040, 1, 2, 270}, + {11049, 1, 2, 300}, + {11061, 1, 2, 290}, + {11063, 1, 2, 290}, + {11077, 1, 2, 290}, + {11099, 1, 2, 280}, + {11105, 1, 2, 300}, + {11129, 1, 2, 250}, + {11130, 1, 2, 300}, + {11131, 1, 2, 280}, + {11139, 1, 2, 290}, + {11145, 1, 2, 260}, + {11096, 1, 2, 300}, + {11046, 1, 2, 47}, + {11066, 1, 2, 47}, + {11067, 1, 2, 47}, + {11072, 1, 2, 47}, + {11082, 1, 2, 47}, + {11103, 1, 2, 47}, + {11110, 1, 2, 47}, + {11112, 1, 2, 47}, + {11114, 1, 2, 47}, + {11115, 1, 2, 47}, + {11121, 1, 2, 47}, + {11144, 1, 2, 48}, + {11085, 1, 2, 47}, + {11089, 1, 2, 47}, + {11091, 1, 2, 47}, + {10376, 1, 2, 47}, + {10377, 1, 2, 47}, + {11127, 1, 2, 17}, + {11069, 1, 2, 17}, + {11142, 1, 2, 17}, + {11078, 1, 2, 17}, + {11056, 1, 2, 16}, + {11092, 1, 2, 16}, + {11159, 1, 2, 1200}, + {11159, 2, 2, 650}, + {11160, 1, 2, 800}, + {11160, 2, 2, 300}, + {11161, 1, 2, 100}, + {11161, 2, 2, 50}, + {11164, 1, 2, 100}, + {11162, 1, 2, 100}, + {11163, 1, 2, 100}, + {11158, 1, 2, 300}, + {11463, 1, 2, 300}, + {11356, 1, 2, 300}, + {11464, 1, 2, 300}, + {11357, 1, 2, 500}, + {11041, 1, 3, 266}, + {11047, 1, 3, 266}, + {11054, 1, 3, 266}, + {11065, 1, 3, 266}, + {11068, 1, 3, 266}, + {11075, 1, 3, 266}, + {11100, 1, 3, 266}, + {11106, 1, 3, 266}, + {11119, 1, 3, 266}, + {11135, 1, 3, 268}, + {11136, 1, 3, 268}, + {11138, 1, 3, 268}, + {11088, 1, 3, 268}, + {10370, 1, 3, 266}, + {10368, 1, 3, 268}, + {11043, 1, 3, 50}, + {11048, 1, 3, 50}, + {11050, 1, 3, 50}, + {11058, 1, 3, 50}, + {11060, 1, 3, 50}, + {11074, 1, 3, 50}, + {11107, 1, 3, 50}, + {11111, 1, 3, 50}, + {11113, 1, 3, 50}, + {11118, 1, 3, 50}, + {11126, 1, 3, 50}, + {11140, 1, 3, 50}, + {11086, 1, 3, 50}, + {11095, 1, 3, 50}, + {11055, 1, 3, 50}, + {10378, 1, 3, 50}, + {11052, 1, 3, 15}, + {11073, 1, 3, 15}, + {11146, 1, 3, 15}, + {11116, 1, 3, 15}, + {11123, 1, 3, 15}, + {11097, 1, 3, 15}, + {10367, 1, 3, 15}, + {10371, 1, 3, 15}, + {10373, 1, 3, 15}, + {10778, 1, 3, 375}, + {11209, 1, 3, 375}, + {10813, 1, 3, 375}, + {11389, 1, 3, 375}, + {11159, 1, 3, 1000}, + {11159, 2, 3, 250}, + {11160, 1, 3, 700}, + {11160, 2, 3, 175}, + {11161, 1, 3, 300}, + {11161, 2, 3, 75}, + {11465, 1, 3, 53}, + {11466, 1, 3, 27}, + {11467, 1, 3, 266}, + {11468, 1, 3, 533}, + {11469, 1, 3, 186}, + }, + 7002: { + {11037, 1, 1, 100}, + {11038, 1, 1, 100}, + {11044, 1, 1, 100}, + {11057, 1, 1, 100}, + {11059, 1, 1, 100}, + {11079, 1, 1, 100}, + {11098, 1, 1, 100}, + {11104, 1, 1, 100}, + {11117, 1, 1, 100}, + {11128, 1, 1, 100}, + {11133, 1, 1, 100}, + {11137, 1, 1, 100}, + {11143, 1, 1, 100}, + {11132, 1, 1, 100}, + {11042, 1, 1, 60}, + {11045, 1, 1, 60}, + {11064, 1, 1, 60}, + {11062, 1, 1, 60}, + {11070, 1, 1, 60}, + {11101, 1, 1, 60}, + {11108, 1, 1, 60}, + {11109, 1, 1, 60}, + {11120, 1, 1, 60}, + {11122, 1, 1, 60}, + {11134, 1, 1, 60}, + {11141, 1, 1, 60}, + {11084, 1, 1, 60}, + {11087, 1, 1, 60}, + {11094, 1, 1, 60}, + {10374, 1, 1, 60}, + {10375, 1, 1, 60}, + {11051, 1, 1, 20}, + {11071, 1, 1, 20}, + {11076, 1, 1, 20}, + {11102, 1, 1, 20}, + {11124, 1, 1, 20}, + {11090, 1, 1, 20}, + {11164, 1, 1, 400}, + {11162, 1, 1, 200}, + {11163, 1, 1, 200}, + {11463, 1, 1, 100}, + {11464, 1, 1, 150}, + {10355, 1, 1, 150}, + {12506, 1, 1, 200}, + {12507, 1, 1, 300}, + {12508, 1, 1, 900}, + {13629, 1, 1, 350}, + {13628, 1, 1, 200}, + {11356, 1, 1, 100}, + {11357, 1, 1, 150}, + {12014, 1, 1, 250}, + {12016, 1, 1, 400}, + {12015, 1, 1, 410}, + {11159, 2, 1, 500}, + {11159, 4, 1, 500}, + {11159, 6, 1, 500}, + {11160, 2, 1, 400}, + {11160, 4, 1, 400}, + {11160, 6, 1, 400}, + {11161, 2, 1, 100}, + {11161, 4, 1, 100}, + {11161, 6, 1, 100}, + {11039, 1, 2, 100}, + {11040, 1, 2, 100}, + {11049, 1, 2, 100}, + {11061, 1, 2, 100}, + {11063, 1, 2, 100}, + {11077, 1, 2, 100}, + {11099, 1, 2, 100}, + {11105, 1, 2, 100}, + {11129, 1, 2, 100}, + {11130, 1, 2, 100}, + {11131, 1, 2, 100}, + {11139, 1, 2, 100}, + {11145, 1, 2, 100}, + {11096, 1, 2, 100}, + {11046, 1, 2, 60}, + {11066, 1, 2, 60}, + {11067, 1, 2, 60}, + {11072, 1, 2, 60}, + {11082, 1, 2, 60}, + {11103, 1, 2, 60}, + {11110, 1, 2, 60}, + {11112, 1, 2, 60}, + {11114, 1, 2, 60}, + {11115, 1, 2, 60}, + {11121, 1, 2, 60}, + {11144, 1, 2, 60}, + {11085, 1, 2, 60}, + {11089, 1, 2, 60}, + {11091, 1, 2, 60}, + {10376, 1, 2, 60}, + {10377, 1, 2, 60}, + {11127, 1, 2, 20}, + {11069, 1, 2, 20}, + {11142, 1, 2, 20}, + {11078, 1, 2, 20}, + {11056, 1, 2, 20}, + {11092, 1, 2, 20}, + {11164, 1, 2, 400}, + {11162, 1, 2, 200}, + {11163, 1, 2, 200}, + {11463, 1, 2, 250}, + {11464, 1, 2, 350}, + {12506, 1, 2, 150}, + {12507, 1, 2, 200}, + {12508, 1, 2, 350}, + {13629, 1, 2, 250}, + {13628, 1, 2, 200}, + {10355, 1, 2, 400}, + {11158, 1, 2, 100}, + {11356, 1, 2, 100}, + {11357, 1, 2, 100}, + {12014, 1, 2, 300}, + {12016, 1, 2, 450}, + {12015, 1, 2, 460}, + {11159, 2, 2, 500}, + {11159, 4, 2, 500}, + {11159, 6, 2, 500}, + {11160, 2, 2, 400}, + {11160, 4, 2, 400}, + {11160, 6, 2, 400}, + {11161, 2, 2, 100}, + {11161, 4, 2, 100}, + {11161, 6, 2, 100}, + {11041, 1, 3, 120}, + {11047, 1, 3, 120}, + {11054, 1, 3, 120}, + {11065, 1, 3, 120}, + {11068, 1, 3, 120}, + {11075, 1, 3, 120}, + {11100, 1, 3, 120}, + {11106, 1, 3, 120}, + {11119, 1, 3, 120}, + {11135, 1, 3, 120}, + {11136, 1, 3, 120}, + {11138, 1, 3, 120}, + {11088, 1, 3, 120}, + {10370, 1, 3, 120}, + {10368, 1, 3, 120}, + {11043, 1, 3, 65}, + {11048, 1, 3, 65}, + {11050, 1, 3, 65}, + {11058, 1, 3, 65}, + {11060, 1, 3, 65}, + {11074, 1, 3, 65}, + {11107, 1, 3, 65}, + {11111, 1, 3, 65}, + {11113, 1, 3, 65}, + {11118, 1, 3, 65}, + {11126, 1, 3, 65}, + {11140, 1, 3, 65}, + {11086, 1, 3, 65}, + {11095, 1, 3, 65}, + {11055, 1, 3, 65}, + {10378, 1, 3, 65}, + {11052, 1, 3, 15}, + {11073, 1, 3, 15}, + {11146, 1, 3, 15}, + {11116, 1, 3, 15}, + {11123, 1, 3, 15}, + {11097, 1, 3, 15}, + {10367, 1, 3, 15}, + {10371, 1, 3, 15}, + {10373, 1, 3, 15}, + {10778, 3, 3, 490}, + {11209, 3, 3, 490}, + {10813, 3, 3, 490}, + {11389, 3, 3, 490}, + {12046, 3, 3, 500}, + {12503, 3, 3, 500}, + {11159, 2, 3, 500}, + {11159, 4, 3, 500}, + {11159, 6, 3, 500}, + {11160, 2, 3, 400}, + {11160, 4, 3, 400}, + {11160, 6, 3, 400}, + {11161, 2, 3, 100}, + {11161, 4, 3, 100}, + {11161, 6, 3, 100}, + {11465, 1, 3, 53}, + {11466, 1, 3, 27}, + {11467, 1, 3, 266}, + {11468, 1, 3, 533}, + {11469, 1, 3, 186}, + }, + 7011: { + {11037, 1, 1, 290}, + {11038, 1, 1, 270}, + {11044, 1, 1, 270}, + {11057, 1, 1, 290}, + {11059, 1, 1, 290}, + {11079, 1, 1, 290}, + {11098, 1, 1, 280}, + {11104, 1, 1, 300}, + {11117, 1, 1, 280}, + {11128, 1, 1, 290}, + {11133, 1, 1, 290}, + {11137, 1, 1, 300}, + {11143, 1, 1, 290}, + {11132, 1, 1, 270}, + {11042, 1, 1, 47}, + {11045, 1, 1, 47}, + {11064, 1, 1, 47}, + {11062, 1, 1, 47}, + {11070, 1, 1, 48}, + {11101, 1, 1, 47}, + {11108, 1, 1, 47}, + {11109, 1, 1, 47}, + {11120, 1, 1, 47}, + {11122, 1, 1, 47}, + {11134, 1, 1, 47}, + {11141, 1, 1, 47}, + {11084, 1, 1, 47}, + {11087, 1, 1, 47}, + {11094, 1, 1, 47}, + {10374, 1, 1, 47}, + {10375, 1, 1, 47}, + {11051, 1, 1, 17}, + {11071, 1, 1, 16}, + {11076, 1, 1, 16}, + {11102, 1, 1, 17}, + {11124, 1, 1, 17}, + {11090, 1, 1, 17}, + {11159, 1, 1, 1200}, + {11159, 2, 1, 650}, + {11160, 1, 1, 800}, + {11160, 2, 1, 300}, + {11161, 1, 1, 100}, + {11161, 2, 1, 50}, + {11164, 1, 1, 100}, + {11162, 1, 1, 100}, + {11163, 1, 1, 100}, + {11158, 1, 1, 300}, + {11463, 1, 1, 300}, + {11356, 1, 1, 300}, + {11464, 1, 1, 300}, + {11357, 1, 1, 500}, + {11039, 1, 2, 300}, + {11040, 1, 2, 270}, + {11049, 1, 2, 300}, + {11061, 1, 2, 290}, + {11063, 1, 2, 290}, + {11077, 1, 2, 290}, + {11099, 1, 2, 280}, + {11105, 1, 2, 300}, + {11129, 1, 2, 250}, + {11130, 1, 2, 300}, + {11131, 1, 2, 280}, + {11139, 1, 2, 290}, + {11145, 1, 2, 260}, + {11096, 1, 2, 300}, + {11046, 1, 2, 47}, + {11066, 1, 2, 47}, + {11067, 1, 2, 47}, + {11072, 1, 2, 47}, + {11082, 1, 2, 47}, + {11103, 1, 2, 47}, + {11110, 1, 2, 47}, + {11112, 1, 2, 47}, + {11114, 1, 2, 47}, + {11115, 1, 2, 47}, + {11121, 1, 2, 47}, + {11144, 1, 2, 48}, + {11085, 1, 2, 47}, + {11089, 1, 2, 47}, + {11091, 1, 2, 47}, + {10376, 1, 2, 47}, + {10377, 1, 2, 47}, + {11127, 1, 2, 17}, + {11069, 1, 2, 17}, + {11142, 1, 2, 17}, + {11078, 1, 2, 17}, + {11056, 1, 2, 16}, + {11092, 1, 2, 16}, + {11159, 1, 2, 1200}, + {11159, 2, 2, 650}, + {11160, 1, 2, 800}, + {11160, 2, 2, 300}, + {11161, 1, 2, 100}, + {11161, 2, 2, 50}, + {11164, 1, 2, 100}, + {11162, 1, 2, 100}, + {11163, 1, 2, 100}, + {11158, 1, 2, 300}, + {11463, 1, 2, 300}, + {11356, 1, 2, 300}, + {11464, 1, 2, 300}, + {11357, 1, 2, 500}, + {11041, 1, 3, 266}, + {11047, 1, 3, 266}, + {11054, 1, 3, 266}, + {11065, 1, 3, 266}, + {11068, 1, 3, 266}, + {11075, 1, 3, 266}, + {11100, 1, 3, 266}, + {11106, 1, 3, 266}, + {11119, 1, 3, 266}, + {11135, 1, 3, 268}, + {11136, 1, 3, 268}, + {11138, 1, 3, 268}, + {11088, 1, 3, 268}, + {10370, 1, 3, 266}, + {10368, 1, 3, 268}, + {11043, 1, 3, 50}, + {11048, 1, 3, 50}, + {11050, 1, 3, 50}, + {11058, 1, 3, 50}, + {11060, 1, 3, 50}, + {11074, 1, 3, 50}, + {11107, 1, 3, 50}, + {11111, 1, 3, 50}, + {11113, 1, 3, 50}, + {11118, 1, 3, 50}, + {11126, 1, 3, 50}, + {11140, 1, 3, 50}, + {11086, 1, 3, 50}, + {11095, 1, 3, 50}, + {11055, 1, 3, 50}, + {10378, 1, 3, 50}, + {11052, 1, 3, 15}, + {11073, 1, 3, 15}, + {11146, 1, 3, 15}, + {11116, 1, 3, 15}, + {11123, 1, 3, 15}, + {11097, 1, 3, 15}, + {10367, 1, 3, 15}, + {10371, 1, 3, 15}, + {10373, 1, 3, 15}, + {10778, 1, 3, 375}, + {11209, 1, 3, 375}, + {10813, 1, 3, 375}, + {11389, 1, 3, 375}, + {11159, 1, 3, 1000}, + {11159, 2, 3, 250}, + {11160, 1, 3, 700}, + {11160, 2, 3, 175}, + {11161, 1, 3, 300}, + {11161, 2, 3, 75}, + {11465, 1, 3, 53}, + {11466, 1, 3, 27}, + {11467, 1, 3, 266}, + {11468, 1, 3, 533}, + {11469, 1, 3, 186}, + }, + 7012: { + {11037, 1, 1, 290}, + {11038, 1, 1, 270}, + {11044, 1, 1, 270}, + {11057, 1, 1, 290}, + {11059, 1, 1, 290}, + {11079, 1, 1, 290}, + {11098, 1, 1, 280}, + {11104, 1, 1, 300}, + {11117, 1, 1, 280}, + {11128, 1, 1, 290}, + {11133, 1, 1, 290}, + {11137, 1, 1, 300}, + {11143, 1, 1, 290}, + {11132, 1, 1, 270}, + {11042, 1, 1, 47}, + {11045, 1, 1, 47}, + {11064, 1, 1, 47}, + {11062, 1, 1, 47}, + {11070, 1, 1, 48}, + {11101, 1, 1, 47}, + {11108, 1, 1, 47}, + {11109, 1, 1, 47}, + {11120, 1, 1, 47}, + {11122, 1, 1, 47}, + {11134, 1, 1, 47}, + {11141, 1, 1, 47}, + {11084, 1, 1, 47}, + {11087, 1, 1, 47}, + {11094, 1, 1, 47}, + {10374, 1, 1, 47}, + {10375, 1, 1, 47}, + {11051, 1, 1, 17}, + {11071, 1, 1, 16}, + {11076, 1, 1, 16}, + {11102, 1, 1, 17}, + {11124, 1, 1, 17}, + {11090, 1, 1, 17}, + {11159, 1, 1, 1200}, + {11159, 2, 1, 650}, + {11160, 1, 1, 800}, + {11160, 2, 1, 300}, + {11161, 1, 1, 100}, + {11161, 2, 1, 50}, + {11164, 1, 1, 100}, + {11162, 1, 1, 100}, + {11163, 1, 1, 100}, + {11158, 1, 1, 300}, + {11463, 1, 1, 300}, + {11356, 1, 1, 300}, + {11464, 1, 1, 300}, + {11357, 1, 1, 500}, + {11039, 1, 2, 300}, + {11040, 1, 2, 270}, + {11049, 1, 2, 300}, + {11061, 1, 2, 290}, + {11063, 1, 2, 290}, + {11077, 1, 2, 290}, + {11099, 1, 2, 280}, + {11105, 1, 2, 300}, + {11129, 1, 2, 250}, + {11130, 1, 2, 300}, + {11131, 1, 2, 280}, + {11139, 1, 2, 290}, + {11145, 1, 2, 260}, + {11096, 1, 2, 300}, + {11046, 1, 2, 47}, + {11066, 1, 2, 47}, + {11067, 1, 2, 47}, + {11072, 1, 2, 47}, + {11082, 1, 2, 47}, + {11103, 1, 2, 47}, + {11110, 1, 2, 47}, + {11112, 1, 2, 47}, + {11114, 1, 2, 47}, + {11115, 1, 2, 47}, + {11121, 1, 2, 47}, + {11144, 1, 2, 48}, + {11085, 1, 2, 47}, + {11089, 1, 2, 47}, + {11091, 1, 2, 47}, + {10376, 1, 2, 47}, + {10377, 1, 2, 47}, + {11127, 1, 2, 17}, + {11069, 1, 2, 17}, + {11142, 1, 2, 17}, + {11078, 1, 2, 17}, + {11056, 1, 2, 16}, + {11092, 1, 2, 16}, + {11159, 1, 2, 1200}, + {11159, 2, 2, 650}, + {11160, 1, 2, 800}, + {11160, 2, 2, 300}, + {11161, 1, 2, 100}, + {11161, 2, 2, 50}, + {11164, 1, 2, 100}, + {11162, 1, 2, 100}, + {11163, 1, 2, 100}, + {11158, 1, 2, 300}, + {11463, 1, 2, 300}, + {11356, 1, 2, 300}, + {11464, 1, 2, 300}, + {11357, 1, 2, 500}, + {11041, 1, 3, 266}, + {11047, 1, 3, 266}, + {11054, 1, 3, 266}, + {11065, 1, 3, 266}, + {11068, 1, 3, 266}, + {11075, 1, 3, 266}, + {11100, 1, 3, 266}, + {11106, 1, 3, 266}, + {11119, 1, 3, 266}, + {11135, 1, 3, 268}, + {11136, 1, 3, 268}, + {11138, 1, 3, 268}, + {11088, 1, 3, 268}, + {10370, 1, 3, 266}, + {10368, 1, 3, 268}, + {11043, 1, 3, 50}, + {11048, 1, 3, 50}, + {11050, 1, 3, 50}, + {11058, 1, 3, 50}, + {11060, 1, 3, 50}, + {11074, 1, 3, 50}, + {11107, 1, 3, 50}, + {11111, 1, 3, 50}, + {11113, 1, 3, 50}, + {11118, 1, 3, 50}, + {11126, 1, 3, 50}, + {11140, 1, 3, 50}, + {11086, 1, 3, 50}, + {11095, 1, 3, 50}, + {11055, 1, 3, 50}, + {10378, 1, 3, 50}, + {11052, 1, 3, 15}, + {11073, 1, 3, 15}, + {11146, 1, 3, 15}, + {11116, 1, 3, 15}, + {11123, 1, 3, 15}, + {11097, 1, 3, 15}, + {10367, 1, 3, 15}, + {10371, 1, 3, 15}, + {10373, 1, 3, 15}, + {10778, 1, 3, 375}, + {11209, 1, 3, 375}, + {10813, 1, 3, 375}, + {11389, 1, 3, 375}, + {11159, 1, 3, 1000}, + {11159, 2, 3, 250}, + {11160, 1, 3, 700}, + {11160, 2, 3, 175}, + {11161, 1, 3, 300}, + {11161, 2, 3, 75}, + {11465, 1, 3, 53}, + {11466, 1, 3, 27}, + {11467, 1, 3, 266}, + {11468, 1, 3, 533}, + {11469, 1, 3, 186}, + }, +} + +type PaperMissionTimetable struct { + Start time.Time + End time.Time +} + +type PaperMissionData struct { + Unk0 uint8 + Unk1 uint8 + Unk2 int16 + Reward1ID uint16 + Reward1Quantity uint8 + Reward2ID uint16 + Reward2Quantity uint8 +} + +type PaperMission struct { + Timetables []PaperMissionTimetable + Data []PaperMissionData +} + +type PaperData struct { + Unk0 uint16 + Unk1 int16 + Unk2 int16 + Unk3 int16 + Unk4 int16 + Unk5 int16 + Unk6 int16 +} + +type PaperGift struct { + Unk0 uint16 + Unk1 uint8 + Unk2 uint8 + Unk3 uint16 +} + func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { - // if the game gets bad responses for this it breaks the ability to save pkt := p.(*mhfpacket.MsgMhfGetPaperData) - var data []byte - var err error - if pkt.Unk2 == 4 { - data, err = hex.DecodeString("0A218EAD000000000000000000000000") - } else if pkt.Unk2 == 5 { - data, err = hex.DecodeString("0A218EAD00000000000000000000003403E900010000000000000000000003E900020000000000000000000003EB00010064006400C80064000003EB00020096006400F00064000003EC000A270F002800000000000003ED000A01F4000000000000000003EF00010000000000000000000003F000C801900BB801900BB8000003F200010FA0000000000000000003F200020FA0000000000000000003F3000117703A984E2061A8753003F3000217703A984E2061A8753003F400011F40445C57E46B6C791803F400021F40445C57E46B6C791803F700010010001000100000000003F7000200100010001000000000044D000107E001F4000000000000044D000207E001F4000000000000044F0001000000000BB800000BB8044F0002000000000BB800000BB804500001000A270F00280000000004500002000A270F00280000000004510001000A01F400000000000004510002000A01F400000000000007D100010011003A0000000602BC07D100010014003A0000000300C807D100010016003A0000000700FA07D10001001B003A00000001006407D100010035003A0000000803E807D100010043003A0000000901F407D100010044003A00000002009607D10001004A003A0000000400C807D10001004B003A0000000501F407D10001004C003A0000000A032007D100010050003A0000000B038407D100010059003A0000000C025807D100020011003C0000000602BC07D100020014003C0000000300C807D100020016003C00000007015E07D10002001B003C00000001006407D100020027003C0000000D00C807D100020028003C0000000F025807D100020035003C0000000803E807D100020043003C0000000201F407D100020044003C00000009009607D10002004A003C0000000400C807D10002004B003C0000000501F407D10002004C003C0000000A032007D100020050003C0000000B038407D100020051003C0000000E038407D100020059003C0000000C025807D10002005E003C0000001003E8") - } else if pkt.Unk2 == 6 { - data, err = hex.DecodeString("0A218EAD0000000000000000000001A503EA00640000000000000000000003EE00012710271000000000000003EE000227104E2000000000000003F100140000000000000000000003F5000100010001006400C8012C03F5000100010002006400C8012C03F5000100020001012C006400C803F5000100020002012C006400C803F500010003000100C8012C006403F500010003000200C8012C006403F5000200010001012C006400C803F5000200010002012C006400C803F500020002000100C8012C006403F500020002000200C8012C006403F5000200030001006400C8012C03F5000200030002006400C8012C03F500030001000100C8012C006403F500030001000200C8012C006403F5000300020001006400C8012C03F5000300020002006400C8012C03F5000300030001012C006400C803F5000300030002012C006400C803F800010001005000000000000003F800010002005000000000000003F800010003005000000000000003F800020001005000000000000003F800020002005000000000000003F800020003005000000000000004B10001003C003200000000000004B10002003C003200000000000004B200010000000500320000000004B2000100060014003C0000000004B200010015002800460000000004B200010029007800500000000004B20001007900A0005A0000000004B2000100A100FA00640000000004B2000100FB01F400640000000004B2000101F5270F00640000000004B200020000006400640000000004B20002006500C800640000000004B2000200C901F400960000000004B2000201F5270F00960000000004B3000100000005000A0000000004B300010006000A00140000000004B30001000B001E001E0000000004B30001001F003C00280000000004B30001003D007800320000000004B3000100790082003C0000000004B300010083008C00460000000004B30001008D009600500000000004B30001009700A000550000000004B3000100A100C800640000000004B3000100C901F400640000000004B3000101F5270F00640000000004B300020000007800460000000004B30002007901F400780000000004B3000201F5270F00780000000004B4000100000005000F0000000004B400010006000A00140000000004B40001000B000F00190000000004B4000100100014001B0000000004B4000100150019001E0000000004B40001001A001E00200000000004B40001001F002800230000000004B400010029003200250000000004B400010033003C00280000000004B40001003D0046002B0000000004B4000100470050002D0000000004B400010051005A002F0000000004B40001005B006400320000000004B400010065006E003C0000000004B40001006F007800460000000004B4000100790082004B0000000004B400010083008C00520000000004B40001008D00A000550000000004B4000100A100C800640000000004B4000100C901F400640000000004B4000101F5270F00640000000004B400020000007800460000000004B40002007901F400780000000004B4000201F5270F0078000000000FA10001000000000000000000000FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000028900001000000010FA10002000028900001000000010FA10002000029AE0002000000010FA10002000029AE0002000000010FA10002000029BA0002000000010FA10002000029BB0002000000010FA10002000029B60001000000010FA10002000029B60001000000010FA5000100002B970001138800010FA5000100002B9800010D1600010FA5000100002B99000105DC00010FA5000100002B9A0001006400010FA5000100002B9B0001003200010FA5000200002B970002070800010FA5000200002B98000204B000010FA5000200002B99000201F400010FA5000200002B9A0001003200010FA5000200002B1D0001009600010FA5000200002B1E0001009600010FA5000200002B240001009600010FA5000200002B310001009600010FA5000200002B330001009600010FA5000200002B470001009600010FA5000200002B5A0001009600010FA5000200002B600001009600010FA5000200002B6D0001009600010FA5000200002B780001009600010FA5000200002B7D0001009600010FA5000200002B810001009600010FA5000200002B870001009600010FA5000200002B7C0001009600010FA5000200002B1F0001009600010FA5000200002B200001009600010FA5000200002B290001009600010FA5000200002B350001009600010FA5000200002B370001009600010FA5000200002B450001009600010FA5000200002B5B0001009600010FA5000200002B610001009600010FA5000200002B790001009600010FA5000200002B7A0001009600010FA5000200002B7B0001009600010FA5000200002B830001009600010FA5000200002B890001009600010FA5000200002B580001009600010FA5000200002B210001009600010FA5000200002B270001009600010FA5000200002B2E0001009600010FA5000200002B390001009600010FA5000200002B3C0001009600010FA5000200002B430001009600010FA5000200002B5C0001009600010FA5000200002B620001009600010FA5000200002B6F0001009600010FA5000200002B7F0001009600010FA5000200002B800001009600010FA5000200002B820001009600010FA5000200002B500001009600010FA50002000028820001009600010FA50002000028800001009600010FA6000100002B970001138800010FA6000100002B9800010D1600010FA6000100002B99000105DC00010FA6000100002B9A0001006400010FA6000100002B9B0001003200010FA6000200002B970002070800010FA6000200002B98000204B000010FA6000200002B99000201F400010FA6000200002B9A0001003200010FA6000200002B1D0001009600010FA6000200002B1E0001009600010FA6000200002B240001009600010FA6000200002B310001009600010FA6000200002B330001009600010FA6000200002B470001009600010FA6000200002B5A0001009600010FA6000200002B600001009600010FA6000200002B6D0001009600010FA6000200002B780001009600010FA6000200002B7D0001009600010FA6000200002B810001009600010FA6000200002B870001009600010FA6000200002B7C0001009600010FA6000200002B1F0001009600010FA6000200002B200001009600010FA6000200002B290001009600010FA6000200002B350001009600010FA6000200002B370001009600010FA6000200002B450001009600010FA6000200002B5B0001009600010FA6000200002B610001009600010FA6000200002B790001009600010FA6000200002B7A0001009600010FA6000200002B7B0001009600010FA6000200002B830001009600010FA6000200002B890001009600010FA6000200002B580001009600010FA6000200002B210001009600010FA6000200002B270001009600010FA6000200002B2E0001009600010FA6000200002B390001009600010FA6000200002B3C0001009600010FA6000200002B430001009600010FA6000200002B5C0001009600010FA6000200002B620001009600010FA6000200002B6F0001009600010FA6000200002B7F0001009600010FA6000200002B800001009600010FA6000200002B820001009600010FA6000200002B500001009600010FA60002000028820001009600010FA60002000028800001009600010FA7000100002B320001004600010FA7000100002B340001004600010FA7000100002B360001004600010FA7000100002B380001004600010FA7000100002B3A0001004600010FA7000100002B6E0001004600010FA7000100002B700001004600010FA7000100002B660001004600010FA7000100002B680001004600010FA7000100002B6A0001004600010FA7000100002B220001004600010FA7000100002B230001004600010FA7000100002B420001004600010FA7000100002B840001004600010FA7000100002B3B0001004600010FA7000100002B280001004600010FA7000100002B260001004600010FA7000100002B5F0001004600010FA7000100002B630001004600010FA7000100002B640001004600010FA7000100002B710001004600010FA7000100002B7E0001004600010FA7000100002B4C0001004600010FA7000100002B4D0001004600010FA7000100002B4E0001004600010FA7000100002B4F0001004600010FA7000100002B560001004600010FA7000100002B570001004600010FA70001000028860001004600010FA70001000028870001004600010FA70001000028880001004600010FA70001000028890001004600010FA700010000288A0001004600010FA7000100002B3D0001002D00010FA7000100002B3F0001002D00010FA7000100002B410001002D00010FA7000100002B440001002D00010FA7000100002B460001002D00010FA7000100002B6C0001002D00010FA7000100002B730001002D00010FA7000100002B770001002D00010FA7000100002B860001002D00010FA7000100002B300001002D00010FA7000100002B520001002D00010FA7000100002B590001002D00010FA700010000287F0001002D00010FA70001000028830001002D00010FA70001000028850001002D00010FA7000100002B480001000F00010FA7000100002B490001000F00010FA7000100002B4B0001000F00010FA7000100002B750001000F00010FA7000100002B550001000E00010FA7000100002B2D0001000A00010FA7000100002B8B0001000A00010FA70001000028840001000500010FA70001000028810001000100010FA7000100002B9B0001009600010FA7000100002CC90001003200010FA7000100002CCA0001001900010FA7000100002CCB000100C800010FA7000100002CCC0001019000010FA7000100002CCD0001009600010FA7000100002B1D0001005C00010FA7000100002B1E0001005C00010FA7000100002B240001005C00010FA7000100002B310001005C00010FA7000100002B330001005C00010FA7000100002B470001005C00010FA7000100002B5A0001005C00010FA7000100002B600001005C00010FA7000100002B6D0001005C00010FA7000100002B7D0001005C00010FA7000100002B810001005C00010FA7000100002B870001005C00010FA7000100002B7C0001005C00010FA7000100002B1F0001005C00010FA7000100002B200001005C00010FA7000100002B290001005C00010FA7000100002B350001005C00010FA7000100002B370001005C00010FA7000100002B450001005C00010FA7000100002B5B0001005C00010FA7000100002B610001005C00010FA7000100002B790001005C00010FA7000100002B7A0001005C00010FA7000100002B7B0001005C00010FA7000100002B830001005C00010FA7000100002B890001005B00010FA7000100002B580001005B00010FA7000100002B210001005B00010FA7000100002B270001005B00010FA7000100002B2E0001005B00010FA7000100002B390001005B00010FA7000100002B3C0001005B00010FA7000100002B430001005B00010FA7000100002B5C0001005B00010FA7000100002B620001005B00010FA7000100002B6F0001005B00010FA7000100002B7F0001005B00010FA7000100002B800001005B00010FA7000100002B820001005B00010FA7000100002B500001005B00010FA70001000028820001005B00010FA70001000028800001005B00010FA7000100002B250001005B00010FA7000100002B3E0001005B00010FA7000100002B5D0001005B00010FA7000100002B650001005B00010FA7000100002B720001005B00010FA7000100002B850001005B00010FA7000100002B2B0001005B00010FA7000100002B5E0001005B00010FA7000100002B740001005B00010FA7000100002B400001005B00010FA7000100002B4A0001005B00010FA7000100002B6B0001005B00010FA7000100002B880001005B00010FA7000100002B510001005B00010FA7000100002B530001005B00010FA7000100002B540001005B00010FA7000100002B2A0001005B00010FA7000100002B670001005B00010FA7000100002B690001005B00010FA7000100002B760001005B00010FA7000100002B2F0001005B00010FA7000100002B2C0001005B00010FA7000100002B8A0001005B00010FA7000200002B320001005A00010FA7000200002B340001005A00010FA7000200002B360001005A00010FA7000200002B380001005A00010FA7000200002B3A0001005A00010FA7000200002B6E0001005A00010FA7000200002B700001005A00010FA7000200002B660001005A00010FA7000200002B680001005A00010FA7000200002B6A0001005A00010FA7000200002B220001005A00010FA7000200002B230001005A00010FA7000200002B420001005A00010FA7000200002B840001005A00010FA7000200002B3B0001005A00010FA7000200002B280001005A00010FA7000200002B260001005A00010FA7000200002B5F0001005A00010FA7000200002B630001005A00010FA7000200002B640001005A00010FA7000200002B710001005A00010FA7000200002B7E0001005A00010FA7000200002B4C0001005A00010FA7000200002B4D0001005A00010FA7000200002B4E0001005A00010FA7000200002B4F0001005A00010FA7000200002B560001005A00010FA7000200002B570001005A00010FA70002000028860001005A00010FA70002000028870001005A00010FA70002000028880001005A00010FA70002000028890001005A00010FA700020000288A0001005A00010FA7000200002B3D0001005000010FA7000200002B3F0001005000010FA7000200002B410001005000010FA7000200002B440001005000010FA7000200002B460001005000010FA7000200002B6C0001005000010FA7000200002B730001005000010FA7000200002B770001005000010FA7000200002B860001005000010FA7000200002B300001005000010FA7000200002B520001005000010FA7000200002B590001005000010FA700020000287F0001005000010FA70002000028830001005000010FA70002000028850001005000010FA7000200002B480001001600010FA7000200002B490001001600010FA7000200002B4B0001001600010FA7000200002B750001001600010FA7000200002B550001001600010FA7000200002B2D0001000F00010FA7000200002B8B0001000F00010FA70002000028840001000800010FA70002000028810001000200010FA7000200002B97000304C400010FA7000200002B980003028A00010FA7000200002B99000300A000010FA7000200002D8D0001032000010FA7000200002D8E0001032000010FA7000200002B9B000101F400010FA7000200002B9A0001022600010FA7000200002CC90001003200010FA7000200002CCA0001001900010FA7000200002CCB000100FA00010FA7000200002CCC000101F400010FA7000200002CCD000100AF0001106A000100002B9B000117700001106A000100002CC9000100C80001106A000100002CCA000100640001106A000100002CCB000103E80001106A000100002CCC000107D00001106A000100002CCD000102BC0001106A000200002D8D000103200001106A000200002D8E000103200001106A000200002B9B000101900001106A000200002CC9000101900001106A000200002CCA000100C80001106A000200002CCB000107D00001106A000200002CCC00010FA00001106A000200002CCD000105780001") - } else if pkt.Unk2 == 6001 { - data, err = hex.DecodeString("0A218EAD0000000000000000000000052B97010113882B9801010D162B99010105DC2B9A010100642B9B01010032") - } else if pkt.Unk2 == 6002 { - data, err = hex.DecodeString("0A218EAD00000000000000000000002F2B97020107082B98020104B02B99020101F42B9A010100322B1D010100962B1E010100962B24010100962B31010100962B33010100962B47010100962B5A010100962B60010100962B6D010100962B78010100962B7D010100962B81010100962B87010100962B7C010100962B1F010100962B20010100962B29010100962B35010100962B37010100962B45010100962B5B010100962B61010100962B79010100962B7A010100962B7B010100962B83010100962B89010100962B58010100962B21010100962B27010100962B2E010100962B39010100962B3C010100962B43010100962B5C010100962B62010100962B6F010100962B7F010100962B80010100962B82010100962B5001010096288201010096288001010096") - } else if pkt.Unk2 == 6010 { - data, err = hex.DecodeString("0A218EAD00000000000000000000000B2B9701010E742B9801010B542B99010105142CBD010100FA2CBE010100FA2F17010100FA2F21010100FA2F1A010100FA2F24010100FA2DFE010100C82DFD01010190") - } else if pkt.Unk2 == 6011 { - data, err = hex.DecodeString("0A218EAD00000000000000000000000B2B9701010E742B9801010B542B99010105142CBD010100FA2CBE010100FA2F17010100FA2F21010100FA2F1A010100FA2F24010100FA2DFE010100C82DFD01010190") - } else if pkt.Unk2 == 6012 { - data, err = hex.DecodeString("0A218EAD00000000000000000000000D2B9702010DAC2B9802010B542B990201051430DC010101902CBD010100C82CBE010100C82F17010100C82F21010100C82F1A010100C82F24010100C82DFF010101902E00010100C82E0101010064") - } else if pkt.Unk2 == 7001 { - data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") - } else if pkt.Unk2 == 7002 { - data, err = hex.DecodeString("0A218EAD0000000000000000000000B92B1D010100642B1E010100642B24010100642B31010100642B33010100642B47010100642B5A010100642B60010100642B6D010100642B78010100642B7D010100642B81010100642B87010100642B7C010100642B220101003C2B250101003C2B380101003C2B360101003C2B3E0101003C2B5D0101003C2B640101003C2B650101003C2B700101003C2B720101003C2B7E0101003C2B850101003C2B4C0101003C2B4F0101003C2B560101003C28860101003C28870101003C2B2B010100142B3F010100142B44010100142B5E010100142B74010100142B52010100142B9C010101902B9A010100C82B9B010100C82CC7010100642CC80101009628730101009630DA010100C830DB0101012C30DC01010384353D0101015E353C010100C82C5C010100642C5D010100962EEE010100FA2EF0010101902EEF0101019A2B97020101F42B97040101F42B97060101F42B98020101902B98040101902B98060101902B99020100642B99040100642B99060100642B1F010200642B20010200642B29010200642B35010200642B37010200642B45010200642B5B010200642B61010200642B79010200642B7A010200642B7B010200642B83010200642B89010200642B58010200642B260102003C2B3A0102003C2B3B0102003C2B400102003C2B4A0102003C2B5F0102003C2B660102003C2B680102003C2B6A0102003C2B6B0102003C2B710102003C2B880102003C2B4D0102003C2B510102003C2B530102003C28880102003C28890102003C2B77010200142B3D010200142B86010200142B46010200142B30010200142B54010200142B9C010201902B9A010200C82B9B010200C82CC7010200FA2CC80102015E30DA0102009630DB010200C830DC0102015E353D010200FA353C010200C82873010201902B96010200642C5C010200642C5D010200642EEE0102012C2EF0010201C22EEF010201CC2B97020201F42B97040201F42B97060201F42B98020201902B98040201902B98060201902B99020200642B99040200642B99060200642B21010300782B27010300782B2E010300782B39010300782B3C010300782B43010300782B5C010300782B62010300782B6F010300782B7F010300782B80010300782B82010300782B50010300782882010300782880010300782B23010300412B28010300412B2A010300412B32010300412B34010300412B42010300412B63010300412B67010300412B69010300412B6E010300412B76010300412B84010300412B4E010300412B57010300412B2F01030041288A010300412B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A030301EA2BC9030301EA2A3D030301EA2C7D030301EA2F0E030301F430D7030301F42B97020301F42B97040301F42B97060301F42B98020301902B98040301902B98060301902B99020300642B99040300642B99060300642CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") - } else if pkt.Unk2 == 7011 { - data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") - } else if pkt.Unk2 == 7012 { - data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") + var data []*byteframe.ByteFrame + + var paperData []PaperData + var paperMissions PaperMission + var paperGift []PaperGift + + switch pkt.Unk2 { + case 0: + paperMissions = PaperMission{ + []PaperMissionTimetable{{TimeMidnight(), TimeMidnight().Add(24 * time.Hour)}}, + []PaperMissionData{ + {1, 1, 50, 7, 10, 8, 10}, + {1, 2, 50, 7, 10, 8, 10}, + {1, 3, 50, 7, 10, 8, 10}, + {1, 4, 50, 7, 10, 8, 10}, + {1, 5, 50, 7, 10, 8, 10}, + {1, 6, 50, 7, 10, 8, 10}, + }, + } + case 5: + paperData = []PaperData{ + {1001, 1, 0, 0, 0, 0, 0}, + {1001, 2, 0, 0, 0, 0, 0}, + {1003, 1, 100, 100, 200, 100, 0}, + {1003, 2, 150, 100, 240, 100, 0}, + {1004, 10, 9999, 40, 0, 0, 0}, + {1005, 10, 500, 0, 0, 0, 0}, + {1007, 1, 0, 0, 0, 0, 0}, + {1008, 200, 400, 3000, 400, 3000, 0}, + {1010, 1, 4000, 0, 0, 0, 0}, + {1010, 2, 4000, 0, 0, 0, 0}, + {1011, 1, 6000, 15000, 20000, 25000, 30000}, + {1011, 2, 6000, 15000, 20000, 25000, 30000}, + {1012, 1, 8000, 17500, 22500, 27500, 31000}, + {1012, 2, 8000, 17500, 22500, 27500, 31000}, + {1015, 1, 16, 16, 16, 0, 0}, + {1015, 2, 16, 16, 16, 0, 0}, + {1101, 1, 2016, 500, 0, 0, 0}, + {1101, 2, 2016, 500, 0, 0, 0}, + {1103, 1, 0, 0, 3000, 0, 3000}, + {1103, 2, 0, 0, 3000, 0, 3000}, + {1104, 1, 10, 9999, 40, 0, 0}, + {1104, 2, 10, 9999, 40, 0, 0}, + {1105, 1, 10, 500, 0, 0, 0}, + {1105, 2, 10, 500, 0, 0, 0}, + {2001, 1, 17, 58, 0, 6, 700}, + {2001, 1, 20, 58, 0, 3, 200}, + {2001, 1, 22, 58, 0, 7, 250}, + {2001, 1, 27, 58, 0, 1, 100}, + {2001, 1, 53, 58, 0, 8, 1000}, + {2001, 1, 67, 58, 0, 9, 500}, + {2001, 1, 68, 58, 0, 2, 150}, + {2001, 1, 74, 58, 0, 4, 200}, + {2001, 1, 75, 58, 0, 5, 500}, + {2001, 1, 76, 58, 0, 10, 800}, + {2001, 1, 80, 58, 0, 11, 900}, + {2001, 1, 89, 58, 0, 12, 600}, + {2001, 2, 17, 60, 0, 6, 700}, + {2001, 2, 20, 60, 0, 3, 200}, + {2001, 2, 22, 60, 0, 7, 350}, + {2001, 2, 27, 60, 0, 1, 100}, + {2001, 2, 39, 60, 0, 13, 200}, + {2001, 2, 40, 60, 0, 15, 600}, + {2001, 2, 53, 60, 0, 8, 1000}, + {2001, 2, 67, 60, 0, 2, 500}, + {2001, 2, 68, 60, 0, 9, 150}, + {2001, 2, 74, 60, 0, 4, 200}, + {2001, 2, 75, 60, 0, 5, 500}, + {2001, 2, 76, 60, 0, 10, 800}, + {2001, 2, 80, 60, 0, 11, 900}, + {2001, 2, 81, 60, 0, 14, 900}, + {2001, 2, 89, 60, 0, 12, 600}, + {2001, 2, 94, 60, 0, 16, 1000}, + } + case 6: + paperData = []PaperData{ + {1002, 100, 0, 0, 0, 0, 0}, + {1006, 1, 10000, 10000, 0, 0, 0}, + {1006, 2, 10000, 20000, 0, 0, 0}, + {1009, 20, 0, 0, 0, 0, 0}, + {1013, 1, 1, 1, 100, 200, 300}, + {1013, 1, 1, 2, 100, 200, 300}, + {1013, 1, 2, 1, 300, 100, 200}, + {1013, 1, 2, 2, 300, 100, 200}, + {1013, 1, 3, 1, 200, 300, 100}, + {1013, 1, 3, 2, 200, 300, 100}, + {1013, 2, 1, 1, 300, 100, 200}, + {1013, 2, 1, 2, 300, 100, 200}, + {1013, 2, 2, 1, 200, 300, 100}, + {1013, 2, 2, 2, 200, 300, 100}, + {1013, 2, 3, 1, 100, 200, 300}, + {1013, 2, 3, 2, 100, 200, 300}, + {1013, 3, 1, 1, 200, 300, 100}, + {1013, 3, 1, 2, 200, 300, 100}, + {1013, 3, 2, 1, 100, 200, 300}, + {1013, 3, 2, 2, 100, 200, 300}, + {1013, 3, 3, 1, 300, 100, 200}, + {1013, 3, 3, 2, 300, 100, 200}, + {1016, 1, 1, 80, 0, 0, 0}, + {1016, 1, 2, 80, 0, 0, 0}, + {1016, 1, 3, 80, 0, 0, 0}, + {1016, 2, 1, 80, 0, 0, 0}, + {1016, 2, 2, 80, 0, 0, 0}, + {1016, 2, 3, 80, 0, 0, 0}, + {1201, 1, 60, 50, 0, 0, 0}, + {1201, 2, 60, 50, 0, 0, 0}, + {1202, 1, 0, 5, 50, 0, 0}, + {1202, 1, 6, 20, 60, 0, 0}, + {1202, 1, 21, 40, 70, 0, 0}, + {1202, 1, 41, 120, 80, 0, 0}, + {1202, 1, 121, 160, 90, 0, 0}, + {1202, 1, 161, 250, 100, 0, 0}, + {1202, 1, 251, 500, 100, 0, 0}, + {1202, 1, 501, 9999, 100, 0, 0}, + {1202, 2, 0, 100, 100, 0, 0}, + {1202, 2, 101, 200, 100, 0, 0}, + {1202, 2, 201, 500, 150, 0, 0}, + {1202, 2, 501, 9999, 150, 0, 0}, + {1203, 1, 0, 5, 10, 0, 0}, + {1203, 1, 6, 10, 20, 0, 0}, + {1203, 1, 11, 30, 30, 0, 0}, + {1203, 1, 31, 60, 40, 0, 0}, + {1203, 1, 61, 120, 50, 0, 0}, + {1203, 1, 121, 130, 60, 0, 0}, + {1203, 1, 131, 140, 70, 0, 0}, + {1203, 1, 141, 150, 80, 0, 0}, + {1203, 1, 151, 160, 85, 0, 0}, + {1203, 1, 161, 200, 100, 0, 0}, + {1203, 1, 201, 500, 100, 0, 0}, + {1203, 1, 501, 9999, 100, 0, 0}, + {1203, 2, 0, 120, 70, 0, 0}, + {1203, 2, 121, 500, 120, 0, 0}, + {1203, 2, 501, 9999, 120, 0, 0}, + {1204, 1, 0, 5, 15, 0, 0}, + {1204, 1, 6, 10, 20, 0, 0}, + {1204, 1, 11, 15, 25, 0, 0}, + {1204, 1, 16, 20, 27, 0, 0}, + {1204, 1, 21, 25, 30, 0, 0}, + {1204, 1, 26, 30, 32, 0, 0}, + {1204, 1, 31, 40, 35, 0, 0}, + {1204, 1, 41, 50, 37, 0, 0}, + {1204, 1, 51, 60, 40, 0, 0}, + {1204, 1, 61, 70, 43, 0, 0}, + {1204, 1, 71, 80, 45, 0, 0}, + {1204, 1, 81, 90, 47, 0, 0}, + {1204, 1, 91, 100, 50, 0, 0}, + {1204, 1, 101, 110, 60, 0, 0}, + {1204, 1, 111, 120, 70, 0, 0}, + {1204, 1, 121, 130, 75, 0, 0}, + {1204, 1, 131, 140, 82, 0, 0}, + {1204, 1, 141, 160, 85, 0, 0}, + {1204, 1, 161, 200, 100, 0, 0}, + {1204, 1, 201, 500, 100, 0, 0}, + {1204, 1, 501, 9999, 100, 0, 0}, + {1204, 2, 0, 120, 70, 0, 0}, + {1204, 2, 121, 500, 120, 0, 0}, + {1204, 2, 501, 9999, 120, 0, 0}, + {4001, 1, 0, 0, 0, 0, 0}, + {4001, 2, 0, 10667, 5, 0, 1}, + {4001, 2, 0, 10667, 5, 0, 1}, + {4001, 2, 0, 10667, 5, 0, 1}, + {4001, 2, 0, 10667, 5, 0, 1}, + {4001, 2, 0, 10668, 2, 0, 1}, + {4001, 2, 0, 10668, 2, 0, 1}, + {4001, 2, 0, 10668, 2, 0, 1}, + {4001, 2, 0, 10668, 2, 0, 1}, + {4001, 2, 0, 10669, 1, 0, 1}, + {4001, 2, 0, 10669, 1, 0, 1}, + {4001, 2, 0, 10669, 1, 0, 1}, + {4001, 2, 0, 10669, 1, 0, 1}, + {4001, 2, 0, 10671, 3, 0, 1}, + {4001, 2, 0, 10671, 3, 0, 1}, + {4001, 2, 0, 10671, 3, 0, 1}, + {4001, 2, 0, 10671, 3, 0, 1}, + {4001, 2, 0, 10384, 1, 0, 1}, + {4001, 2, 0, 10384, 1, 0, 1}, + {4001, 2, 0, 10670, 2, 0, 1}, + {4001, 2, 0, 10670, 2, 0, 1}, + {4001, 2, 0, 10682, 2, 0, 1}, + {4001, 2, 0, 10683, 2, 0, 1}, + {4001, 2, 0, 10678, 1, 0, 1}, + {4001, 2, 0, 10678, 1, 0, 1}, + {4005, 1, 0, 11159, 1, 5000, 1}, + {4005, 1, 0, 11160, 1, 3350, 1}, + {4005, 1, 0, 11161, 1, 1500, 1}, + {4005, 1, 0, 11162, 1, 100, 1}, + {4005, 1, 0, 11163, 1, 50, 1}, + {4005, 2, 0, 11159, 2, 1800, 1}, + {4005, 2, 0, 11160, 2, 1200, 1}, + {4005, 2, 0, 11161, 2, 500, 1}, + {4005, 2, 0, 11162, 1, 50, 1}, + {4005, 2, 0, 11037, 1, 150, 1}, + {4005, 2, 0, 11038, 1, 150, 1}, + {4005, 2, 0, 11044, 1, 150, 1}, + {4005, 2, 0, 11057, 1, 150, 1}, + {4005, 2, 0, 11059, 1, 150, 1}, + {4005, 2, 0, 11079, 1, 150, 1}, + {4005, 2, 0, 11098, 1, 150, 1}, + {4005, 2, 0, 11104, 1, 150, 1}, + {4005, 2, 0, 11117, 1, 150, 1}, + {4005, 2, 0, 11128, 1, 150, 1}, + {4005, 2, 0, 11133, 1, 150, 1}, + {4005, 2, 0, 11137, 1, 150, 1}, + {4005, 2, 0, 11143, 1, 150, 1}, + {4005, 2, 0, 11132, 1, 150, 1}, + {4005, 2, 0, 11039, 1, 150, 1}, + {4005, 2, 0, 11040, 1, 150, 1}, + {4005, 2, 0, 11049, 1, 150, 1}, + {4005, 2, 0, 11061, 1, 150, 1}, + {4005, 2, 0, 11063, 1, 150, 1}, + {4005, 2, 0, 11077, 1, 150, 1}, + {4005, 2, 0, 11099, 1, 150, 1}, + {4005, 2, 0, 11105, 1, 150, 1}, + {4005, 2, 0, 11129, 1, 150, 1}, + {4005, 2, 0, 11130, 1, 150, 1}, + {4005, 2, 0, 11131, 1, 150, 1}, + {4005, 2, 0, 11139, 1, 150, 1}, + {4005, 2, 0, 11145, 1, 150, 1}, + {4005, 2, 0, 11096, 1, 150, 1}, + {4005, 2, 0, 11041, 1, 150, 1}, + {4005, 2, 0, 11047, 1, 150, 1}, + {4005, 2, 0, 11054, 1, 150, 1}, + {4005, 2, 0, 11065, 1, 150, 1}, + {4005, 2, 0, 11068, 1, 150, 1}, + {4005, 2, 0, 11075, 1, 150, 1}, + {4005, 2, 0, 11100, 1, 150, 1}, + {4005, 2, 0, 11106, 1, 150, 1}, + {4005, 2, 0, 11119, 1, 150, 1}, + {4005, 2, 0, 11135, 1, 150, 1}, + {4005, 2, 0, 11136, 1, 150, 1}, + {4005, 2, 0, 11138, 1, 150, 1}, + {4005, 2, 0, 11088, 1, 150, 1}, + {4005, 2, 0, 10370, 1, 150, 1}, + {4005, 2, 0, 10368, 1, 150, 1}, + {4006, 1, 0, 11159, 1, 5000, 1}, + {4006, 1, 0, 11160, 1, 3350, 1}, + {4006, 1, 0, 11161, 1, 1500, 1}, + {4006, 1, 0, 11162, 1, 100, 1}, + {4006, 1, 0, 11163, 1, 50, 1}, + {4006, 2, 0, 11159, 2, 1800, 1}, + {4006, 2, 0, 11160, 2, 1200, 1}, + {4006, 2, 0, 11161, 2, 500, 1}, + {4006, 2, 0, 11162, 1, 50, 1}, + {4006, 2, 0, 11037, 1, 150, 1}, + {4006, 2, 0, 11038, 1, 150, 1}, + {4006, 2, 0, 11044, 1, 150, 1}, + {4006, 2, 0, 11057, 1, 150, 1}, + {4006, 2, 0, 11059, 1, 150, 1}, + {4006, 2, 0, 11079, 1, 150, 1}, + {4006, 2, 0, 11098, 1, 150, 1}, + {4006, 2, 0, 11104, 1, 150, 1}, + {4006, 2, 0, 11117, 1, 150, 1}, + {4006, 2, 0, 11128, 1, 150, 1}, + {4006, 2, 0, 11133, 1, 150, 1}, + {4006, 2, 0, 11137, 1, 150, 1}, + {4006, 2, 0, 11143, 1, 150, 1}, + {4006, 2, 0, 11132, 1, 150, 1}, + {4006, 2, 0, 11039, 1, 150, 1}, + {4006, 2, 0, 11040, 1, 150, 1}, + {4006, 2, 0, 11049, 1, 150, 1}, + {4006, 2, 0, 11061, 1, 150, 1}, + {4006, 2, 0, 11063, 1, 150, 1}, + {4006, 2, 0, 11077, 1, 150, 1}, + {4006, 2, 0, 11099, 1, 150, 1}, + {4006, 2, 0, 11105, 1, 150, 1}, + {4006, 2, 0, 11129, 1, 150, 1}, + {4006, 2, 0, 11130, 1, 150, 1}, + {4006, 2, 0, 11131, 1, 150, 1}, + {4006, 2, 0, 11139, 1, 150, 1}, + {4006, 2, 0, 11145, 1, 150, 1}, + {4006, 2, 0, 11096, 1, 150, 1}, + {4006, 2, 0, 11041, 1, 150, 1}, + {4006, 2, 0, 11047, 1, 150, 1}, + {4006, 2, 0, 11054, 1, 150, 1}, + {4006, 2, 0, 11065, 1, 150, 1}, + {4006, 2, 0, 11068, 1, 150, 1}, + {4006, 2, 0, 11075, 1, 150, 1}, + {4006, 2, 0, 11100, 1, 150, 1}, + {4006, 2, 0, 11106, 1, 150, 1}, + {4006, 2, 0, 11119, 1, 150, 1}, + {4006, 2, 0, 11135, 1, 150, 1}, + {4006, 2, 0, 11136, 1, 150, 1}, + {4006, 2, 0, 11138, 1, 150, 1}, + {4006, 2, 0, 11088, 1, 150, 1}, + {4006, 2, 0, 10370, 1, 150, 1}, + {4006, 2, 0, 10368, 1, 150, 1}, + {4007, 1, 0, 11058, 1, 70, 1}, + {4007, 1, 0, 11060, 1, 70, 1}, + {4007, 1, 0, 11062, 1, 70, 1}, + {4007, 1, 0, 11064, 1, 70, 1}, + {4007, 1, 0, 11066, 1, 70, 1}, + {4007, 1, 0, 11118, 1, 70, 1}, + {4007, 1, 0, 11120, 1, 70, 1}, + {4007, 1, 0, 11110, 1, 70, 1}, + {4007, 1, 0, 11112, 1, 70, 1}, + {4007, 1, 0, 11114, 1, 70, 1}, + {4007, 1, 0, 11042, 1, 70, 1}, + {4007, 1, 0, 11043, 1, 70, 1}, + {4007, 1, 0, 11074, 1, 70, 1}, + {4007, 1, 0, 11140, 1, 70, 1}, + {4007, 1, 0, 11067, 1, 70, 1}, + {4007, 1, 0, 11048, 1, 70, 1}, + {4007, 1, 0, 11046, 1, 70, 1}, + {4007, 1, 0, 11103, 1, 70, 1}, + {4007, 1, 0, 11107, 1, 70, 1}, + {4007, 1, 0, 11108, 1, 70, 1}, + {4007, 1, 0, 11121, 1, 70, 1}, + {4007, 1, 0, 11134, 1, 70, 1}, + {4007, 1, 0, 11084, 1, 70, 1}, + {4007, 1, 0, 11085, 1, 70, 1}, + {4007, 1, 0, 11086, 1, 70, 1}, + {4007, 1, 0, 11087, 1, 70, 1}, + {4007, 1, 0, 11094, 1, 70, 1}, + {4007, 1, 0, 11095, 1, 70, 1}, + {4007, 1, 0, 10374, 1, 70, 1}, + {4007, 1, 0, 10375, 1, 70, 1}, + {4007, 1, 0, 10376, 1, 70, 1}, + {4007, 1, 0, 10377, 1, 70, 1}, + {4007, 1, 0, 10378, 1, 70, 1}, + {4007, 1, 0, 11069, 1, 45, 1}, + {4007, 1, 0, 11071, 1, 45, 1}, + {4007, 1, 0, 11073, 1, 45, 1}, + {4007, 1, 0, 11076, 1, 45, 1}, + {4007, 1, 0, 11078, 1, 45, 1}, + {4007, 1, 0, 11116, 1, 45, 1}, + {4007, 1, 0, 11123, 1, 45, 1}, + {4007, 1, 0, 11127, 1, 45, 1}, + {4007, 1, 0, 11142, 1, 45, 1}, + {4007, 1, 0, 11056, 1, 45, 1}, + {4007, 1, 0, 11090, 1, 45, 1}, + {4007, 1, 0, 11097, 1, 45, 1}, + {4007, 1, 0, 10367, 1, 45, 1}, + {4007, 1, 0, 10371, 1, 45, 1}, + {4007, 1, 0, 10373, 1, 45, 1}, + {4007, 1, 0, 11080, 1, 15, 1}, + {4007, 1, 0, 11081, 1, 15, 1}, + {4007, 1, 0, 11083, 1, 15, 1}, + {4007, 1, 0, 11125, 1, 15, 1}, + {4007, 1, 0, 11093, 1, 14, 1}, + {4007, 1, 0, 11053, 1, 10, 1}, + {4007, 1, 0, 11147, 1, 10, 1}, + {4007, 1, 0, 10372, 1, 5, 1}, + {4007, 1, 0, 10369, 1, 1, 1}, + {4007, 1, 0, 11163, 1, 150, 1}, + {4007, 1, 0, 11465, 1, 50, 1}, + {4007, 1, 0, 11466, 1, 25, 1}, + {4007, 1, 0, 11467, 1, 200, 1}, + {4007, 1, 0, 11468, 1, 400, 1}, + {4007, 1, 0, 11469, 1, 150, 1}, + {4007, 1, 0, 11037, 1, 92, 1}, + {4007, 1, 0, 11038, 1, 92, 1}, + {4007, 1, 0, 11044, 1, 92, 1}, + {4007, 1, 0, 11057, 1, 92, 1}, + {4007, 1, 0, 11059, 1, 92, 1}, + {4007, 1, 0, 11079, 1, 92, 1}, + {4007, 1, 0, 11098, 1, 92, 1}, + {4007, 1, 0, 11104, 1, 92, 1}, + {4007, 1, 0, 11117, 1, 92, 1}, + {4007, 1, 0, 11133, 1, 92, 1}, + {4007, 1, 0, 11137, 1, 92, 1}, + {4007, 1, 0, 11143, 1, 92, 1}, + {4007, 1, 0, 11132, 1, 92, 1}, + {4007, 1, 0, 11039, 1, 92, 1}, + {4007, 1, 0, 11040, 1, 92, 1}, + {4007, 1, 0, 11049, 1, 92, 1}, + {4007, 1, 0, 11061, 1, 92, 1}, + {4007, 1, 0, 11063, 1, 92, 1}, + {4007, 1, 0, 11077, 1, 92, 1}, + {4007, 1, 0, 11099, 1, 92, 1}, + {4007, 1, 0, 11105, 1, 92, 1}, + {4007, 1, 0, 11129, 1, 92, 1}, + {4007, 1, 0, 11130, 1, 92, 1}, + {4007, 1, 0, 11131, 1, 92, 1}, + {4007, 1, 0, 11139, 1, 92, 1}, + {4007, 1, 0, 11145, 1, 91, 1}, + {4007, 1, 0, 11096, 1, 91, 1}, + {4007, 1, 0, 11041, 1, 91, 1}, + {4007, 1, 0, 11047, 1, 91, 1}, + {4007, 1, 0, 11054, 1, 91, 1}, + {4007, 1, 0, 11065, 1, 91, 1}, + {4007, 1, 0, 11068, 1, 91, 1}, + {4007, 1, 0, 11075, 1, 91, 1}, + {4007, 1, 0, 11100, 1, 91, 1}, + {4007, 1, 0, 11106, 1, 91, 1}, + {4007, 1, 0, 11119, 1, 91, 1}, + {4007, 1, 0, 11135, 1, 91, 1}, + {4007, 1, 0, 11136, 1, 91, 1}, + {4007, 1, 0, 11138, 1, 91, 1}, + {4007, 1, 0, 11088, 1, 91, 1}, + {4007, 1, 0, 10370, 1, 91, 1}, + {4007, 1, 0, 10368, 1, 91, 1}, + {4007, 1, 0, 11045, 1, 91, 1}, + {4007, 1, 0, 11070, 1, 91, 1}, + {4007, 1, 0, 11101, 1, 91, 1}, + {4007, 1, 0, 11109, 1, 91, 1}, + {4007, 1, 0, 11122, 1, 91, 1}, + {4007, 1, 0, 11141, 1, 91, 1}, + {4007, 1, 0, 11051, 1, 91, 1}, + {4007, 1, 0, 11102, 1, 91, 1}, + {4007, 1, 0, 11124, 1, 91, 1}, + {4007, 1, 0, 11072, 1, 91, 1}, + {4007, 1, 0, 11082, 1, 91, 1}, + {4007, 1, 0, 11115, 1, 91, 1}, + {4007, 1, 0, 11144, 1, 91, 1}, + {4007, 1, 0, 11089, 1, 91, 1}, + {4007, 1, 0, 11091, 1, 91, 1}, + {4007, 1, 0, 11092, 1, 91, 1}, + {4007, 1, 0, 11050, 1, 91, 1}, + {4007, 1, 0, 11111, 1, 91, 1}, + {4007, 1, 0, 11113, 1, 91, 1}, + {4007, 1, 0, 11126, 1, 91, 1}, + {4007, 1, 0, 11055, 1, 91, 1}, + {4007, 1, 0, 11052, 1, 91, 1}, + {4007, 1, 0, 11146, 1, 91, 1}, + {4007, 2, 0, 11058, 1, 90, 1}, + {4007, 2, 0, 11060, 1, 90, 1}, + {4007, 2, 0, 11062, 1, 90, 1}, + {4007, 2, 0, 11064, 1, 90, 1}, + {4007, 2, 0, 11066, 1, 90, 1}, + {4007, 2, 0, 11118, 1, 90, 1}, + {4007, 2, 0, 11120, 1, 90, 1}, + {4007, 2, 0, 11110, 1, 90, 1}, + {4007, 2, 0, 11112, 1, 90, 1}, + {4007, 2, 0, 11114, 1, 90, 1}, + {4007, 2, 0, 11042, 1, 90, 1}, + {4007, 2, 0, 11043, 1, 90, 1}, + {4007, 2, 0, 11074, 1, 90, 1}, + {4007, 2, 0, 11140, 1, 90, 1}, + {4007, 2, 0, 11067, 1, 90, 1}, + {4007, 2, 0, 11048, 1, 90, 1}, + {4007, 2, 0, 11046, 1, 90, 1}, + {4007, 2, 0, 11103, 1, 90, 1}, + {4007, 2, 0, 11107, 1, 90, 1}, + {4007, 2, 0, 11108, 1, 90, 1}, + {4007, 2, 0, 11121, 1, 90, 1}, + {4007, 2, 0, 11134, 1, 90, 1}, + {4007, 2, 0, 11084, 1, 90, 1}, + {4007, 2, 0, 11085, 1, 90, 1}, + {4007, 2, 0, 11086, 1, 90, 1}, + {4007, 2, 0, 11087, 1, 90, 1}, + {4007, 2, 0, 11094, 1, 90, 1}, + {4007, 2, 0, 11095, 1, 90, 1}, + {4007, 2, 0, 10374, 1, 90, 1}, + {4007, 2, 0, 10375, 1, 90, 1}, + {4007, 2, 0, 10376, 1, 90, 1}, + {4007, 2, 0, 10377, 1, 90, 1}, + {4007, 2, 0, 10378, 1, 90, 1}, + {4007, 2, 0, 11069, 1, 80, 1}, + {4007, 2, 0, 11071, 1, 80, 1}, + {4007, 2, 0, 11073, 1, 80, 1}, + {4007, 2, 0, 11076, 1, 80, 1}, + {4007, 2, 0, 11078, 1, 80, 1}, + {4007, 2, 0, 11116, 1, 80, 1}, + {4007, 2, 0, 11123, 1, 80, 1}, + {4007, 2, 0, 11127, 1, 80, 1}, + {4007, 2, 0, 11142, 1, 80, 1}, + {4007, 2, 0, 11056, 1, 80, 1}, + {4007, 2, 0, 11090, 1, 80, 1}, + {4007, 2, 0, 11097, 1, 80, 1}, + {4007, 2, 0, 10367, 1, 80, 1}, + {4007, 2, 0, 10371, 1, 80, 1}, + {4007, 2, 0, 10373, 1, 80, 1}, + {4007, 2, 0, 11080, 1, 22, 1}, + {4007, 2, 0, 11081, 1, 22, 1}, + {4007, 2, 0, 11083, 1, 22, 1}, + {4007, 2, 0, 11125, 1, 22, 1}, + {4007, 2, 0, 11093, 1, 22, 1}, + {4007, 2, 0, 11053, 1, 15, 1}, + {4007, 2, 0, 11147, 1, 15, 1}, + {4007, 2, 0, 10372, 1, 8, 1}, + {4007, 2, 0, 10369, 1, 2, 1}, + {4007, 2, 0, 11159, 3, 1220, 1}, + {4007, 2, 0, 11160, 3, 650, 1}, + {4007, 2, 0, 11161, 3, 160, 1}, + {4007, 2, 0, 11661, 1, 800, 1}, + {4007, 2, 0, 11662, 1, 800, 1}, + {4007, 2, 0, 11163, 1, 500, 1}, + {4007, 2, 0, 11162, 1, 550, 1}, + {4007, 2, 0, 11465, 1, 50, 1}, + {4007, 2, 0, 11466, 1, 25, 1}, + {4007, 2, 0, 11467, 1, 250, 1}, + {4007, 2, 0, 11468, 1, 500, 1}, + {4007, 2, 0, 11469, 1, 175, 1}, + {4202, 1, 0, 11163, 1, 6000, 1}, + {4202, 1, 0, 11465, 1, 200, 1}, + {4202, 1, 0, 11466, 1, 100, 1}, + {4202, 1, 0, 11467, 1, 1000, 1}, + {4202, 1, 0, 11468, 1, 2000, 1}, + {4202, 1, 0, 11469, 1, 700, 1}, + {4202, 2, 0, 11661, 1, 800, 1}, + {4202, 2, 0, 11662, 1, 800, 1}, + {4202, 2, 0, 11163, 1, 400, 1}, + {4202, 2, 0, 11465, 1, 400, 1}, + {4202, 2, 0, 11466, 1, 200, 1}, + {4202, 2, 0, 11467, 1, 2000, 1}, + {4202, 2, 0, 11468, 1, 4000, 1}, + {4202, 2, 0, 11469, 1, 1400, 1}, + } + default: + if pkt.Unk2 < 1000 { + s.logger.Info("PaperData request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) + } + } + + if pkt.Unk2 > 1000 { + _, ok := paperGiftData[pkt.Unk2] + if ok { + paperGift = paperGiftData[pkt.Unk2] + } else { + s.logger.Info("PaperGift request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) + } + for _, gift := range paperGift { + bf := byteframe.NewByteFrame() + bf.WriteUint16(gift.Unk0) + bf.WriteUint8(gift.Unk1) + bf.WriteUint8(gift.Unk2) + bf.WriteUint16(gift.Unk3) + data = append(data, bf) + } + doAckEarthSucceed(s, pkt.AckHandle, data) + } else if pkt.Unk2 == 0 { + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(len(paperMissions.Timetables))) + bf.WriteUint16(uint16(len(paperMissions.Data))) + for _, timetable := range paperMissions.Timetables { + bf.WriteUint32(uint32(timetable.Start.Unix())) + bf.WriteUint32(uint32(timetable.End.Unix())) + } + for _, mdata := range paperMissions.Data { + bf.WriteUint8(mdata.Unk0) + bf.WriteUint8(mdata.Unk1) + bf.WriteInt16(mdata.Unk2) + bf.WriteUint16(mdata.Reward1ID) + bf.WriteUint8(mdata.Reward1Quantity) + bf.WriteUint16(mdata.Reward2ID) + bf.WriteUint8(mdata.Reward2Quantity) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { - data = []byte{0x00, 0x00, 0x00, 0x00} - s.logger.Info("GET_PAPER request for unknown type") + for _, pdata := range paperData { + bf := byteframe.NewByteFrame() + bf.WriteUint16(pdata.Unk0) + bf.WriteInt16(pdata.Unk1) + bf.WriteInt16(pdata.Unk2) + bf.WriteInt16(pdata.Unk3) + bf.WriteInt16(pdata.Unk4) + bf.WriteInt16(pdata.Unk5) + bf.WriteInt16(pdata.Unk6) + data = append(data, bf) + } + doAckEarthSucceed(s, pkt.AckHandle, data) } - if err != nil { - panic(err) - } - doAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgSysAuthData(s *Session, p mhfpacket.MHFPacket) {} From 6865e2d530aeafc7bad39f0effdeae81368fd92d Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 19 Jun 2023 22:43:32 +1000 Subject: [PATCH 38/99] rename Zone to Block --- server/channelserver/handlers_tower.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 2bc8bf72e..aeb1834ab 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -149,7 +149,7 @@ type TenrouiraiTicket struct { } type TenrouiraiData struct { - Zone uint8 + Block uint8 Mission uint8 // 1 = Floors climbed // 2 = Collect antiques @@ -223,7 +223,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { case 1: for _, tdata := range tenrouirai.Data { bf := byteframe.NewByteFrame() - bf.WriteUint8(tdata.Zone) + bf.WriteUint8(tdata.Block) bf.WriteUint8(tdata.Mission) bf.WriteUint16(tdata.Goal) bf.WriteUint16(tdata.Unk3) From b60bf4979b93a79708b074a95dff8ef4d2462280 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 19 Jun 2023 22:44:20 +1000 Subject: [PATCH 39/99] fix ContractMercenary --- server/channelserver/handlers_mercenary.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_mercenary.go b/server/channelserver/handlers_mercenary.go index 251bc107b..85ca65f9a 100644 --- a/server/channelserver/handlers_mercenary.go +++ b/server/channelserver/handlers_mercenary.go @@ -222,8 +222,8 @@ func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfContractMercenary) switch pkt.Op { - case 0: - s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, s.charID) + case 0: // Form loan + s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID) case 1: // Cancel lend s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID) case 2: // Cancel loan From 796927ac61ee33d5a773515f6391b151e7560c22 Mon Sep 17 00:00:00 2001 From: wish Date: Tue, 20 Jun 2023 21:42:06 +1000 Subject: [PATCH 40/99] add PS3_TROP to constant courses --- common/mhfcourse/mhfcourse.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/mhfcourse/mhfcourse.go b/common/mhfcourse/mhfcourse.go index 13496119b..6b0936e45 100644 --- a/common/mhfcourse/mhfcourse.go +++ b/common/mhfcourse/mhfcourse.go @@ -66,7 +66,7 @@ func CourseExists(ID uint16, c []Course) bool { // GetCourseStruct returns a slice of Course(s) from a rights integer func GetCourseStruct(rights uint32) ([]Course, uint32) { - resp := []Course{{ID: 1}, {ID: 24}} + resp := []Course{{ID: 1}, {ID: 23}, {ID: 24}} s := Courses() slices.SortStableFunc(s, func(i, j Course) bool { return i.ID > j.ID From 4a21272c424d5af0abea0618a1fba2d31640e6de Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 00:11:47 +1000 Subject: [PATCH 41/99] partial Tenrouirai automation and Gem fix --- network/mhfpacket/msg_mhf_post_tenrouirai.go | 52 +++-- patch-schema/tower.sql | 17 +- server/channelserver/handlers_tower.go | 211 ++++++++++++------- 3 files changed, 191 insertions(+), 89 deletions(-) diff --git a/network/mhfpacket/msg_mhf_post_tenrouirai.go b/network/mhfpacket/msg_mhf_post_tenrouirai.go index 7edb751e5..bc91279b4 100644 --- a/network/mhfpacket/msg_mhf_post_tenrouirai.go +++ b/network/mhfpacket/msg_mhf_post_tenrouirai.go @@ -12,15 +12,23 @@ import ( type MsgMhfPostTenrouirai struct { AckHandle uint32 Unk0 uint8 - Unk1 uint8 + Op uint8 GuildID uint32 - Unk3 uint8 - Floors uint16 - Antiques uint16 - Chests uint16 - Cats uint16 - TRP uint16 - Slays uint16 + Unk1 uint8 + + Floors uint16 + Antiques uint16 + Chests uint16 + Cats uint16 + TRP uint16 + Slays uint16 + + DonatedRP uint16 + PreviousRP uint16 + Unk2_0 uint16 + Unk2_1 uint16 + Unk2_2 uint16 + Unk2_3 uint16 } // Opcode returns the ID associated with this packet type. @@ -32,15 +40,27 @@ func (m *MsgMhfPostTenrouirai) Opcode() network.PacketID { func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() + m.Op = bf.ReadUint8() m.GuildID = bf.ReadUint32() - m.Unk3 = bf.ReadUint8() - m.Floors = bf.ReadUint16() - m.Antiques = bf.ReadUint16() - m.Chests = bf.ReadUint16() - m.Cats = bf.ReadUint16() - m.TRP = bf.ReadUint16() - m.Slays = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + + switch m.Op { + case 1: + m.Floors = bf.ReadUint16() + m.Antiques = bf.ReadUint16() + m.Chests = bf.ReadUint16() + m.Cats = bf.ReadUint16() + m.TRP = bf.ReadUint16() + m.Slays = bf.ReadUint16() + case 2: + m.DonatedRP = bf.ReadUint16() + m.PreviousRP = bf.ReadUint16() + m.Unk2_0 = bf.ReadUint16() + m.Unk2_1 = bf.ReadUint16() + m.Unk2_2 = bf.ReadUint16() + m.Unk2_3 = bf.ReadUint16() + } + return nil } diff --git a/patch-schema/tower.sql b/patch-schema/tower.sql index cab01c558..0697fc2be 100644 --- a/patch-schema/tower.sql +++ b/patch-schema/tower.sql @@ -8,7 +8,22 @@ CREATE TABLE IF NOT EXISTS tower ( block1 INT, block2 INT, skills TEXT DEFAULT '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,0,0,0,0,0,0,0,0,0,0,0', - gems TEXT DEFAULT '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' + gems TEXT DEFAULT '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,0' ); +ALTER TABLE IF EXISTS guild_characters + ADD COLUMN IF NOT EXISTS tower_mission_1 INT; + +ALTER TABLE IF EXISTS guild_characters + ADD COLUMN IF NOT EXISTS tower_mission_2 INT; + +ALTER TABLE IF EXISTS guild_characters + ADD COLUMN IF NOT EXISTS tower_mission_3 INT; + +ALTER TABLE IF EXISTS guilds + ADD COLUMN IF NOT EXISTS tower_mission_page INT DEFAULT 1; + +ALTER TABLE IF EXISTS guilds + ADD COLUMN IF NOT EXISTS tower_rp INT DEFAULT 0; + END; \ No newline at end of file diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index aeb1834ab..e4f02b1c8 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -1,6 +1,7 @@ package channelserver import ( + "fmt" "go.uber.org/zap" "erupe-ce/common/byteframe" @@ -130,22 +131,59 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -type TenrouiraiCharScore struct { - Score int32 - Name string +// Default missions +var tenrouiraiData = []TenrouiraiData{ + {1, 1, 80, 0, 2, 2, 1, 1, 2, 2}, + {1, 4, 16, 0, 2, 2, 1, 1, 2, 2}, + {1, 6, 50, 0, 2, 2, 1, 0, 2, 2}, + {1, 4, 12, 50, 2, 2, 1, 1, 2, 2}, + {1, 3, 50, 0, 2, 2, 1, 1, 2, 2}, + {2, 5, 40000, 0, 2, 2, 1, 0, 2, 2}, + {1, 5, 50000, 50, 2, 2, 1, 1, 2, 2}, + {2, 1, 60, 0, 2, 2, 1, 1, 2, 2}, + {2, 3, 50, 0, 2, 1, 1, 0, 1, 2}, + {2, 3, 40, 50, 2, 1, 1, 1, 1, 2}, + {2, 4, 12, 0, 2, 1, 1, 1, 1, 2}, + {2, 6, 40, 0, 2, 1, 1, 0, 1, 2}, + {1, 1, 60, 50, 2, 1, 2, 1, 1, 2}, + {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, + {1, 6, 50, 0, 3, 1, 2, 0, 1, 2}, + {1, 4, 16, 50, 3, 1, 2, 1, 1, 2}, + {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, + {2, 3, 40, 0, 3, 1, 2, 0, 1, 2}, + {1, 3, 50, 50, 3, 1, 2, 1, 1, 2}, + {2, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, + {2, 6, 40, 0, 3, 1, 2, 0, 1, 1}, + {2, 1, 60, 50, 3, 1, 2, 1, 1, 1}, + {2, 6, 50, 0, 3, 1, 2, 1, 1, 1}, + {2, 4, 12, 0, 3, 1, 2, 0, 1, 1}, + {1, 1, 80, 50, 3, 1, 2, 1, 1, 1}, + {1, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, + {1, 3, 50, 0, 3, 1, 2, 0, 1, 1}, + {1, 4, 16, 50, 3, 1, 0, 1, 1, 1}, + {1, 6, 50, 0, 3, 1, 0, 1, 1, 1}, + {2, 3, 40, 0, 3, 1, 0, 1, 1, 1}, + {1, 1, 80, 50, 3, 1, 0, 0, 1, 1}, + {2, 5, 40000, 0, 3, 1, 0, 0, 1, 1}, + {2, 6, 40, 0, 3, 1, 0, 0, 1, 1}, } type TenrouiraiProgress struct { - Completed uint8 - Mission1 uint16 - Mission2 uint16 - Mission3 uint16 + Page uint8 + Mission1 uint16 + Mission2 uint16 + Mission3 uint16 } -type TenrouiraiTicket struct { +type TenrouiraiReward struct { + Index uint8 + Item []uint16 // 5 + Quantity []uint8 // 5 +} + +type TenrouiraiKeyScore struct { Unk0 uint8 - Unk1 uint32 - Unk2 uint32 + Unk1 int32 } type TenrouiraiData struct { @@ -157,21 +195,34 @@ type TenrouiraiData struct { // 4 = Cats saved // 5 = TRP acquisition // 6 = Monster slays - Goal uint16 - Unk3 uint16 - Unk4 uint8 - Unk5 uint8 - Unk6 uint8 - Unk7 uint8 - Unk8 uint8 - Unk9 uint8 + Goal uint16 + Cost uint16 + Skill1 uint8 // 80 + Skill2 uint8 // 40 + Skill3 uint8 // 40 + Skill4 uint8 // 20 + Skill5 uint8 // 40 + Skill6 uint8 // 50 +} + +type TenrouiraiCharScore struct { + Score int32 + Name string +} + +type TenrouiraiTicket struct { + Unk0 uint8 + RP uint32 + Unk2 uint32 } type Tenrouirai struct { - CharScore []TenrouiraiCharScore Progress []TenrouiraiProgress - Ticket []TenrouiraiTicket + Reward []TenrouiraiReward + KeyScore []TenrouiraiKeyScore Data []TenrouiraiData + CharScore []TenrouiraiCharScore + Ticket []TenrouiraiTicket } func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { @@ -179,44 +230,9 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { var data []*byteframe.ByteFrame tenrouirai := Tenrouirai{ - Progress: []TenrouiraiProgress{ - {1, 0, 0, 0}, - }, - Data: []TenrouiraiData{ - {1, 1, 80, 0, 2, 2, 1, 1, 2, 2}, - {1, 4, 16, 0, 2, 2, 1, 1, 2, 2}, - {1, 6, 50, 0, 2, 2, 1, 0, 2, 2}, - {1, 4, 12, 50, 2, 2, 1, 1, 2, 2}, - {1, 3, 50, 0, 2, 2, 1, 1, 2, 2}, - {2, 5, 40000, 0, 2, 2, 1, 0, 2, 2}, - {1, 5, 50000, 50, 2, 2, 1, 1, 2, 2}, - {2, 1, 60, 0, 2, 2, 1, 1, 2, 2}, - {2, 3, 50, 0, 2, 1, 1, 0, 1, 2}, - {2, 3, 40, 50, 2, 1, 1, 1, 1, 2}, - {2, 4, 12, 0, 2, 1, 1, 1, 1, 2}, - {2, 6, 40, 0, 2, 1, 1, 0, 1, 2}, - {1, 1, 60, 50, 2, 1, 2, 1, 1, 2}, - {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, - {1, 6, 50, 0, 3, 1, 2, 0, 1, 2}, - {1, 4, 16, 50, 3, 1, 2, 1, 1, 2}, - {1, 5, 50000, 0, 3, 1, 2, 1, 1, 2}, - {2, 3, 40, 0, 3, 1, 2, 0, 1, 2}, - {1, 3, 50, 50, 3, 1, 2, 1, 1, 2}, - {2, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, - {2, 6, 40, 0, 3, 1, 2, 0, 1, 1}, - {2, 1, 60, 50, 3, 1, 2, 1, 1, 1}, - {2, 6, 50, 0, 3, 1, 2, 1, 1, 1}, - {2, 4, 12, 0, 3, 1, 2, 0, 1, 1}, - {1, 1, 80, 50, 3, 1, 2, 1, 1, 1}, - {1, 5, 40000, 0, 3, 1, 2, 1, 1, 1}, - {1, 3, 50, 0, 3, 1, 2, 0, 1, 1}, - {1, 4, 16, 50, 3, 1, 0, 1, 1, 1}, - {1, 6, 50, 0, 3, 1, 0, 1, 1, 1}, - {2, 3, 40, 0, 3, 1, 0, 1, 1, 1}, - {1, 1, 80, 50, 3, 1, 0, 0, 1, 1}, - {2, 5, 40000, 0, 3, 1, 0, 0, 1, 1}, - {2, 6, 40, 0, 3, 1, 0, 0, 1, 1}, - }, + Progress: []TenrouiraiProgress{{1, 0, 0, 0}}, + Data: tenrouiraiData, + Ticket: []TenrouiraiTicket{{0, 0, 0}}, } switch pkt.Unk1 { @@ -226,24 +242,75 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(tdata.Block) bf.WriteUint8(tdata.Mission) bf.WriteUint16(tdata.Goal) - bf.WriteUint16(tdata.Unk3) - bf.WriteUint8(tdata.Unk4) - bf.WriteUint8(tdata.Unk5) - bf.WriteUint8(tdata.Unk6) - bf.WriteUint8(tdata.Unk7) - bf.WriteUint8(tdata.Unk8) - bf.WriteUint8(tdata.Unk9) + bf.WriteUint16(tdata.Cost) + bf.WriteUint8(tdata.Skill1) + bf.WriteUint8(tdata.Skill2) + bf.WriteUint8(tdata.Skill3) + bf.WriteUint8(tdata.Skill4) + bf.WriteUint8(tdata.Skill5) + bf.WriteUint8(tdata.Skill6) + data = append(data, bf) + } + case 2: + for _, reward := range tenrouirai.Reward { + bf := byteframe.NewByteFrame() + bf.WriteUint8(reward.Index) + bf.WriteUint16(reward.Item[0]) + bf.WriteUint16(reward.Item[1]) + bf.WriteUint16(reward.Item[2]) + bf.WriteUint16(reward.Item[3]) + bf.WriteUint16(reward.Item[4]) + bf.WriteUint8(reward.Quantity[0]) + bf.WriteUint8(reward.Quantity[1]) + bf.WriteUint8(reward.Quantity[2]) + bf.WriteUint8(reward.Quantity[3]) + bf.WriteUint8(reward.Quantity[4]) data = append(data, bf) } case 4: + s.server.db.QueryRow(`SELECT tower_mission_page FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Page) + s.server.db.QueryRow(`SELECT SUM(tower_mission_1) AS _, SUM(tower_mission_2) AS _, SUM(tower_mission_3) AS _ FROM guild_characters WHERE guild_id=$1 + `, pkt.GuildID).Scan(&tenrouirai.Progress[0].Mission1, &tenrouirai.Progress[0].Mission2, &tenrouirai.Progress[0].Mission3) + + if tenrouirai.Progress[0].Mission1 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-3].Goal { + tenrouirai.Progress[0].Mission1 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-3].Goal + } + if tenrouirai.Progress[0].Mission2 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal { + tenrouirai.Progress[0].Mission2 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal + } + if tenrouirai.Progress[0].Mission1 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal { + tenrouirai.Progress[0].Mission1 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal + } + for _, progress := range tenrouirai.Progress { bf := byteframe.NewByteFrame() - bf.WriteUint8(progress.Completed) + bf.WriteUint8(progress.Page) bf.WriteUint16(progress.Mission1) bf.WriteUint16(progress.Mission2) bf.WriteUint16(progress.Mission3) data = append(data, bf) } + case 5: + rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c on gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL`, pkt.Unk3, pkt.Unk3), pkt.GuildID) + for rows.Next() { + temp := TenrouiraiCharScore{} + rows.Scan(&temp.Name, &temp.Score) + tenrouirai.CharScore = append(tenrouirai.CharScore, temp) + } + for _, charScore := range tenrouirai.CharScore { + bf := byteframe.NewByteFrame() + bf.WriteInt32(charScore.Score) + bf.WriteBytes(stringsupport.PaddedString(charScore.Name, 14, true)) + data = append(data, bf) + } + case 6: + for _, ticket := range tenrouirai.Ticket { + bf := byteframe.NewByteFrame() + bf.WriteUint8(ticket.Unk0) + bf.WriteUint32(ticket.RP) + bf.WriteUint32(ticket.Unk2) + data = append(data, bf) + } } doAckEarthSucceed(s, pkt.AckHandle, data) @@ -256,9 +323,9 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { s.logger.Debug( p.Opcode().String(), zap.Uint8("Unk0", pkt.Unk0), - zap.Uint8("Unk1", pkt.Unk1), + zap.Uint8("Op", pkt.Op), zap.Uint32("GuildID", pkt.GuildID), - zap.Uint8("Unk3", pkt.Unk3), + zap.Uint8("Unk1", pkt.Unk1), zap.Uint16("Floors", pkt.Floors), zap.Uint16("Antiques", pkt.Antiques), zap.Uint16("Chests", pkt.Chests), @@ -308,10 +375,10 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { gemInfo := []GemInfo{} gemHistory := []GemHistory{} - tempGems := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + tempGems := "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,0" s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&tempGems) for i, v := range stringsupport.CSVElems(tempGems) { - gemInfo = append(gemInfo, GemInfo{uint16(((i / 3) * 256) + ((i % 3) + 1)), uint16(v)}) + gemInfo = append(gemInfo, GemInfo{uint16(((i / 5) * 256) + ((i % 5) + 1)), uint16(v)}) } switch pkt.Unk0 { @@ -351,11 +418,11 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { ) } - gems := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + gems := "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,0" s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&gems) switch pkt.Op { case 1: // Add gem - i := int(((pkt.Gem / 256) * 3) + (((pkt.Gem - ((pkt.Gem / 256) * 256)) - 1) % 3)) + i := int(((pkt.Gem / 256) * 5) + (((pkt.Gem - ((pkt.Gem / 256) * 256)) - 1) % 5)) s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID) case 2: // Transfer gem // no way im doing this for now From 36cdc77321b02fecdb02917ddcba09e3497cad4c Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 00:18:08 +1000 Subject: [PATCH 42/99] fix contribution sorting --- server/channelserver/handlers_tower.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index e4f02b1c8..11158155d 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -291,7 +291,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } case 5: - rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c on gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL`, pkt.Unk3, pkt.Unk3), pkt.GuildID) + rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID) for rows.Next() { temp := TenrouiraiCharScore{} rows.Scan(&temp.Name, &temp.Score) From fa5b5bb774fac3598bfa5922cb7eb14fd8d7f776 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 00:19:44 +1000 Subject: [PATCH 43/99] fix variable mistake --- server/channelserver/handlers_tower.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 11158155d..e873e0056 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -278,8 +278,8 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { if tenrouirai.Progress[0].Mission2 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal { tenrouirai.Progress[0].Mission2 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal } - if tenrouirai.Progress[0].Mission1 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal { - tenrouirai.Progress[0].Mission1 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal + if tenrouirai.Progress[0].Mission3 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal { + tenrouirai.Progress[0].Mission3 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal } for _, progress := range tenrouirai.Progress { From cdf7b09c484f005d4fad95f6dab25ae7af8db8e7 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 02:47:40 +1000 Subject: [PATCH 44/99] partial Tenrouirai progression automation --- server/channelserver/handlers_tower.go | 37 +++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index e873e0056..7675f114e 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -291,6 +291,12 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } case 5: + if pkt.Unk3 > 3 { + pkt.Unk3 %= 3 + if pkt.Unk3 == 0 { + pkt.Unk3 = 3 + } + } rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID) for rows.Next() { temp := TenrouiraiCharScore{} @@ -304,6 +310,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } case 6: + s.server.db.QueryRow(`SELECT tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Ticket[0].RP) for _, ticket := range tenrouirai.Ticket { bf := byteframe.NewByteFrame() bf.WriteUint8(ticket.Unk0) @@ -335,7 +342,35 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { ) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + if pkt.Op == 2 { + var page, requirement, donated int + s.server.db.QueryRow(`SELECT tower_mission_page, tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&page, &donated) + + for i := 0; i < (page*3)+1; i++ { + requirement += int(tenrouiraiData[i].Cost) + } + + bf := byteframe.NewByteFrame() + + sd, err := GetCharacterSaveData(s, s.charID) + if err == nil && sd != nil { + sd.RP -= pkt.DonatedRP + sd.Save(s) + if donated+int(pkt.DonatedRP) >= requirement { + s.server.db.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID) + s.server.db.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID) + pkt.DonatedRP = uint16(requirement - donated) + } + bf.WriteUint32(uint32(pkt.DonatedRP)) + s.server.db.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID) + } else { + bf.WriteUint32(0) + } + + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + } else { + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + } } func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { From fb5294e705f8d197c26b50bd81d758c2923f032e Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 12:24:20 +1000 Subject: [PATCH 45/99] decode Get/PostNotice and GemHistory --- network/mhfpacket/msg_mhf_get_notice.go | 21 ++++++++++++----- network/mhfpacket/msg_mhf_post_notice.go | 23 ++++++++++++++----- server/channelserver/handlers.go | 4 ---- server/channelserver/handlers_tower.go | 29 ++++++++++++++++-------- 4 files changed, 52 insertions(+), 25 deletions(-) diff --git a/network/mhfpacket/msg_mhf_get_notice.go b/network/mhfpacket/msg_mhf_get_notice.go index 75e18d9d5..843e71ddc 100644 --- a/network/mhfpacket/msg_mhf_get_notice.go +++ b/network/mhfpacket/msg_mhf_get_notice.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetNotice represents the MSG_MHF_GET_NOTICE -type MsgMhfGetNotice struct{} +type MsgMhfGetNotice struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetNotice) Opcode() network.PacketID { @@ -18,7 +23,11 @@ func (m *MsgMhfGetNotice) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_post_notice.go b/network/mhfpacket/msg_mhf_post_notice.go index c599d2afc..51eb945fa 100644 --- a/network/mhfpacket/msg_mhf_post_notice.go +++ b/network/mhfpacket/msg_mhf_post_notice.go @@ -1,15 +1,21 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostNotice represents the MSG_MHF_POST_NOTICE -type MsgMhfPostNotice struct{} +type MsgMhfPostNotice struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 + Unk3 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfPostNotice) Opcode() network.PacketID { @@ -18,7 +24,12 @@ func (m *MsgMhfPostNotice) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 614b98da1..4647b8021 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1632,10 +1632,6 @@ func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {} - func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 7675f114e..a9bc1421c 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -3,6 +3,7 @@ package channelserver import ( "fmt" "go.uber.org/zap" + "time" "erupe-ce/common/byteframe" "erupe-ce/common/stringsupport" @@ -398,10 +399,10 @@ type GemInfo struct { } type GemHistory struct { - Unk0 uint16 - Unk1 uint16 - Unk2 uint32 - Unk3 string + Gem uint16 + Message uint16 + Timestamp time.Time + Sender string } func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { @@ -424,13 +425,13 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(info.Quantity) data = append(data, bf) } - default: + case 2: for _, history := range gemHistory { bf := byteframe.NewByteFrame() - bf.WriteUint16(history.Unk0) - bf.WriteUint16(history.Unk1) - bf.WriteUint32(history.Unk2) - bf.WriteBytes(stringsupport.PaddedString(history.Unk3, 14, true)) + bf.WriteUint16(history.Gem) + bf.WriteUint16(history.Message) + bf.WriteUint32(uint32(history.Timestamp.Unix())) + bf.WriteBytes(stringsupport.PaddedString(history.Sender, 14, true)) data = append(data, bf) } } @@ -464,3 +465,13 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } + +func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetNotice) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostNotice) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} From 586ae8b388db4370cb06f348ae282d2db9e20776 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 25 Jun 2023 21:44:59 +1000 Subject: [PATCH 46/99] add comment descriptions for PaperData --- server/channelserver/handlers_data.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/server/channelserver/handlers_data.go b/server/channelserver/handlers_data.go index ac8f7bf5c..b033988b2 100644 --- a/server/channelserver/handlers_data.go +++ b/server/channelserver/handlers_data.go @@ -1134,30 +1134,40 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { } case 5: paperData = []PaperData{ + // getTowerQuestTowerLevel {1001, 1, 0, 0, 0, 0, 0}, {1001, 2, 0, 0, 0, 0, 0}, + // iniTQT {1003, 1, 100, 100, 200, 100, 0}, {1003, 2, 150, 100, 240, 100, 0}, {1004, 10, 9999, 40, 0, 0, 0}, {1005, 10, 500, 0, 0, 0, 0}, + // getPaperDataSetFromProp {1007, 1, 0, 0, 0, 0, 0}, {1008, 200, 400, 3000, 400, 3000, 0}, + // getPaperDataSetParam1 / Dure Goal {1010, 1, 4000, 0, 0, 0, 0}, {1010, 2, 4000, 0, 0, 0, 0}, + // update_disp_flag / getPaperDataSetParam1 {1011, 1, 6000, 15000, 20000, 25000, 30000}, {1011, 2, 6000, 15000, 20000, 25000, 30000}, {1012, 1, 8000, 17500, 22500, 27500, 31000}, {1012, 2, 8000, 17500, 22500, 27500, 31000}, + // setServerZako {1015, 1, 16, 16, 16, 0, 0}, {1015, 2, 16, 16, 16, 0, 0}, + // createTowerFloorRandomNumberArray {1101, 1, 2016, 500, 0, 0, 0}, {1101, 2, 2016, 500, 0, 0, 0}, + // HRP/SRP/GRP/GSRP/TRP reward {1103, 1, 0, 0, 3000, 0, 3000}, {1103, 2, 0, 0, 3000, 0, 3000}, + // getTowerNextVenomLevel {1104, 1, 10, 9999, 40, 0, 0}, {1104, 2, 10, 9999, 40, 0, 0}, {1105, 1, 10, 500, 0, 0, 0}, {1105, 2, 10, 500, 0, 0, 0}, + // setServerBoss {2001, 1, 17, 58, 0, 6, 700}, {2001, 1, 20, 58, 0, 3, 200}, {2001, 1, 22, 58, 0, 7, 250}, @@ -1189,10 +1199,13 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { } case 6: paperData = []PaperData{ + // updateClearTowerFloor {1002, 100, 0, 0, 0, 0, 0}, + // give_gem_func {1006, 1, 10000, 10000, 0, 0, 0}, {1006, 2, 10000, 20000, 0, 0, 0}, {1009, 20, 0, 0, 0, 0, 0}, + // ttcStageInitDRP {1013, 1, 1, 1, 100, 200, 300}, {1013, 1, 1, 2, 100, 200, 300}, {1013, 1, 2, 1, 300, 100, 200}, @@ -1219,6 +1232,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {1016, 2, 3, 80, 0, 0, 0}, {1201, 1, 60, 50, 0, 0, 0}, {1201, 2, 60, 50, 0, 0, 0}, + // Gimmick Damage {ID, Block, StartFloor, EndFloor, Multiplier*100, Unk, Unk} {1202, 1, 0, 5, 50, 0, 0}, {1202, 1, 6, 20, 60, 0, 0}, {1202, 1, 21, 40, 70, 0, 0}, @@ -1231,6 +1245,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {1202, 2, 101, 200, 100, 0, 0}, {1202, 2, 201, 500, 150, 0, 0}, {1202, 2, 501, 9999, 150, 0, 0}, + // Mon Damage {ID, Block, StartFloor, EndFloor, Multiplier*100, Unk, Unk} {1203, 1, 0, 5, 10, 0, 0}, {1203, 1, 6, 10, 20, 0, 0}, {1203, 1, 11, 30, 30, 0, 0}, @@ -1246,6 +1261,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {1203, 2, 0, 120, 70, 0, 0}, {1203, 2, 121, 500, 120, 0, 0}, {1203, 2, 501, 9999, 120, 0, 0}, + // Mon HP {ID, Block, StartFloor, EndFloor, Multiplier*100, Unk, Unk} {1204, 1, 0, 5, 15, 0, 0}, {1204, 1, 6, 10, 20, 0, 0}, {1204, 1, 11, 15, 25, 0, 0}, @@ -1270,6 +1286,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {1204, 2, 0, 120, 70, 0, 0}, {1204, 2, 121, 500, 120, 0, 0}, {1204, 2, 501, 9999, 120, 0, 0}, + // Supply Items {ID, Block, Unk, ItemID, Quantity, Unk, Unk} {4001, 1, 0, 0, 0, 0, 0}, {4001, 2, 0, 10667, 5, 0, 1}, {4001, 2, 0, 10667, 5, 0, 1}, @@ -1295,6 +1312,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {4001, 2, 0, 10683, 2, 0, 1}, {4001, 2, 0, 10678, 1, 0, 1}, {4001, 2, 0, 10678, 1, 0, 1}, + // Item Rewards {ID, Block, Unk, ItemID, Quantity?, Chance*100, Unk} {4005, 1, 0, 11159, 1, 5000, 1}, {4005, 1, 0, 11160, 1, 3350, 1}, {4005, 1, 0, 11161, 1, 1500, 1}, @@ -1596,6 +1614,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { {4007, 2, 0, 11467, 1, 250, 1}, {4007, 2, 0, 11468, 1, 500, 1}, {4007, 2, 0, 11469, 1, 175, 1}, + // Probably treasure chest rewards {4202, 1, 0, 11163, 1, 6000, 1}, {4202, 1, 0, 11465, 1, 200, 1}, {4202, 1, 0, 11466, 1, 100, 1}, From aaefb207de073f5069387cdc93220fac68b6cd00 Mon Sep 17 00:00:00 2001 From: wish Date: Tue, 27 Jun 2023 22:29:44 +1000 Subject: [PATCH 47/99] prevent lockup on Z1 StampcardStamp --- network/mhfpacket/msg_mhf_stampcard_stamp.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/network/mhfpacket/msg_mhf_stampcard_stamp.go b/network/mhfpacket/msg_mhf_stampcard_stamp.go index 8d18ae971..ec6dac6db 100644 --- a/network/mhfpacket/msg_mhf_stampcard_stamp.go +++ b/network/mhfpacket/msg_mhf_stampcard_stamp.go @@ -2,6 +2,7 @@ package mhfpacket import ( "errors" + _config "erupe-ce/config" "erupe-ce/common/byteframe" "erupe-ce/network" @@ -34,12 +35,14 @@ func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli m.GR = bf.ReadUint16() m.Stamps = bf.ReadUint16() _ = bf.ReadUint16() - m.Reward1 = uint16(bf.ReadUint32()) - m.Reward2 = uint16(bf.ReadUint32()) - m.Item1 = uint16(bf.ReadUint32()) - m.Item2 = uint16(bf.ReadUint32()) - m.Quantity1 = uint16(bf.ReadUint32()) - m.Quantity2 = uint16(bf.ReadUint32()) + if _config.ErupeConfig.ClientMode != _config.Z1 { + m.Reward1 = uint16(bf.ReadUint32()) + m.Reward2 = uint16(bf.ReadUint32()) + m.Item1 = uint16(bf.ReadUint32()) + m.Item2 = uint16(bf.ReadUint32()) + m.Quantity1 = uint16(bf.ReadUint32()) + m.Quantity2 = uint16(bf.ReadUint32()) + } return nil } From e96e6372f51a6c1850ef1f1cd4431a901b9a693a Mon Sep 17 00:00:00 2001 From: wish Date: Tue, 27 Jun 2023 22:39:44 +1000 Subject: [PATCH 48/99] hacky fix for PSSGN panic --- server/signserver/session.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/signserver/session.go b/server/signserver/session.go index de46c5337..2a83afc6a 100644 --- a/server/signserver/session.go +++ b/server/signserver/session.go @@ -156,6 +156,13 @@ func (s *Session) handleWIIUSGN(bf *byteframe.ByteFrame) { } func (s *Session) handlePSSGN(bf *byteframe.ByteFrame) { + // Prevent reading malformed request + if len(bf.DataFromCurrent()) < 128 { + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(SIGN_EABORT)) + s.cryptConn.SendPacket(resp.Data()) + return + } _ = bf.ReadNullTerminatedBytes() // VITA = 0000000256, PS3 = 0000000255 _ = bf.ReadBytes(2) // VITA = 1, PS3 = ! _ = bf.ReadBytes(82) From 9c09ed1c4a66a123ed6dfa725b5fa884d008487e Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 30 Jun 2023 21:51:28 +1000 Subject: [PATCH 49/99] fix diva defense timestamps --- server/channelserver/handlers_diva.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index 10d0c0a2b..d97865706 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -80,12 +80,11 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { timestamps = generateDivaTimestamps(s, start, false) } - bf.WriteUint32(id) - for i, timestamp := range timestamps { - if s.server.erupeConfig.ClientMode == _config.Z1 && i == 4 { - continue - } - bf.WriteUint32(timestamp) + if s.server.erupeConfig.ClientMode != _config.Z1 { + bf.WriteUint32(id) + } + for i := range timestamps { + bf.WriteUint32(timestamps[i]) } bf.WriteUint16(0x19) // Unk 00011001 From f526624fd64b04d96def7e65359309efabcd688d Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 30 Jun 2023 21:55:57 +1000 Subject: [PATCH 50/99] fix diva defense timestamps --- server/channelserver/handlers_diva.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index d97865706..14baf8b2b 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -72,7 +72,11 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { var timestamps []uint32 if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DivaEvent >= 0 { if s.server.erupeConfig.DevModeOptions.DivaEvent == 0 { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) + if s.server.erupeConfig.ClientMode == _config.Z1 { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32)) + } else { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) + } return } timestamps = generateDivaTimestamps(s, uint32(s.server.erupeConfig.DevModeOptions.DivaEvent), true) From 1169684e5bee17f886ce85d650b318ed160e81f2 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 1 Jul 2023 12:53:17 +1000 Subject: [PATCH 51/99] remove test PaperMission data --- server/channelserver/handlers_data.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/server/channelserver/handlers_data.go b/server/channelserver/handlers_data.go index b033988b2..bf8ed7a29 100644 --- a/server/channelserver/handlers_data.go +++ b/server/channelserver/handlers_data.go @@ -1123,14 +1123,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { case 0: paperMissions = PaperMission{ []PaperMissionTimetable{{TimeMidnight(), TimeMidnight().Add(24 * time.Hour)}}, - []PaperMissionData{ - {1, 1, 50, 7, 10, 8, 10}, - {1, 2, 50, 7, 10, 8, 10}, - {1, 3, 50, 7, 10, 8, 10}, - {1, 4, 50, 7, 10, 8, 10}, - {1, 5, 50, 7, 10, 8, 10}, - {1, 6, 50, 7, 10, 8, 10}, - }, + []PaperMissionData{}, } case 5: paperData = []PaperData{ From 758bd90ab313f7559ea4aefa5779b1c6a9c4396b Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 2 Jul 2023 17:06:28 +1000 Subject: [PATCH 52/99] fix the last two bytes of HunterNavi savedata being clipped off --- server/channelserver/handlers_mercenary.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_mercenary.go b/server/channelserver/handlers_mercenary.go index 85ca65f9a..6d935fc92 100644 --- a/server/channelserver/handlers_mercenary.go +++ b/server/channelserver/handlers_mercenary.go @@ -54,13 +54,15 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) { doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } +const NaviLength = 552 + func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) var data []byte err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) if len(data) == 0 { s.logger.Error("Failed to load hunternavi", zap.Error(err)) - data = make([]byte, 0x226) + data = make([]byte, NaviLength) } doAckBufSucceed(s, pkt.AckHandle, data) } @@ -78,7 +80,7 @@ func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { // Check if we actually had any hunternavi data, using a blank buffer if not. // This is requried as the client will try to send a diff after character creation without a prior MsgMhfSaveHunterNavi packet. if len(data) == 0 { - data = make([]byte, 0x226) + data = make([]byte, NaviLength) } // Perform diff and compress it to write back to db From b7f9751787f7bb858d0a24c52dfc41050036e631 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 2 Jul 2023 22:56:52 +1000 Subject: [PATCH 53/99] handle BoostTime packets --- .../mhfpacket/msg_mhf_post_boost_time_limit.go | 17 +++++++++++------ server/channelserver/handlers_cafe.go | 10 ++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/network/mhfpacket/msg_mhf_post_boost_time_limit.go b/network/mhfpacket/msg_mhf_post_boost_time_limit.go index 3f0bc53b8..259712ac8 100644 --- a/network/mhfpacket/msg_mhf_post_boost_time_limit.go +++ b/network/mhfpacket/msg_mhf_post_boost_time_limit.go @@ -1,15 +1,18 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostBoostTimeLimit represents the MSG_MHF_POST_BOOST_TIME_LIMIT -type MsgMhfPostBoostTimeLimit struct{} +type MsgMhfPostBoostTimeLimit struct { + AckHandle uint32 + Expiration uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfPostBoostTimeLimit) Opcode() network.PacketID { @@ -18,7 +21,9 @@ func (m *MsgMhfPostBoostTimeLimit) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostBoostTimeLimit) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Expiration = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers_cafe.go b/server/channelserver/handlers_cafe.go index 46a6425a0..67b7c3807 100644 --- a/server/channelserver/handlers_cafe.go +++ b/server/channelserver/handlers_cafe.go @@ -270,6 +270,12 @@ func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) { doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } -func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostBoostTime) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} -func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostBoostTimeLimit) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} From 1f93419cb769a9b3cfc85a308acf6f13143a0f2a Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 3 Jul 2023 00:30:44 +1000 Subject: [PATCH 54/99] add support for more versions --- config/config.go | 74 ++++++++++++++++---- main.go | 2 +- network/mhfpacket/msg_mhf_enumerate_quest.go | 2 +- network/mhfpacket/msg_mhf_stampcard_stamp.go | 2 +- server/channelserver/handlers_character.go | 4 +- server/channelserver/handlers_diva.go | 4 +- server/channelserver/handlers_event.go | 5 +- server/channelserver/handlers_guild.go | 2 +- server/channelserver/handlers_mercenary.go | 15 ++-- server/entranceserver/make_resp.go | 37 ++++++++-- server/signserver/dsgn_resp.go | 8 ++- 11 files changed, 120 insertions(+), 35 deletions(-) diff --git a/config/config.go b/config/config.go index 9e96031a8..7ef6c9bad 100644 --- a/config/config.go +++ b/config/config.go @@ -11,16 +11,58 @@ import ( "github.com/spf13/viper" ) -type Mode string +type Mode int const ( - ZZ Mode = "ZZ" - Z2 Mode = "Z2" - Z1 Mode = "Z1" + S1 Mode = iota + 1 + S15 + S2 + S25 + S3 + S35 + S4 + S5 + S55 + S6 + S7 + S8 + S85 + S9 + S10 + F1 + F2 + F3 + F4 + F5 + G1 + G2 + G3 + G31 + G32 + GG + G5 + G51 + G52 + G6 + G61 + G7 + G8 + G81 + G9 + G91 + G10 + G101 + Z1 + Z2 + ZZ ) +var versionStrings = []string{"S1.0", "S1.5", "S2.0", "S2.5", "S3.0", "S3.5", "S4.0", "S5.0", "S5.5", "S6.0", "S7.0", + "S8.0", "S8.5", "S9", "S10", "FW.1", "FW.2", "FW.3", "FW.4", "FW.5", "G1", "G2", "G3", "G3.1", "G3.2", "GG", "G5", + "G5.1", "G5.2", "G6", "G6.1", "G7", "G8", "G8.1", "G9", "G9.1", "G10", "G10.1", "Z1", "Z2", "ZZ"} + func (m Mode) String() string { - return string(m) + return versionStrings[m] } // Config holds the global server-wide config. @@ -35,7 +77,8 @@ type Config struct { PatchServerFile string // File patch server override ScreenshotAPIURL string // Destination for screenshots uploaded to BBS DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion - ClientMode Mode + ClientMode string + RealClientMode Mode DevMode bool DevModeOptions DevModeOptions @@ -225,13 +268,18 @@ func LoadConfig() (*Config, error) { c.Host = getOutboundIP4().To4().String() } - switch strings.ToUpper(c.ClientMode.String()) { - case "Z1": - c.ClientMode = Z1 - case "Z2": - c.ClientMode = Z2 - default: - c.ClientMode = ZZ + for i := range versionStrings { + if strings.ToUpper(c.ClientMode) == versionStrings[i] { + c.RealClientMode = Mode(i + 1) + c.ClientMode = strings.ToUpper(c.ClientMode) + if c.RealClientMode < Z1 { + c.ClientMode += " (Debug only)" + } + } + } + if c.RealClientMode == 0 { + c.ClientMode = versionStrings[len(versionStrings)-1] + c.RealClientMode = ZZ } return c, nil diff --git a/main.go b/main.go index 6f1abc011..dacd0dd18 100644 --- a/main.go +++ b/main.go @@ -56,7 +56,7 @@ func main() { logger := zapLogger.Named("main") logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit())) - logger.Info(fmt.Sprintf("Client Mode: %s", config.ClientMode.String())) + logger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.RealClientMode)) if config.Database.Password == "" { preventClose("Database password is blank") diff --git a/network/mhfpacket/msg_mhf_enumerate_quest.go b/network/mhfpacket/msg_mhf_enumerate_quest.go index 5961cf152..2bc7ea967 100644 --- a/network/mhfpacket/msg_mhf_enumerate_quest.go +++ b/network/mhfpacket/msg_mhf_enumerate_quest.go @@ -31,7 +31,7 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli m.World = bf.ReadUint8() m.Counter = bf.ReadUint16() m.Offset = bf.ReadUint16() - if _config.ErupeConfig.ClientMode != _config.Z1 { + if _config.ErupeConfig.RealClientMode > _config.Z1 { m.Unk4 = bf.ReadUint8() } return nil diff --git a/network/mhfpacket/msg_mhf_stampcard_stamp.go b/network/mhfpacket/msg_mhf_stampcard_stamp.go index ec6dac6db..5ac650ad2 100644 --- a/network/mhfpacket/msg_mhf_stampcard_stamp.go +++ b/network/mhfpacket/msg_mhf_stampcard_stamp.go @@ -35,7 +35,7 @@ func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli m.GR = bf.ReadUint16() m.Stamps = bf.ReadUint16() _ = bf.ReadUint16() - if _config.ErupeConfig.ClientMode != _config.Z1 { + if _config.ErupeConfig.RealClientMode > _config.Z1 { m.Reward1 = uint16(bf.ReadUint32()) m.Reward2 = uint16(bf.ReadUint32()) m.Item1 = uint16(bf.ReadUint32()) diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 320d459a6..01d9dc73a 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -148,7 +148,7 @@ func (save *CharacterSaveData) Decompress() error { func (save *CharacterSaveData) updateSaveDataWithStruct() { rpBytes := make([]byte, 2) binary.LittleEndian.PutUint16(rpBytes, save.RP) - if _config.ErupeConfig.ClientMode == _config.ZZ { + if _config.ErupeConfig.RealClientMode == _config.ZZ { copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) } else { @@ -166,7 +166,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() { save.Gender = false } if !save.IsNewCharacter { - if _config.ErupeConfig.ClientMode == _config.ZZ { + if _config.ErupeConfig.RealClientMode == _config.ZZ { save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2]) save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5] save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195] diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index 14baf8b2b..1867bfacd 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -72,7 +72,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { var timestamps []uint32 if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DivaEvent >= 0 { if s.server.erupeConfig.DevModeOptions.DivaEvent == 0 { - if s.server.erupeConfig.ClientMode == _config.Z1 { + if s.server.erupeConfig.RealClientMode <= _config.Z1 { doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32)) } else { doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) @@ -84,7 +84,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { timestamps = generateDivaTimestamps(s, start, false) } - if s.server.erupeConfig.ClientMode != _config.Z1 { + if s.server.erupeConfig.RealClientMode <= _config.Z1 { bf.WriteUint32(id) } for i := range timestamps { diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index ffc1b895f..41da41318 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -92,9 +92,12 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { func generateFeatureWeapons(count int) activeFeature { max := 14 - if _config.ErupeConfig.ClientMode != _config.ZZ { + if _config.ErupeConfig.RealClientMode < _config.ZZ { max = 13 } + if _config.ErupeConfig.RealClientMode < _config.GG { + max = 12 + } if count > max { count = max } diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index ec58c7487..c05b15f68 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -1391,7 +1391,7 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(member.CharID) bf.WriteUint16(member.HRP) bf.WriteUint16(member.GR) - if s.server.erupeConfig.ClientMode != _config.ZZ { + if s.server.erupeConfig.RealClientMode < _config.ZZ { // Magnet Spike crash workaround bf.WriteUint16(0) } else { diff --git a/server/channelserver/handlers_mercenary.go b/server/channelserver/handlers_mercenary.go index 6d935fc92..810786751 100644 --- a/server/channelserver/handlers_mercenary.go +++ b/server/channelserver/handlers_mercenary.go @@ -3,6 +3,7 @@ package channelserver import ( "erupe-ce/common/byteframe" "erupe-ce/common/stringsupport" + _config "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/server/channelserver/compression/deltacomp" "erupe-ce/server/channelserver/compression/nullcomp" @@ -54,15 +55,17 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) { doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -const NaviLength = 552 - func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) + naviLength := 552 + if s.server.erupeConfig.RealClientMode <= _config.G7 { + naviLength = 280 + } var data []byte err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) if len(data) == 0 { s.logger.Error("Failed to load hunternavi", zap.Error(err)) - data = make([]byte, NaviLength) + data = make([]byte, naviLength) } doAckBufSucceed(s, pkt.AckHandle, data) } @@ -70,6 +73,10 @@ func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi) if pkt.IsDataDiff { + naviLength := 552 + if s.server.erupeConfig.RealClientMode <= _config.G7 { + naviLength = 280 + } var data []byte // Load existing save err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) @@ -80,7 +87,7 @@ func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { // Check if we actually had any hunternavi data, using a blank buffer if not. // This is requried as the client will try to send a diff after character creation without a prior MsgMhfSaveHunterNavi packet. if len(data) == 0 { - data = make([]byte, NaviLength) + data = make([]byte, naviLength) } // Perform diff and compress it to write back to db diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index ac63a8ad5..40789294d 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -25,11 +25,16 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { for serverIdx, si := range serverInfos { // Prevent MezFes Worlds displaying on Z1 - if config.ClientMode == _config.Z1 { + if config.RealClientMode <= _config.Z1 { if si.Type == 6 { continue } } + if config.RealClientMode <= _config.G6 { + if si.Type == 5 { + continue + } + } sid := (4096 + serverIdx*256) + 16 err := s.db.QueryRow("SELECT season FROM servers WHERE server_id=$1", sid).Scan(&season) if err != nil { @@ -49,10 +54,19 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteUint8(si.Type) bf.WriteUint8(season) bf.WriteUint8(si.Recommended) - bf.WriteUint8(0) // Prevents malformed server name - combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) - combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) - bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) + + if s.erupeConfig.RealClientMode <= _config.GG { + bf.WriteUint8(64) // Prevents malformed server name + combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) + combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) + bf.WriteBytes(stringsupport.PaddedString(string(combined), 64, false)) + } else { + bf.WriteUint8(0) // Prevents malformed server name + combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) + combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) + bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) + } + bf.WriteUint32(si.AllowedClientFlags) for channelIdx, ci := range si.Channels { @@ -101,13 +115,22 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte { serverInfos := config.Entrance.Entries // Decrease by the number of MezFes Worlds var mf int - if config.ClientMode == _config.Z1 { + if config.RealClientMode <= _config.Z1 { for _, si := range serverInfos { if si.Type == 6 { mf++ } } } + // and Return Worlds + var ret int + if config.RealClientMode <= _config.G6 { + for _, si := range serverInfos { + if si.Type == 5 { + ret++ + } + } + } rawServerData := encodeServerInfo(config, s, local) if s.erupeConfig.DevMode && s.erupeConfig.DevModeOptions.LogOutboundMessages { @@ -115,7 +138,7 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte { } bf := byteframe.NewByteFrame() - bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-mf), 0x00)) + bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-(mf+ret)), 0x00)) return bf.Data() } diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 5d47dc067..65874b683 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -5,6 +5,7 @@ import ( ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" "erupe-ce/common/token" + _config "erupe-ce/config" "erupe-ce/server/channelserver" "fmt" "go.uber.org/zap" @@ -77,8 +78,11 @@ func (s *Session) makeSignResponse(uid int) []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 - bf.WriteUint16(char.GR) - bf.WriteUint16(0) // Unk + if s.server.erupeConfig.RealClientMode >= _config.G7 { + bf.WriteUint16(char.GR) + bf.WriteUint8(0) // Unk + bf.WriteUint8(0) // Unk + } } friends := s.server.getFriendsForCharacters(chars) From d23b6eb61a3b1f2e75296869956708ef00ed2d38 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 3 Jul 2023 02:08:05 +1000 Subject: [PATCH 55/99] forgot SAF --- server/channelserver/handlers_event.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index 41da41318..ff84b4a7a 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -95,9 +95,12 @@ func generateFeatureWeapons(count int) activeFeature { if _config.ErupeConfig.RealClientMode < _config.ZZ { max = 13 } - if _config.ErupeConfig.RealClientMode < _config.GG { + if _config.ErupeConfig.RealClientMode < _config.G10 { max = 12 } + if _config.ErupeConfig.RealClientMode < _config.GG { + max = 11 + } if count > max { count = max } From d1302338600f355cedfc2a2bfc40db25bcbfb824 Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 3 Jul 2023 03:13:23 +1000 Subject: [PATCH 56/99] add support for SVR Entrance responses --- server/entranceserver/make_resp.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 40789294d..0e2466865 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -56,10 +56,10 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteUint8(si.Recommended) if s.erupeConfig.RealClientMode <= _config.GG { - bf.WriteUint8(64) // Prevents malformed server name combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) - bf.WriteBytes(stringsupport.PaddedString(string(combined), 64, false)) + bf.WriteUint8(uint8(len(combined))) + bf.WriteBytes(combined) } else { bf.WriteUint8(0) // Prevents malformed server name combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) @@ -67,7 +67,9 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) } - bf.WriteUint32(si.AllowedClientFlags) + if s.erupeConfig.RealClientMode >= _config.GG { + bf.WriteUint32(si.AllowedClientFlags) + } for channelIdx, ci := range si.Channels { sid = (4096 + serverIdx*256) + (16 + channelIdx) @@ -137,8 +139,13 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte { fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(rawServerData), hex.Dump(rawServerData)) } + respType := "SV2" + if config.RealClientMode <= _config.G32 { + respType = "SVR" + } + bf := byteframe.NewByteFrame() - bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-(mf+ret)), 0x00)) + bf.WriteBytes(makeHeader(rawServerData, respType, uint16(len(serverInfos)-(mf+ret)), 0x00)) return bf.Data() } From 76a3d7310230556cb35fe7061b74c3f57cbcabdb Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 3 Jul 2023 03:59:00 +1000 Subject: [PATCH 57/99] add WIIUSGN:000 --- server/signserver/session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/signserver/session.go b/server/signserver/session.go index 2a83afc6a..d836b8c10 100644 --- a/server/signserver/session.go +++ b/server/signserver/session.go @@ -60,7 +60,7 @@ func (s *Session) handlePacket(pkt []byte) error { case "VITASGN:100": s.client = VITA s.handlePSSGN(bf) - case "WIIUSGN:100": + case "WIIUSGN:100", "WIIUSGN:000": s.client = WIIU s.handleWIIUSGN(bf) case "DELETE:100": From ec1c9631c87df900613fd5cce5897d1677227b8f Mon Sep 17 00:00:00 2001 From: straticspaff Date: Mon, 3 Jul 2023 21:25:46 +0100 Subject: [PATCH 58/99] clean: added config to readme --- README.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 669f37573..818236cb3 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,11 @@ If you want to modify or compile Erupe yourself, please read on. - [Go](https://go.dev/dl/) - [PostgreSQL](https://www.postgresql.org/download/) +# Comptaible Clients +- ZZ +- Z2 +- Z1 + ### Installation 1. Bring up a fresh database by using the [backup file attached with the latest release](https://github.com/ZeruLight/Erupe/releases/latest/download/SCHEMA.sql). @@ -18,12 +23,120 @@ If you want to modify or compile Erupe yourself, please read on. 3. Edit [config.json](./config.json) such that the database password matches your PostgreSQL setup. 4. Run `go build` or `go run .` to compile Erupe. -### Note - -- You will need to acquire and install the client files and quest binaries separately. - ## Resources - [Quest and Scenario Binary Files](https://files.catbox.moe/xf0l7w.7z) - [PewPewDojo Discord](https://discord.gg/CFnzbhQ) - [Community FAQ Pastebin](https://pastebin.com/QqAwZSTC) + + +## Configuration +This portion of the documetation goes over the `config.json` file. + +### General Configuraiton + +| Variable | Description | Default | Options | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------- | +| Host | the ip the server is running from | 127.0.0.1 | | +| BinPath | The bin path folder is where you place files needed for various parts of the game such as scenario and quest files. | bin | | +| Language | This is the language the server will run in. The two options are english `en` and japanese `ja` if you wish to contribute other languages talk to a maintainer. | en | en/jp | +| DisableSoftCrash | | false | | +| HideLoginNotice | This hides the notices that appear on login from `LoginNotices` | true | | +| LoginNotices | This is where you place notices for users. You can have multiple notices | | | +| PatchServerManifest | | | | +| PatchServerFile | | | | +| ScreenshotAPIURL | This is the url you want user sreenshots to go to. | | | +| DeleteOnSaveCorruption | This option deletes a users save if they corrupt it from the database. Can be used as punishment for cheaters | false | | +| ClientMode | This tells the server what client it should run for | ZZ | Check compatible versions above | +| DevMode | This enables DevModeOptions to be configured | true | | + +### `DevModeOptions` Configuraiton + +| Variable | Description | Default | Options | +| -------------------- | -------------------------------------------------------------------------------------------------- | -------- | ----------------------- | +| AutoCreateAccount | This allows users that dont exist to auto create there account from initial login | true | | +| CleanDB | This cleans the databse down | false | | +| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break server HR requirements | false | | +| LogInboundMessages | This will allow inbound messages to be logged in the stdout terminal you run the applicaiton from | false | | +| LogOutboundMessages | This will allow outbound messages to be logged in the stdout terminal you run the applicaiton from | false | | +| MaxHexdumpLength | This is the amount of hex that will be dumped to stdout along side a message | 0 | | +| DivaEvent | This sets the Dive event stage in game | 2 | 0/1/2/3/-1 | +| FestaEvent | This sets the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | +| TournamentEvent | This sets the Hunter Tournement event stage in game | 2 | 0/1/2/3/-1 | +| MezFesEvent | Enables whether the MezFes event/world is active | true | | +| MezFesAlt | Switches the multiplayer mesfes event | false | | +| DisableTokenCheck | This disables the random token that is generated at login from being checked | false | | +| QuestDebugTools | Enable various quest debug logs | false | | +| EarthStatusOverride | Enables events pallone fest,tower and conquest | 0 | 21=Tower,11=PalloneFest | | +| EarthIDOverride | A random event ID | 0 | | +| EarthMonsterOverride | ? | 0 | | +| SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | +| SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | + +### `GameplayOptions` Configuraiton + +| Variable | Description | Default | Options | +| -------------------- | --------------------------------------------------------------------------- | ------- | ------- | +| FeaturedWeapons | Number of Active Feature weapons to generate daily | 0 | | +| MaximumNP | Maximum number of NP held by a player | 100000 | | +| MaximumRP | Maximum number of RP held by a player | 100000 | | +| DisableLoginBoost | Disables the Login Boost system | false | | +| DisableBoostTime | Disables the daily NetCafe Boost Time | false | | +| BoostTimeDuration | The number of minutes NetCafe Boost Time lasts for | 120 | +| GuildMealDuration | The number of minutes a Guild Meal can be activated for after cooking | | | +| BonusQuestAllowance | Number of Bonus Point Quests to allow daily | | | +| DailyQuestAllowance | Number of Daily Quests to allow daily | | | +| MezfesSoloTickets | Number of solo tickets given weekly | | | +| MezfesGroupTickets | Number of group tickets given weekly | | | +| GUrgentRate | Adjusts the rate of G Urgent quests spawning | | | +| GCPMultiplier | Adjusts the multiplier of GCP rewarded for quest completion | | | +| GRPMultiplier | Adjusts the multiplier of G Rank Points rewarded for quest completion | | | +| GSRPMultiplier | Adjusts the multiplier of G Skill Rank Points rewarded for quest completion | | | +| GZennyMultiplier | Adjusts the multiplier of G Zenny rewarded for quest completion | | | +| MaterialMultiplier | Adjusts the multiplier of Monster Materials rewarded for quest completion | | | +| ExtraCarves | Grant n extra chances to carve ALL carcasses | | | +| DisableHunterNavi | Disables the Hunter Navi | | | +| EnableHiganjimaEvent | Enables the Higanjima event in the Rasta Bar | | | +| EnableNierEvent | Enables the Nier event in the Rasta Bar | | | +| DisableRoad | Disables the Hunting Road | | | + +### Discord +There is limited discord capability in erupe. That allows you to replay messages from your server into a channel. + +### Commands +There are a series of commands that can be turned on and off. Most of them are really for admins or debugging purposes. + +| Name | command | Description | Options | +| -------- | -------------- | ------------------------------------------------------- | ------------------- | +| Rights | !rights | Changes rights interger to specifc interger | | +| Teleport | !tele | Teleports user to specific x,y,z | | +| Reload | !reload | Flush all objects and users and reload stage you are on | | +| KeyQuest | !kqf | | | +| Course | !course OPTION | Changes the players course | HL,EX,Premium,Boost | +| PSN | !psn USERNAME | Links Erupe account to PSN | | + +### Ravi Sub Commands +| Name | command | Description | Options | +| -------- | -------------------------------- | ----------------------------- | ------- | +| Raviente | !ravi start | Starts Ravi Event | | +| Raviente | !ravi cm / !ravi checkmultiplier | Checks ravi health multiplier | | +| Raviente | !ravi ss | send sedation | | +| Raviente | !ravi sr | send resurrection | | +| Raviente | !ravi rs | request sedation | | + + +## World `Entries` config + +| Config Item | Description | Options | +| ----------- | --------------------------------------------- | -------------------------------------------------------------------- | +| Type | Server type. | 1=Normal, 2=Cities, 3=newbie, 4=Tavern 6=MezFes | +| Season | Server activity. | 0 = Green/Breeding, 1 = Orange/Warm, 2 = Blue/Cold | + +### `Recommend` +This sets the types of quest that can be ordered from a world. +* 0 = All quests +* 1 = Up to 2 star quests +* 2 = Up to 4 star quests +* 4 = All Quests in HR (Enables G Experience Tab) +* 5 = Only G rank quests +* 6 = mini games world there is no place to order quests \ No newline at end of file From 5af40ab46acc0ab6f5bf37bb6c445f341b5a3237 Mon Sep 17 00:00:00 2001 From: straticspaff Date: Mon, 3 Jul 2023 21:32:11 +0100 Subject: [PATCH 59/99] clean: added version info --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 818236cb3..be11c40ef 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,18 @@ If you want to modify or compile Erupe yourself, please read on. - [Go](https://go.dev/dl/) - [PostgreSQL](https://www.postgresql.org/download/) -# Comptaible Clients +# Comptaible Clients +## Platforms +- PC +- PS3 +- PSVita +- Wii U +## Versions - ZZ - Z2 - Z1 + ### Installation 1. Bring up a fresh database by using the [backup file attached with the latest release](https://github.com/ZeruLight/Erupe/releases/latest/download/SCHEMA.sql). From 60e86c74fe4f5a815c7fdda555b126aed4b7904d Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 00:34:11 +1000 Subject: [PATCH 60/99] mitigate LoadDecoMyset crashing on older versions --- server/channelserver/handlers_house.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/channelserver/handlers_house.go b/server/channelserver/handlers_house.go index ab150f180..52cdb4fa9 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" @@ -249,6 +250,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} } doAckBufSucceed(s, pkt.AckHandle, data) From ab83e64f8468d5ee51b557565a0f878aabc40366 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 00:35:15 +1000 Subject: [PATCH 61/99] fix limited friends & clanmates amount --- server/signserver/dbutils.go | 8 +------- server/signserver/dsgn_resp.go | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/server/signserver/dbutils.go b/server/signserver/dbutils.go index 3d7e34318..2720e07cd 100644 --- a/server/signserver/dbutils.go +++ b/server/signserver/dbutils.go @@ -131,9 +131,6 @@ func (s *Server) getFriendsForCharacters(chars []character) []members { } friends = append(friends, charFriends...) } - if len(friends) > 255 { // Uint8 - friends = friends[:255] - } return friends } @@ -153,15 +150,12 @@ func (s *Server) getGuildmatesForCharacters(chars []character) []members { if err != nil { continue } - for i, _ := range charGuildmates { + for i := range charGuildmates { charGuildmates[i].CID = char.ID } guildmates = append(guildmates, charGuildmates...) } } - if len(guildmates) > 255 { // Uint8 - guildmates = guildmates[:255] - } return guildmates } diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 65874b683..21a9aa3c2 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -89,7 +89,12 @@ func (s *Session) makeSignResponse(uid int) []byte { if len(friends) == 0 { bf.WriteUint8(0) } else { - bf.WriteUint8(uint8(len(friends))) + if len(friends) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(friends))) + } else { + bf.WriteUint8(uint8(len(friends))) + } for _, friend := range friends { bf.WriteUint32(friend.CID) bf.WriteUint32(friend.ID) @@ -101,7 +106,12 @@ func (s *Session) makeSignResponse(uid int) []byte { if len(guildmates) == 0 { bf.WriteUint8(0) } else { - bf.WriteUint8(uint8(len(guildmates))) + if len(guildmates) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(guildmates))) + } else { + bf.WriteUint8(uint8(len(guildmates))) + } for _, guildmate := range guildmates { bf.WriteUint32(guildmate.CID) bf.WriteUint32(guildmate.ID) From 310e049a234282e08ad28f985628189d6763a145 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 00:35:41 +1000 Subject: [PATCH 62/99] correctly parse UpdateBeatLevel --- .../mhfpacket/msg_mhf_update_beat_level.go | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/network/mhfpacket/msg_mhf_update_beat_level.go b/network/mhfpacket/msg_mhf_update_beat_level.go index 84f41ae61..e00d50c93 100644 --- a/network/mhfpacket/msg_mhf_update_beat_level.go +++ b/network/mhfpacket/msg_mhf_update_beat_level.go @@ -1,45 +1,42 @@ package mhfpacket import ( - "errors" + "errors" - "erupe-ce/common/byteframe" - "erupe-ce/network" - "erupe-ce/network/clientctx" + "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfUpdateBeatLevel represents the MSG_MHF_UPDATE_BEAT_LEVEL type MsgMhfUpdateBeatLevel struct { - AckHandle uint32 - Unk1 uint32 - Unk2 uint32 - MonsterData []byte - Unk3 uint8 - Unk4 uint32 - Unk5 uint16 - Unk6 uint8 - + AckHandle uint32 + Unk1 uint32 + Unk2 uint32 + Data1 []int32 + Data2 []int32 } // Opcode returns the ID associated with this packet type. func (m *MsgMhfUpdateBeatLevel) Opcode() network.PacketID { - return network.MSG_MHF_UPDATE_BEAT_LEVEL + return network.MSG_MHF_UPDATE_BEAT_LEVEL } // Parse parses the packet from binary func (m *MsgMhfUpdateBeatLevel) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - m.AckHandle = bf.ReadUint32() - m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadUint32() - m.MonsterData = bf.ReadBytes(uint(120)) - m.Unk3 = bf.ReadUint8() - m.Unk4 = bf.ReadUint32() - m.Unk5 = bf.ReadUint16() - m.Unk6 = bf.ReadUint8() - return nil + m.AckHandle = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + for i := 0; i < 16; i++ { + m.Data1 = append(m.Data1, bf.ReadInt32()) + } + for i := 0; i < 16; i++ { + m.Data2 = append(m.Data2, bf.ReadInt32()) + } + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfUpdateBeatLevel) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + return errors.New("NOT IMPLEMENTED") } From cf1da979ec5ba231d505e941803002eabca85a15 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 00:55:26 +1000 Subject: [PATCH 63/99] readme review pass 1 --- README.md | 132 +++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index be11c40ef..90f94d3ac 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,17 @@ If you want to modify or compile Erupe yourself, please read on. - [Go](https://go.dev/dl/) - [PostgreSQL](https://www.postgresql.org/download/) -# Comptaible Clients -## Platforms +## Client Compatiblity +### Platforms - PC - PS3 - PSVita - Wii U -## Versions -- ZZ +### Versions +- ZZ (Z3) - Z2 - Z1 - ### Installation 1. Bring up a fresh database by using the [backup file attached with the latest release](https://github.com/ZeruLight/Erupe/releases/latest/download/SCHEMA.sql). @@ -34,87 +33,86 @@ If you want to modify or compile Erupe yourself, please read on. - [Quest and Scenario Binary Files](https://files.catbox.moe/xf0l7w.7z) - [PewPewDojo Discord](https://discord.gg/CFnzbhQ) -- [Community FAQ Pastebin](https://pastebin.com/QqAwZSTC) - ## Configuration -This portion of the documetation goes over the `config.json` file. +This portion of the documentation goes over the `config.json` file. -### General Configuraiton +### General Configuration -| Variable | Description | Default | Options | -| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------- | -| Host | the ip the server is running from | 127.0.0.1 | | -| BinPath | The bin path folder is where you place files needed for various parts of the game such as scenario and quest files. | bin | | -| Language | This is the language the server will run in. The two options are english `en` and japanese `ja` if you wish to contribute other languages talk to a maintainer. | en | en/jp | -| DisableSoftCrash | | false | | -| HideLoginNotice | This hides the notices that appear on login from `LoginNotices` | true | | -| LoginNotices | This is where you place notices for users. You can have multiple notices | | | -| PatchServerManifest | | | | -| PatchServerFile | | | | -| ScreenshotAPIURL | This is the url you want user sreenshots to go to. | | | -| DeleteOnSaveCorruption | This option deletes a users save if they corrupt it from the database. Can be used as punishment for cheaters | false | | -| ClientMode | This tells the server what client it should run for | ZZ | Check compatible versions above | -| DevMode | This enables DevModeOptions to be configured | true | | +| Variable | Description | Default | Options | +|------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|---------------------------------| +| Host | The IP or host address the server is running from | 127.0.0.1 | | +| BinPath | The bin path folder is where you place files needed for various parts of the game such as scenario and quest files | bin | | +| Language | This is the language the server will run in. Only English `en` and Japanese `ja` are available, if you wish to contribute to tranlation, get in touch | en | en/jp | +| DisableSoftCrash | | false | | +| HideLoginNotice | This hides the notices that appear on login from `LoginNotices` | true | | +| LoginNotices | This is where you place notices for users, you can have multiple notices | | | +| PatchServerManifest | | | | +| PatchServerFile | | | | +| ScreenshotAPIURL | This is the URL you want user sreenshots to go to | | | +| DeleteOnSaveCorruption | This option deletes a users save if they corrupt it from the database, can be used as punishment for cheaters | false | | +| ClientMode | This tells the server what client it should run for | ZZ | Check compatible versions above | +| DevMode | This enables DevModeOptions to be configured | true | | ### `DevModeOptions` Configuraiton | Variable | Description | Default | Options | -| -------------------- | -------------------------------------------------------------------------------------------------- | -------- | ----------------------- | -| AutoCreateAccount | This allows users that dont exist to auto create there account from initial login | true | | -| CleanDB | This cleans the databse down | false | | -| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break server HR requirements | false | | +|----------------------|----------------------------------------------------------------------------------------------------|----------|-------------------------| +| AutoCreateAccount | This allows users that don't exist to auto create there account from initial login | true | | +| CleanDB | This cleans the database down | false | | +| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break World HR requirements | false | | | LogInboundMessages | This will allow inbound messages to be logged in the stdout terminal you run the applicaiton from | false | | | LogOutboundMessages | This will allow outbound messages to be logged in the stdout terminal you run the applicaiton from | false | | -| MaxHexdumpLength | This is the amount of hex that will be dumped to stdout along side a message | 0 | | -| DivaEvent | This sets the Dive event stage in game | 2 | 0/1/2/3/-1 | -| FestaEvent | This sets the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | -| TournamentEvent | This sets the Hunter Tournement event stage in game | 2 | 0/1/2/3/-1 | -| MezFesEvent | Enables whether the MezFes event/world is active | true | | -| MezFesAlt | Switches the multiplayer mesfes event | false | | -| DisableTokenCheck | This disables the random token that is generated at login from being checked | false | | +| MaxHexdumpLength | This is the maximum amount of hex that will be dumped to stdout along side a message | 0 | | +| DivaEvent | This overrides the Diva event stage in game | 2 | 0/1/2/3/-1 | +| FestaEvent | This overrides the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | +| TournamentEvent | This overrides the Hunter Tournament event stage in game | 2 | 0/1/2/3/-1 | +| MezFesEvent | Enables whether the MezFes event & World are active | true | | +| MezFesAlt | Switches the multiplayer MezFes event | false | | +| DisableTokenCheck | This disables the random token that is generated at login from being checked, very insecure | false | | | QuestDebugTools | Enable various quest debug logs | false | | -| EarthStatusOverride | Enables events pallone fest,tower and conquest | 0 | 21=Tower,11=PalloneFest | | +| EarthStatusOverride | Enables Pallone Fest, Tower and Conquest War events | 0 | 21=Tower,11=PalloneFest | | | EarthIDOverride | A random event ID | 0 | | -| EarthMonsterOverride | ? | 0 | | +| EarthMonsterOverride | Sets the ID of the monster targeted in the Conquest War | 0 | | | SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | | SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | ### `GameplayOptions` Configuraiton | Variable | Description | Default | Options | -| -------------------- | --------------------------------------------------------------------------- | ------- | ------- | +|----------------------|-----------------------------------------------------------------------------|---------|---------| | FeaturedWeapons | Number of Active Feature weapons to generate daily | 0 | | | MaximumNP | Maximum number of NP held by a player | 100000 | | | MaximumRP | Maximum number of RP held by a player | 100000 | | | DisableLoginBoost | Disables the Login Boost system | false | | | DisableBoostTime | Disables the daily NetCafe Boost Time | false | | -| BoostTimeDuration | The number of minutes NetCafe Boost Time lasts for | 120 | -| GuildMealDuration | The number of minutes a Guild Meal can be activated for after cooking | | | -| BonusQuestAllowance | Number of Bonus Point Quests to allow daily | | | -| DailyQuestAllowance | Number of Daily Quests to allow daily | | | -| MezfesSoloTickets | Number of solo tickets given weekly | | | -| MezfesGroupTickets | Number of group tickets given weekly | | | -| GUrgentRate | Adjusts the rate of G Urgent quests spawning | | | -| GCPMultiplier | Adjusts the multiplier of GCP rewarded for quest completion | | | -| GRPMultiplier | Adjusts the multiplier of G Rank Points rewarded for quest completion | | | -| GSRPMultiplier | Adjusts the multiplier of G Skill Rank Points rewarded for quest completion | | | -| GZennyMultiplier | Adjusts the multiplier of G Zenny rewarded for quest completion | | | -| MaterialMultiplier | Adjusts the multiplier of Monster Materials rewarded for quest completion | | | -| ExtraCarves | Grant n extra chances to carve ALL carcasses | | | -| DisableHunterNavi | Disables the Hunter Navi | | | -| EnableHiganjimaEvent | Enables the Higanjima event in the Rasta Bar | | | -| EnableNierEvent | Enables the Nier event in the Rasta Bar | | | -| DisableRoad | Disables the Hunting Road | | | +| BoostTimeDuration | The number of minutes NetCafe Boost Time lasts for | 120 | | +| GuildMealDuration | The number of minutes a Guild Meal can be activated for after cooking | 60 | | +| BonusQuestAllowance | Number of Bonus Point Quests to allow daily | 3 | | +| DailyQuestAllowance | Number of Daily Quests to allow daily | 1 | | +| MezfesSoloTickets | Number of solo tickets given weekly | 10 | | +| MezfesGroupTickets | Number of group tickets given weekly | 4 | | +| GUrgentRate | Adjusts the rate of G Urgent quests spawning | 10 | | +| GCPMultiplier | Adjusts the multiplier of GCP rewarded for quest completion | 1.00 | | +| GRPMultiplier | Adjusts the multiplier of G Rank Points rewarded for quest completion | 1.00 | | +| GSRPMultiplier | Adjusts the multiplier of G Skill Rank Points rewarded for quest completion | 1.00 | | +| GZennyMultiplier | Adjusts the multiplier of G Zenny rewarded for quest completion | 1.00 | | +| MaterialMultiplier | Adjusts the multiplier of Monster Materials rewarded for quest completion | 1.00 | | +| ExtraCarves | Grant n extra chances to carve ALL carcasses | 0 | | +| DisableHunterNavi | Disables the Hunter Navi | false | | +| EnableHiganjimaEvent | Enables the Higanjima event in the Rasta Bar | false | | +| EnableNierEvent | Enables the Nier event in the Rasta Bar | false | | +| DisableRoad | Disables the Hunting Road | false | | ### Discord -There is limited discord capability in erupe. That allows you to replay messages from your server into a channel. +There is limited Discord capability in Erupe. The feature allows you to replay messages from your server into a channel. +This may be either be removed or revamped in a future version. ### Commands -There are a series of commands that can be turned on and off. Most of them are really for admins or debugging purposes. +There are several chat commands that can be turned on and off. Most of them are really for admins or debugging purposes. | Name | command | Description | Options | -| -------- | -------------- | ------------------------------------------------------- | ------------------- | +|----------|----------------|---------------------------------------------------------|---------------------| | Rights | !rights | Changes rights interger to specifc interger | | | Teleport | !tele | Teleports user to specific x,y,z | | | Reload | !reload | Flush all objects and users and reload stage you are on | | @@ -124,20 +122,20 @@ There are a series of commands that can be turned on and off. Most of them are r ### Ravi Sub Commands | Name | command | Description | Options | -| -------- | -------------------------------- | ----------------------------- | ------- | +|----------|----------------------------------|-------------------------------|---------| | Raviente | !ravi start | Starts Ravi Event | | -| Raviente | !ravi cm / !ravi checkmultiplier | Checks ravi health multiplier | | -| Raviente | !ravi ss | send sedation | | -| Raviente | !ravi sr | send resurrection | | -| Raviente | !ravi rs | request sedation | | +| Raviente | !ravi cm / !ravi checkmultiplier | Checks Ravi health multiplier | | +| Raviente | !ravi ss | Send sedation | | +| Raviente | !ravi sr | Send resurrection | | +| Raviente | !ravi rs | Request sedation | | ## World `Entries` config -| Config Item | Description | Options | -| ----------- | --------------------------------------------- | -------------------------------------------------------------------- | -| Type | Server type. | 1=Normal, 2=Cities, 3=newbie, 4=Tavern 6=MezFes | -| Season | Server activity. | 0 = Green/Breeding, 1 = Orange/Warm, 2 = Blue/Cold | +| Config Item | Description | Options | +|-------------|------------------|------------------------------------------------------------| +| Type | Server type. | 1=Normal, 2=Cities, 3=Newbie, 4=Tavern, 5=Return, 6=MezFes | +| Season | Server activity. | 0=Green/Breeding, 1=Orange/Warm, 2=Blue/Cold | ### `Recommend` This sets the types of quest that can be ordered from a world. @@ -146,4 +144,4 @@ This sets the types of quest that can be ordered from a world. * 2 = Up to 4 star quests * 4 = All Quests in HR (Enables G Experience Tab) * 5 = Only G rank quests -* 6 = mini games world there is no place to order quests \ No newline at end of file +* 6 = Mini games world there is no place to order quests \ No newline at end of file From 88970a3ec3477611ef44c3e15e016c69a2cc89dc Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 22:14:18 +1000 Subject: [PATCH 64/99] readme review pass 2 --- README.md | 84 +++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 90f94d3ac..60e50503e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ -# Erupe Community Edition +# Erupe + +## Client Compatiblity +### Platforms +- PC +- PlayStation 3 +- PlayStation Vita +- Wii U (Up to Z2) +### Versions +- ZZ +- Z2 +- Z1 ## Setup @@ -6,23 +17,12 @@ If you are only looking to install Erupe, please use [a pre-compiled binary](htt If you want to modify or compile Erupe yourself, please read on. -### Requirements +## Requirements - [Go](https://go.dev/dl/) - [PostgreSQL](https://www.postgresql.org/download/) -## Client Compatiblity -### Platforms -- PC -- PS3 -- PSVita -- Wii U -### Versions -- ZZ (Z3) -- Z2 -- Z1 - -### Installation +## Installation 1. Bring up a fresh database by using the [backup file attached with the latest release](https://github.com/ZeruLight/Erupe/releases/latest/download/SCHEMA.sql). 2. Run each script under [patch-schema](./patch-schema) as they introduce newer schema. @@ -50,32 +50,32 @@ This portion of the documentation goes over the `config.json` file. | PatchServerManifest | | | | | PatchServerFile | | | | | ScreenshotAPIURL | This is the URL you want user sreenshots to go to | | | -| DeleteOnSaveCorruption | This option deletes a users save if they corrupt it from the database, can be used as punishment for cheaters | false | | +| DeleteOnSaveCorruption | This option deletes a users save from the database if they corrupt it, can be used as punishment for cheaters | false | | | ClientMode | This tells the server what client it should run for | ZZ | Check compatible versions above | | DevMode | This enables DevModeOptions to be configured | true | | ### `DevModeOptions` Configuraiton -| Variable | Description | Default | Options | -|----------------------|----------------------------------------------------------------------------------------------------|----------|-------------------------| -| AutoCreateAccount | This allows users that don't exist to auto create there account from initial login | true | | -| CleanDB | This cleans the database down | false | | -| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break World HR requirements | false | | -| LogInboundMessages | This will allow inbound messages to be logged in the stdout terminal you run the applicaiton from | false | | -| LogOutboundMessages | This will allow outbound messages to be logged in the stdout terminal you run the applicaiton from | false | | -| MaxHexdumpLength | This is the maximum amount of hex that will be dumped to stdout along side a message | 0 | | -| DivaEvent | This overrides the Diva event stage in game | 2 | 0/1/2/3/-1 | -| FestaEvent | This overrides the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | -| TournamentEvent | This overrides the Hunter Tournament event stage in game | 2 | 0/1/2/3/-1 | -| MezFesEvent | Enables whether the MezFes event & World are active | true | | -| MezFesAlt | Switches the multiplayer MezFes event | false | | -| DisableTokenCheck | This disables the random token that is generated at login from being checked, very insecure | false | | -| QuestDebugTools | Enable various quest debug logs | false | | -| EarthStatusOverride | Enables Pallone Fest, Tower and Conquest War events | 0 | 21=Tower,11=PalloneFest | | -| EarthIDOverride | A random event ID | 0 | | -| EarthMonsterOverride | Sets the ID of the monster targeted in the Conquest War | 0 | | -| SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | -| SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | +| Variable | Description | Default | Options | +|----------------------|----------------------------------------------------------------------------------------------------|----------|----------------------------------| +| AutoCreateAccount | This allows users that don't exist to auto create there account from initial login | true | | +| CleanDB | This cleans the database down | false | | +| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break World HR requirements | false | | +| LogInboundMessages | This will allow inbound messages to be logged in the stdout terminal you run the applicaiton from | false | | +| LogOutboundMessages | This will allow outbound messages to be logged in the stdout terminal you run the applicaiton from | false | | +| MaxHexdumpLength | This is the maximum amount of hex that will be dumped to stdout along side a message | 0 | | +| DivaEvent | This overrides the Diva event stage in game | 2 | 0/1/2/3/-1 | +| FestaEvent | This overrides the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | +| TournamentEvent | This overrides the Hunter Tournament event stage in game | 2 | 0/1/2/3/-1 | +| MezFesEvent | Enables whether the MezFes event & World are active | true | | +| MezFesAlt | Switches the multiplayer MezFes event | false | | +| DisableTokenCheck | This disables the random token that is generated at login from being checked, very insecure | false | | +| QuestDebugTools | Enable various quest debug logs | false | | +| EarthStatusOverride | Enables Pallone Fest, Tower and Conquest War events | 0 | 2=Conquest, 11=Pallone, 21=Tower | +| EarthIDOverride | A random event ID | 0 | | +| EarthMonsterOverride | Sets the ID of the monster targeted in the Conquest War | 0 | | +| SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | +| SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | ### `GameplayOptions` Configuraiton @@ -121,13 +121,13 @@ There are several chat commands that can be turned on and off. Most of them are | PSN | !psn USERNAME | Links Erupe account to PSN | | ### Ravi Sub Commands -| Name | command | Description | Options | -|----------|----------------------------------|-------------------------------|---------| -| Raviente | !ravi start | Starts Ravi Event | | -| Raviente | !ravi cm / !ravi checkmultiplier | Checks Ravi health multiplier | | -| Raviente | !ravi ss | Send sedation | | -| Raviente | !ravi sr | Send resurrection | | -| Raviente | !ravi rs | Request sedation | | +| Name | command | Description | +|----------|----------------------------------|-------------------------------| +| Raviente | !ravi start | Starts Ravi Event | +| Raviente | !ravi cm / !ravi checkmultiplier | Checks Ravi health multiplier | +| Raviente | !ravi ss | Send sedation | +| Raviente | !ravi sr | Send resurrection | +| Raviente | !ravi rs | Request sedation | ## World `Entries` config From a23e1b62a2feaadc9ed639f64cb50efd96fa3eef Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 22:16:58 +1000 Subject: [PATCH 65/99] GetGuildInfo further decoding --- server/channelserver/handlers_guild.go | 84 +++++++++++++++++--------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index c05b15f68..fbb1f0ea0 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -953,28 +953,38 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(FestivalColourCodes[guild.FestivalColour]) bf.WriteUint32(guild.RankRP) bf.WriteBytes(guildLeaderName) - bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00}) // Unk - bf.WriteBool(false) // isReturnGuild - bf.WriteBool(false) // earnedSpecialHall - bf.WriteBytes([]byte{0x02, 0x02}) // Unk - bf.WriteUint32(guild.EventRP) + bf.WriteUint32(0) // Unk + bf.WriteBool(false) // isReturnGuild + bf.WriteBool(false) // earnedSpecialHall + bf.WriteUint8(2) + bf.WriteUint8(2) + bf.WriteUint32(guild.EventRP) // Skipped if last byte is <2? ps.Uint8(bf, guild.PugiName1, true) ps.Uint8(bf, guild.PugiName2, true) ps.Uint8(bf, guild.PugiName3, true) bf.WriteUint8(guild.PugiOutfit1) bf.WriteUint8(guild.PugiOutfit2) bf.WriteUint8(guild.PugiOutfit3) + // TODO: Skip if Diva Poogies don't exist yet bf.WriteUint8(guild.PugiOutfit1) bf.WriteUint8(guild.PugiOutfit2) bf.WriteUint8(guild.PugiOutfit3) bf.WriteUint32(guild.PugiOutfits) - // Unk flags - bf.WriteUint8(0x3C) // also seen as 0x32 on JP and 0x64 on TW + if guild.Rank >= 3 { + bf.WriteUint8(40) + } else if guild.Rank >= 7 { + bf.WriteUint8(50) + } else if guild.Rank >= 10 { + bf.WriteUint8(60) + } else { + bf.WriteUint8(30) + } - bf.WriteBytes([]byte{ - 0x00, 0x00, 0xD6, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }) + bf.WriteUint32(55000) + bf.WriteUint32(0) + bf.WriteUint16(0) + bf.WriteUint16(0) if guild.AllianceID > 0 { alliance, err := GetAllianceData(s, guild.AllianceID) @@ -984,7 +994,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(alliance.ID) bf.WriteUint32(uint32(alliance.CreatedAt.Unix())) bf.WriteUint16(alliance.TotalMembers) - bf.WriteUint16(0) // Unk0 + bf.WriteUint8(0) + bf.WriteUint8(0) ps.Uint16(bf, alliance.Name, true) if alliance.SubGuild1ID > 0 { if alliance.SubGuild2ID > 0 { @@ -1044,29 +1055,46 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(uint16(len(applicants))) for _, applicant := range applicants { bf.WriteUint32(applicant.CharID) - bf.WriteUint16(0) - bf.WriteUint16(0) + bf.WriteUint32(0) bf.WriteUint16(applicant.HRP) bf.WriteUint16(applicant.GR) ps.Uint8(bf, applicant.Name, true) } } - bf.WriteUint16(0x0000) // lenAllianceApplications + type UnkGuildInfo struct { + Unk0 uint8 + Unk1 uint8 + Unk2 uint8 + } + unkGuildInfo := []UnkGuildInfo{} + bf.WriteUint8(uint8(len(unkGuildInfo))) + for _, info := range unkGuildInfo { + bf.WriteUint8(info.Unk0) + bf.WriteUint8(info.Unk1) + bf.WriteUint8(info.Unk2) + } - /* - alliance application format - uint16 numapplicants (above) - - uint32 guild id - uint32 guild leader id (for mail) - uint32 unk (always null in pcap) - uint16 member count - uint16 len guild name - string nullterm guild name - uint16 len guild leader name - string nullterm guild leader name - */ + type AllianceInvite struct { + GuildID uint32 + LeaderID uint32 + Unk0 uint16 + Unk1 uint16 + Members uint16 + GuildName string + LeaderName string + } + allianceInvites := []AllianceInvite{} + bf.WriteUint8(uint8(len(allianceInvites))) + for _, invite := range allianceInvites { + bf.WriteUint32(invite.GuildID) + bf.WriteUint32(invite.LeaderID) + bf.WriteUint16(invite.Unk0) + bf.WriteUint16(invite.Unk1) + bf.WriteUint16(invite.Members) + ps.Uint16(bf, invite.GuildName, true) + ps.Uint16(bf, invite.LeaderName, true) + } if guild.Icon != nil { bf.WriteUint8(uint8(len(guild.Icon.Parts))) @@ -1084,7 +1112,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(p.PosY) } } else { - bf.WriteUint8(0x00) + bf.WriteUint8(0) } bf.WriteUint8(0) // Unk From 053343befb870fce8fef8219b2d8500d4937d93e Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 22:17:41 +1000 Subject: [PATCH 66/99] prevent Login Notices from overflowing --- server/signserver/dsgn_resp.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 21a9aa3c2..0f5f6f129 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -123,7 +123,9 @@ func (s *Session) makeSignResponse(uid int) []byte { bf.WriteBool(false) } else { bf.WriteBool(true) - ps.Uint32(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], ""), true) + bf.WriteUint8(0) + bf.WriteUint8(0) + ps.Uint16(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], ""), true) } bf.WriteUint32(s.server.getLastCID(uid)) From 436d92cd7eaed2ac267814a8c35e09707f85bd3f Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 22:18:41 +1000 Subject: [PATCH 67/99] fix MezFes Tickets not resetting & cleanup --- server/signserver/dsgn_resp.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 0f5f6f129..948a5a011 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -145,12 +145,13 @@ func (s *Session) makeSignResponse(uid int) []byte { bf.WriteUint16(0x4E20) ps.Uint16(bf, "", false) // unk ipv4 bf.WriteUint32(uint32(s.server.getReturnExpiry(uid).Unix())) - bf.WriteUint32(0x00000000) - bf.WriteUint32(0x0A5197DF) // unk id + bf.WriteUint32(0) mezfes := s.server.erupeConfig.DevModeOptions.MezFesEvent alt := s.server.erupeConfig.DevModeOptions.MezFesAlt if mezfes { + // We can just use the start timestamp as the event ID + bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) // Start time bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) // End time @@ -158,22 +159,23 @@ func (s *Session) makeSignResponse(uid int) []byte { bf.WriteUint8(2) // Unk bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesSoloTickets) bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesGroupTickets) - bf.WriteUint8(8) // Stalls open - bf.WriteUint8(0xA) // Unk - bf.WriteUint8(0x3) // Pachinko - bf.WriteUint8(0x6) // Nyanrendo - bf.WriteUint8(0x9) // Point stall + bf.WriteUint8(8) // Stalls open + bf.WriteUint8(10) // Stall Map + bf.WriteUint8(3) // Pachinko + bf.WriteUint8(6) // Nyanrendo + bf.WriteUint8(9) // Point stall if alt { - bf.WriteUint8(0x2) // Tokotoko + bf.WriteUint8(2) // Tokotoko Partnya } else { - bf.WriteUint8(0x4) // Volpakkun + bf.WriteUint8(4) // Volpakkun Together } - bf.WriteUint8(0x8) // Battle cats - bf.WriteUint8(0x5) // Gook - bf.WriteUint8(0x7) // Honey + bf.WriteUint8(8) // Dokkan Battle Cats + bf.WriteUint8(5) // Goocoo Scoop + bf.WriteUint8(7) // Honey Panic } else { bf.WriteUint32(0) bf.WriteUint32(0) + bf.WriteUint32(0) } return bf.Data() } From db6b7795c532aeb6411c7207665f802ae127e8b9 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 8 Jul 2023 22:41:57 +1000 Subject: [PATCH 68/99] clean up OperateGuild --- network/mhfpacket/msg_mhf_operate_guild.go | 54 +++++++-------- server/channelserver/handlers_guild.go | 77 ++++++++++------------ 2 files changed, 60 insertions(+), 71 deletions(-) diff --git a/network/mhfpacket/msg_mhf_operate_guild.go b/network/mhfpacket/msg_mhf_operate_guild.go index a79719290..96803e89c 100644 --- a/network/mhfpacket/msg_mhf_operate_guild.go +++ b/network/mhfpacket/msg_mhf_operate_guild.go @@ -11,33 +11,33 @@ import ( type OperateGuildAction uint8 const ( - OPERATE_GUILD_DISBAND = 0x01 - OPERATE_GUILD_APPLY = 0x02 - OPERATE_GUILD_LEAVE = 0x03 - OPERATE_GUILD_RESIGN = 0x04 - OPERATE_GUILD_SET_APPLICATION_DENY = 0x05 - OPERATE_GUILD_SET_APPLICATION_ALLOW = 0x06 - OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE = 0x07 - OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE = 0x08 - OPERATE_GUILD_UPDATE_COMMENT = 0x09 - OPERATE_GUILD_DONATE_RANK = 0x0a - OPERATE_GUILD_UPDATE_MOTTO = 0x0b - OPERATE_GUILD_RENAME_PUGI_1 = 0x0c - OPERATE_GUILD_RENAME_PUGI_2 = 0x0d - OPERATE_GUILD_RENAME_PUGI_3 = 0x0e - OPERATE_GUILD_CHANGE_PUGI_1 = 0x0f - OPERATE_GUILD_CHANGE_PUGI_2 = 0x10 - OPERATE_GUILD_CHANGE_PUGI_3 = 0x11 - OPERATE_GUILD_UNLOCK_OUTFIT = 0x12 - // 0x13 Unk - // 0x14 Unk - OPERATE_GUILD_DONATE_EVENT = 0x15 - OPERATE_GUILD_EVENT_EXCHANGE = 0x16 - // 0x17 Unk - // 0x18 Unk - OPERATE_GUILD_CHANGE_DIVA_PUGI_1 = 0x19 - OPERATE_GUILD_CHANGE_DIVA_PUGI_2 = 0x1a - OPERATE_GUILD_CHANGE_DIVA_PUGI_3 = 0x1b + OperateGuildDisband = iota + 1 + OperateGuildApply + OperateGuildLeave + OperateGuildResign + OperateGuildSetApplicationDeny + OperateGuildSetApplicationAllow + OperateGuildSetAvoidLeadershipTrue + OperateGuildSetAvoidLeadershipFalse + OperateGuildUpdateComment + OperateGuildDonateRank + OperateGuildUpdateMotto + OperateGuildRenamePugi1 + OperateGuildRenamePugi2 + OperateGuildRenamePugi3 + OperateGuildChangePugi1 + OperateGuildChangePugi2 + OperateGuildChangePugi3 + OperateGuildUnlockOutfit + OperateGuildDonateRoom + OperateGuildGraduateRookie + OperateGuildDonateEvent + OperateGuildEventExchange + OperateGuildUnknown // I don't think this op exists + OperateGuildGraduateReturn + OperateGuildChangeDivaPugi1 + OperateGuildChangeDivaPugi2 + OperateGuildChangeDivaPugi3 ) // MsgMhfOperateGuild represents the MSG_MHF_OPERATE_GUILD diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index fbb1f0ea0..85ac916be 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -616,13 +616,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateGuild) guild, err := GetGuildInfoByID(s, pkt.GuildID) - - if err != nil { - return - } - characterGuildInfo, err := GetCharacterGuildData(s, s.charID) - if err != nil { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return @@ -631,22 +625,19 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() switch pkt.Action { - case mhfpacket.OPERATE_GUILD_DISBAND: + case mhfpacket.OperateGuildDisband: + response := 1 if guild.LeaderCharID != s.charID { s.logger.Warn(fmt.Sprintf("character '%d' is attempting to manage guild '%d' without permission", s.charID, guild.ID)) - return + response = 0 + } else { + err = guild.Disband(s) + if err != nil { + response = 0 + } } - - err = guild.Disband(s) - response := 0x01 - - if err != nil { - // All successful acks return 0x01, assuming 0x00 is failure - response = 0x00 - } - bf.WriteUint32(uint32(response)) - case mhfpacket.OPERATE_GUILD_RESIGN: + case mhfpacket.OperateGuildResign: guildMembers, err := GetGuildMembers(s, guild.ID, false) if err == nil { sort.Slice(guildMembers[:], func(i, j int) bool { @@ -665,25 +656,22 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { } guild.Save(s) } - case mhfpacket.OPERATE_GUILD_APPLY: + case mhfpacket.OperateGuildApply: err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil) - if err == nil { bf.WriteUint32(guild.LeaderCharID) + } else { + bf.WriteUint32(0) } - case mhfpacket.OPERATE_GUILD_LEAVE: - var err error - + case mhfpacket.OperateGuildLeave: if characterGuildInfo.IsApplicant { err = guild.RejectApplication(s, s.charID) } else { err = guild.RemoveCharacter(s, s.charID) } - - response := 0x01 + response := 1 if err != nil { - // All successful acks return 0x01, assuming 0x00 is failure - response = 0x00 + response = 0 } else { mail := Mail{ RecipientID: s.charID, @@ -693,26 +681,25 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { } mail.Send(s, nil) } - bf.WriteUint32(uint32(response)) - case mhfpacket.OPERATE_GUILD_DONATE_RANK: + case mhfpacket.OperateGuildDonateRank: bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, false)) - case mhfpacket.OPERATE_GUILD_SET_APPLICATION_DENY: + case mhfpacket.OperateGuildSetApplicationDeny: s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID) - case mhfpacket.OPERATE_GUILD_SET_APPLICATION_ALLOW: + case mhfpacket.OperateGuildSetApplicationAllow: s.server.db.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID) - case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE: + case mhfpacket.OperateGuildSetAvoidLeadershipTrue: handleAvoidLeadershipUpdate(s, pkt, true) - case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE: + case mhfpacket.OperateGuildSetAvoidLeadershipFalse: handleAvoidLeadershipUpdate(s, pkt, false) - case mhfpacket.OPERATE_GUILD_UPDATE_COMMENT: + case mhfpacket.OperateGuildUpdateComment: if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } guild.Comment = stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()) guild.Save(s) - case mhfpacket.OPERATE_GUILD_UPDATE_MOTTO: + case mhfpacket.OperateGuildUpdateMotto: if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return @@ -721,27 +708,29 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { guild.SubMotto = pkt.Data1.ReadUint8() guild.MainMotto = pkt.Data1.ReadUint8() guild.Save(s) - case mhfpacket.OPERATE_GUILD_RENAME_PUGI_1: + case mhfpacket.OperateGuildRenamePugi1: handleRenamePugi(s, pkt.Data2, guild, 1) - case mhfpacket.OPERATE_GUILD_RENAME_PUGI_2: + case mhfpacket.OperateGuildRenamePugi2: handleRenamePugi(s, pkt.Data2, guild, 2) - case mhfpacket.OPERATE_GUILD_RENAME_PUGI_3: + case mhfpacket.OperateGuildRenamePugi3: handleRenamePugi(s, pkt.Data2, guild, 3) - case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_1: + case mhfpacket.OperateGuildChangePugi1: handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 1) - case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_2: + case mhfpacket.OperateGuildChangePugi2: handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 2) - case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_3: + case mhfpacket.OperateGuildChangePugi3: handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 3) - case mhfpacket.OPERATE_GUILD_UNLOCK_OUTFIT: + case mhfpacket.OperateGuildUnlockOutfit: // TODO: This doesn't implement blocking, if someone unlocked the same outfit at the same time s.server.db.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID) - case mhfpacket.OPERATE_GUILD_DONATE_EVENT: + case mhfpacket.OperateGuildDonateRoom: + // TODO: Where does this go? + case mhfpacket.OperateGuildDonateEvent: quantity := uint16(pkt.Data1.ReadUint32()) bf.WriteBytes(handleDonateRP(s, quantity, guild, true)) // TODO: Move this value onto rp_yesterday and reset to 0... daily? s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID) - case mhfpacket.OPERATE_GUILD_EVENT_EXCHANGE: + case mhfpacket.OperateGuildEventExchange: rp := uint16(pkt.Data1.ReadUint32()) var balance uint32 s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance) From 216893e3ce89014a3dcf6153b44560b9e0a5154b Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 9 Jul 2023 15:57:48 +1000 Subject: [PATCH 69/99] InfoGuild decoding & GetGuildManageRight cleanup --- server/channelserver/handlers_guild.go | 44 ++++++++++---------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 85ac916be..0858d66c2 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -919,7 +919,12 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(guild.SubMotto) // Unk appears to be static - bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) bf.WriteBool(!guild.Recruiting) @@ -954,10 +959,11 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(guild.PugiOutfit1) bf.WriteUint8(guild.PugiOutfit2) bf.WriteUint8(guild.PugiOutfit3) - // TODO: Skip if Diva Poogies don't exist yet - bf.WriteUint8(guild.PugiOutfit1) - bf.WriteUint8(guild.PugiOutfit2) - bf.WriteUint8(guild.PugiOutfit3) + if s.server.erupeConfig.RealClientMode >= _config.Z1 { + bf.WriteUint8(guild.PugiOutfit1) + bf.WriteUint8(guild.PugiOutfit2) + bf.WriteUint8(guild.PugiOutfit3) + } bf.WriteUint32(guild.PugiOutfits) if guild.Rank >= 3 { @@ -972,7 +978,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(55000) bf.WriteUint32(0) - bf.WriteUint16(0) + bf.WriteUint16(0) // Changing Room RP bf.WriteUint16(0) if guild.AllianceID > 0 { @@ -1365,7 +1371,7 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { if guild != nil { isApplicant, _ := guild.HasApplicationForCharID(s, s.charID) if isApplicant { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) return } } @@ -1407,7 +1413,9 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { for _, member := range guildMembers { bf.WriteUint32(member.CharID) bf.WriteUint16(member.HRP) - bf.WriteUint16(member.GR) + if s.server.erupeConfig.RealClientMode > _config.G7 { + bf.WriteUint16(member.GR) + } if s.server.erupeConfig.RealClientMode < _config.ZZ { // Magnet Spike crash workaround bf.WriteUint16(0) @@ -1473,7 +1481,6 @@ func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildManageRight) guild, err := GetGuildInfoByCharacterId(s, s.charID) - if guild == nil && s.prevGuildID != 0 { guild, err = GetGuildInfoByID(s, s.prevGuildID) s.prevGuildID = 0 @@ -1483,31 +1490,14 @@ func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { } } - if err != nil { - s.logger.Warn("failed to respond to manage rights message") - return - } else if guild == nil { - bf := byteframe.NewByteFrame() - bf.WriteUint16(0x00) // Unk - bf.WriteUint16(0x00) // Member count - - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) - return - } - bf := byteframe.NewByteFrame() - - bf.WriteUint16(0x00) // Unk - bf.WriteUint16(guild.MemberCount) - + bf.WriteUint32(uint32(guild.MemberCount)) members, _ := GetGuildMembers(s, guild.ID, false) - for _, member := range members { bf.WriteUint32(member.CharID) bf.WriteBool(member.Recruiter) bf.WriteBytes(make([]byte, 3)) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } From 0d1ee983f8c6192eb23b9d7ad3e243d07ccf2fea Mon Sep 17 00:00:00 2001 From: wish Date: Mon, 10 Jul 2023 22:23:22 +1000 Subject: [PATCH 70/99] decode Tournament handlers --- .../mhfpacket/msg_mhf_acquire_tournament.go | 17 +- network/mhfpacket/msg_mhf_entry_tournament.go | 19 ++- server/channelserver/handlers_tournament.go | 146 +++++++++++++----- 3 files changed, 132 insertions(+), 50 deletions(-) diff --git a/network/mhfpacket/msg_mhf_acquire_tournament.go b/network/mhfpacket/msg_mhf_acquire_tournament.go index d1d293288..2e65e0984 100644 --- a/network/mhfpacket/msg_mhf_acquire_tournament.go +++ b/network/mhfpacket/msg_mhf_acquire_tournament.go @@ -1,15 +1,18 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfAcquireTournament represents the MSG_MHF_ACQUIRE_TOURNAMENT -type MsgMhfAcquireTournament struct{} +type MsgMhfAcquireTournament struct { + AckHandle uint32 + TournamentID uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfAcquireTournament) Opcode() network.PacketID { @@ -18,7 +21,9 @@ func (m *MsgMhfAcquireTournament) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfAcquireTournament) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.TournamentID = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_entry_tournament.go b/network/mhfpacket/msg_mhf_entry_tournament.go index dbd600cab..6f6550cf0 100644 --- a/network/mhfpacket/msg_mhf_entry_tournament.go +++ b/network/mhfpacket/msg_mhf_entry_tournament.go @@ -1,15 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfEntryTournament represents the MSG_MHF_ENTRY_TOURNAMENT -type MsgMhfEntryTournament struct{} +type MsgMhfEntryTournament struct { + AckHandle uint32 + TournamentID uint32 + Unk0 uint8 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfEntryTournament) Opcode() network.PacketID { @@ -18,7 +22,10 @@ func (m *MsgMhfEntryTournament) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEntryTournament) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.TournamentID = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers_tournament.go b/server/channelserver/handlers_tournament.go index 84c2c8e8f..87fc95330 100644 --- a/server/channelserver/handlers_tournament.go +++ b/server/channelserver/handlers_tournament.go @@ -7,54 +7,124 @@ import ( "time" ) +type TournamentInfo0 struct { + ID uint32 + MaxPlayers uint32 + CurrentPlayers uint32 + Unk1 uint16 + TextColor uint16 + Unk2 uint32 + Time1 time.Time + Time2 time.Time + Time3 time.Time + Time4 time.Time + Time5 time.Time + Time6 time.Time + Unk3 uint8 + Unk4 uint8 + MinHR uint32 + MaxHR uint32 + Unk5 string + Unk6 string +} + +type TournamentInfo21 struct { + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint8 +} + +type TournamentInfo22 struct { + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint8 + Unk4 string +} + func handleMsgMhfInfoTournament(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfInfoTournament) bf := byteframe.NewByteFrame() + tournamentInfo0 := []TournamentInfo0{} + tournamentInfo21 := []TournamentInfo21{} + tournamentInfo22 := []TournamentInfo22{} + switch pkt.Unk0 { case 0: - bf.WriteUint32(uint32(TimeAdjusted().Unix())) - bf.WriteUint32(0) // Tied to schedule ID? - case 1: - - bf.WriteBytes(make([]byte, 21)) - ps.Uint8(bf, "", false) - break - - bf.WriteUint32(0xACEDCAFE) - - bf.WriteUint32(5) // Active schedule? - - bf.WriteUint32(1) // Schedule ID? - - bf.WriteUint32(32) // Max players - bf.WriteUint32(0) // Registered players - - bf.WriteUint16(0) - bf.WriteUint16(2) // Color code for schedule item bf.WriteUint32(0) - - bf.WriteUint32(uint32(time.Now().Add(time.Hour * -10).Unix())) - bf.WriteUint32(uint32(time.Now().Add(time.Hour * 10).Unix())) - bf.WriteUint32(uint32(time.Now().Add(time.Hour * 10).Unix())) - bf.WriteUint32(uint32(time.Now().Add(time.Hour * 10).Unix())) - bf.WriteUint32(uint32(time.Now().Add(time.Hour * 10).Unix())) - bf.WriteUint32(uint32(time.Now().Add(time.Hour * 10).Unix())) - - bf.WriteBool(true) // Unk - bf.WriteBool(false) // Cafe-only - - bf.WriteUint32(0) // Min HR - bf.WriteUint32(0) // Max HR - - ps.Uint8(bf, "Test", false) - - // ... + bf.WriteUint32(uint32(len(tournamentInfo0))) + for _, tinfo := range tournamentInfo0 { + bf.WriteUint32(tinfo.ID) + bf.WriteUint32(tinfo.MaxPlayers) + bf.WriteUint32(tinfo.CurrentPlayers) + bf.WriteUint16(tinfo.Unk1) + bf.WriteUint16(tinfo.TextColor) + bf.WriteUint32(tinfo.Unk2) + bf.WriteUint32(uint32(tinfo.Time1.Unix())) + bf.WriteUint32(uint32(tinfo.Time2.Unix())) + bf.WriteUint32(uint32(tinfo.Time3.Unix())) + bf.WriteUint32(uint32(tinfo.Time4.Unix())) + bf.WriteUint32(uint32(tinfo.Time5.Unix())) + bf.WriteUint32(uint32(tinfo.Time6.Unix())) + bf.WriteUint8(tinfo.Unk3) + bf.WriteUint8(tinfo.Unk4) + bf.WriteUint32(tinfo.MinHR) + bf.WriteUint32(tinfo.MaxHR) + ps.Uint8(bf, tinfo.Unk5, true) + ps.Uint16(bf, tinfo.Unk6, true) + } + case 1: + bf.WriteUint32(uint32(TimeAdjusted().Unix())) + bf.WriteUint32(0) // Registered ID + bf.WriteUint32(0) + bf.WriteUint32(0) + bf.WriteUint8(0) + bf.WriteUint32(0) + ps.Uint8(bf, "", true) + case 2: + bf.WriteUint32(0) + bf.WriteUint32(uint32(len(tournamentInfo21))) + for _, info := range tournamentInfo21 { + bf.WriteUint32(info.Unk0) + bf.WriteUint32(info.Unk1) + bf.WriteUint32(info.Unk2) + bf.WriteUint8(info.Unk3) + } + bf.WriteUint32(uint32(len(tournamentInfo22))) + for _, info := range tournamentInfo22 { + bf.WriteUint32(info.Unk0) + bf.WriteUint32(info.Unk1) + bf.WriteUint32(info.Unk2) + bf.WriteUint8(info.Unk3) + ps.Uint8(bf, info.Unk4, true) + } } doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfEntryTournament(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEntryTournament(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEntryTournament) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} -func handleMsgMhfAcquireTournament(s *Session, p mhfpacket.MHFPacket) {} +type TournamentReward struct { + Unk0 uint16 + Unk1 uint16 + Unk2 uint16 +} + +func handleMsgMhfAcquireTournament(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireTournament) + rewards := []TournamentReward{} + bf := byteframe.NewByteFrame() + bf.WriteUint8(uint8(len(rewards))) + for _, reward := range rewards { + bf.WriteUint16(reward.Unk0) + bf.WriteUint16(reward.Unk1) + bf.WriteUint16(reward.Unk2) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} From 4e2cb1fad901fdd766479a079cdb8b2b2acc67f2 Mon Sep 17 00:00:00 2001 From: wish Date: Thu, 13 Jul 2023 18:12:46 +1000 Subject: [PATCH 71/99] skip invalid pointers --- server/channelserver/handlers_character.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 01d9dc73a..7a4c164fd 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -151,7 +151,7 @@ func (save *CharacterSaveData) updateSaveDataWithStruct() { if _config.ErupeConfig.RealClientMode == _config.ZZ { copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) - } else { + } else if _config.ErupeConfig.RealClientMode >= _config.Z1 { copy(save.decompSave[pointerRPZ:pointerRPZ+2], rpBytes) copy(save.decompSave[pointerKQFZ:pointerKQFZ+8], save.KQF) } @@ -181,7 +181,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() { save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4])) } save.KQF = save.decompSave[pointerKQF : pointerKQF+8] - } else { + } else if _config.ErupeConfig.RealClientMode >= _config.Z1 { save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRPZ : pointerRPZ+2]) save.HouseTier = save.decompSave[pointerHouseTierZ : pointerHouseTierZ+5] save.HouseData = save.decompSave[pointerHouseDataZ : pointerHouseDataZ+195] From aa442b3b7d54a5def927d85baaee1c0cee2b4e94 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 09:00:07 +1000 Subject: [PATCH 72/99] parse most Campaign packets --- network/mhfpacket/msg_mhf_acquire_item.go | 23 +++++++--- network/mhfpacket/msg_mhf_apply_campaign.go | 21 ++++----- .../mhfpacket/msg_mhf_enumerate_campaign.go | 17 +++---- network/mhfpacket/msg_mhf_enumerate_item.go | 21 ++++++--- network/mhfpacket/msg_mhf_state_campaign.go | 19 +++----- server/channelserver/handlers.go | 4 -- server/channelserver/handlers_campaign.go | 45 +++++++++++++++++-- 7 files changed, 97 insertions(+), 53 deletions(-) diff --git a/network/mhfpacket/msg_mhf_acquire_item.go b/network/mhfpacket/msg_mhf_acquire_item.go index 96d96ab11..de86ce846 100644 --- a/network/mhfpacket/msg_mhf_acquire_item.go +++ b/network/mhfpacket/msg_mhf_acquire_item.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM -type MsgMhfAcquireItem struct{} +type MsgMhfAcquireItem struct { + AckHandle uint32 + Unk0 uint16 + Length uint16 + Unk1 []uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfAcquireItem) Opcode() network.PacketID { @@ -18,7 +23,13 @@ func (m *MsgMhfAcquireItem) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Length = bf.ReadUint16() + for i := 0; i < int(m.Length); i++ { + m.Unk1 = append(m.Unk1, bf.ReadUint32()) + } + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_apply_campaign.go b/network/mhfpacket/msg_mhf_apply_campaign.go index 04f506a44..b39dab499 100644 --- a/network/mhfpacket/msg_mhf_apply_campaign.go +++ b/network/mhfpacket/msg_mhf_apply_campaign.go @@ -1,17 +1,18 @@ package mhfpacket import ( + "errors" + "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" - "erupe-ce/common/byteframe" ) // MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN type MsgMhfApplyCampaign struct { AckHandle uint32 - Unk0 uint8 - Unk1 uint8 - Unk2 uint16 + Unk0 uint32 + Unk1 uint16 + Unk2 []byte } // Opcode returns the ID associated with this packet type. @@ -22,17 +23,13 @@ func (m *MsgMhfApplyCampaign) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() - m.Unk2 = bf.ReadUint16() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadBytes(16) return nil } // Build builds a binary packet from the current data. func (m *MsgMhfApplyCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - bf.WriteUint32(m.AckHandle) - bf.WriteUint8(m.Unk0) - bf.WriteUint8(m.Unk1) - bf.WriteUint16(m.Unk2) - return nil + return errors.New("NOT IMPLEMENTED") } diff --git a/network/mhfpacket/msg_mhf_enumerate_campaign.go b/network/mhfpacket/msg_mhf_enumerate_campaign.go index a5e39a1cd..d06075077 100644 --- a/network/mhfpacket/msg_mhf_enumerate_campaign.go +++ b/network/mhfpacket/msg_mhf_enumerate_campaign.go @@ -1,17 +1,16 @@ package mhfpacket import ( + "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" - "erupe-ce/common/byteframe" ) // MsgMhfEnumerateCampaign represents the MSG_MHF_ENUMERATE_CAMPAIGN type MsgMhfEnumerateCampaign struct { AckHandle uint32 - Unk0 uint8 - Unk1 uint8 - Unk2 uint16 + Unk0 uint16 + Unk1 uint16 } // Opcode returns the ID associated with this packet type. @@ -22,17 +21,15 @@ func (m *MsgMhfEnumerateCampaign) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumerateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() - m.Unk2 = bf.ReadUint16() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() return nil } // Build builds a binary packet from the current data. func (m *MsgMhfEnumerateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { bf.WriteUint32(m.AckHandle) - bf.WriteUint8(m.Unk0) - bf.WriteUint8(m.Unk1) - bf.WriteUint16(m.Unk2) + bf.WriteUint16(m.Unk0) + bf.WriteUint16(m.Unk1) return nil } diff --git a/network/mhfpacket/msg_mhf_enumerate_item.go b/network/mhfpacket/msg_mhf_enumerate_item.go index b12276703..ae70deae7 100644 --- a/network/mhfpacket/msg_mhf_enumerate_item.go +++ b/network/mhfpacket/msg_mhf_enumerate_item.go @@ -1,15 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM -type MsgMhfEnumerateItem struct{} +type MsgMhfEnumerateItem struct { + AckHandle uint32 + Unk0 uint16 + Unk1 uint16 + Unk2 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfEnumerateItem) Opcode() network.PacketID { @@ -18,7 +23,11 @@ func (m *MsgMhfEnumerateItem) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_state_campaign.go b/network/mhfpacket/msg_mhf_state_campaign.go index 35cca070d..40a2cc341 100644 --- a/network/mhfpacket/msg_mhf_state_campaign.go +++ b/network/mhfpacket/msg_mhf_state_campaign.go @@ -1,18 +1,18 @@ package mhfpacket import ( + "errors" "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" ) // MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN type MsgMhfStateCampaign struct { AckHandle uint32 - Unk0 uint8 - Unk1 uint8 - Unk2 uint16 + Unk0 uint32 + Unk1 uint16 } // Opcode returns the ID associated with this packet type. @@ -23,17 +23,12 @@ func (m *MsgMhfStateCampaign) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() - m.Unk2 = bf.ReadUint16() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() return nil } // Build builds a binary packet from the current data. func (m *MsgMhfStateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - bf.WriteUint32(m.AckHandle) - bf.WriteUint8(m.Unk0) - bf.WriteUint8(m.Unk1) - bf.WriteUint16(m.Unk2) - return nil + return errors.New("NOT IMPLEMENTED") } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 4647b8021..a8a37d181 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -552,10 +552,6 @@ func handleMsgSysInfokyserver(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetCaUniqueID(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {} - -func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {} - func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfTransferItem) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) diff --git a/server/channelserver/handlers_campaign.go b/server/channelserver/handlers_campaign.go index 8522adab2..bd6ee0552 100644 --- a/server/channelserver/handlers_campaign.go +++ b/server/channelserver/handlers_campaign.go @@ -1,18 +1,57 @@ package channelserver -import "erupe-ce/network/mhfpacket" +import ( + "erupe-ce/common/byteframe" + "erupe-ce/network/mhfpacket" +) func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign) - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + bf := byteframe.NewByteFrame() + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) + bf.WriteUint8(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStateCampaign) - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + bf := byteframe.NewByteFrame() + bf.WriteUint16(0) + bf.WriteUint16(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfApplyCampaign) doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } + +func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateItem) + items := []struct { + Unk0 uint32 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 + Unk4 uint32 + Unk5 uint32 + }{} + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(len(items))) + for _, item := range items { + bf.WriteUint32(item.Unk0) + bf.WriteUint16(item.Unk1) + bf.WriteUint16(item.Unk2) + bf.WriteUint16(item.Unk3) + bf.WriteUint32(item.Unk4) + bf.WriteUint32(item.Unk5) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireItem) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} From e7a0813023b0f241b65a9ad8f43688c87da06c28 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 10:16:23 +1000 Subject: [PATCH 73/99] port Campaign structs --- server/channelserver/handlers_campaign.go | 124 +++++++++++++++++++++- 1 file changed, 119 insertions(+), 5 deletions(-) diff --git a/server/channelserver/handlers_campaign.go b/server/channelserver/handlers_campaign.go index bd6ee0552..4cc61a1d3 100644 --- a/server/channelserver/handlers_campaign.go +++ b/server/channelserver/handlers_campaign.go @@ -2,16 +2,128 @@ package channelserver import ( "erupe-ce/common/byteframe" + ps "erupe-ce/common/pascalstring" + "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" + "time" ) +type CampaignEvent struct { + ID uint32 + Unk0 uint32 + MinHR int16 + MaxHR int16 + MinSR int16 + MaxSR int16 + MinGR int16 + MaxGR int16 + Unk1 uint16 + Unk2 uint8 + Unk3 uint8 + Unk4 uint16 + Unk5 uint16 + Start time.Time + End time.Time + Unk6 uint8 + String0 string + String1 string + String2 string + String3 string + Link string + Prefix string + Categories []uint16 +} + +type CampaignCategory struct { + ID uint16 + Type uint8 + Title string + Description string +} + +type CampaignLink struct { + CategoryID uint16 + CampaignID uint32 +} + func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign) bf := byteframe.NewByteFrame() - bf.WriteUint8(0) - bf.WriteUint8(0) - bf.WriteUint8(0) - bf.WriteUint8(0) + + events := []CampaignEvent{} + categories := []CampaignCategory{} + var campaignLinks []CampaignLink + + if len(events) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(events))) + } else { + bf.WriteUint8(uint8(len(events))) + } + for _, event := range events { + bf.WriteUint32(event.ID) + bf.WriteUint32(event.Unk0) + bf.WriteInt16(event.MinHR) + bf.WriteInt16(event.MaxHR) + bf.WriteInt16(event.MinSR) + bf.WriteInt16(event.MaxSR) + bf.WriteInt16(event.MinGR) + bf.WriteInt16(event.MaxGR) + bf.WriteUint16(event.Unk1) + bf.WriteUint8(event.Unk2) + bf.WriteUint8(event.Unk3) + bf.WriteUint16(event.Unk4) + bf.WriteUint16(event.Unk5) + bf.WriteUint32(uint32(event.Start.Unix())) + bf.WriteUint32(uint32(event.End.Unix())) + bf.WriteUint8(event.Unk6) + ps.Uint8(bf, event.String0, true) + ps.Uint8(bf, event.String1, true) + ps.Uint8(bf, event.String2, true) + ps.Uint8(bf, event.String3, true) + ps.Uint8(bf, event.Link, true) + for i := range event.Categories { + campaignLinks = append(campaignLinks, CampaignLink{event.Categories[i], event.ID}) + } + } + + if len(events) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(events))) + } else { + bf.WriteUint8(uint8(len(events))) + } + for _, event := range events { + bf.WriteUint32(event.ID) + bf.WriteUint8(1) // Always 1? + bf.WriteBytes([]byte(event.Prefix)) + } + + if len(categories) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(categories))) + } else { + bf.WriteUint8(uint8(len(categories))) + } + for _, category := range categories { + bf.WriteUint16(category.ID) + bf.WriteUint8(category.Type) + bf.WriteUint8(uint8(len(category.Title))) + bf.WriteUint8(uint8(len(category.Description))) + bf.WriteBytes(stringsupport.UTF8ToSJIS(category.Title)) + bf.WriteBytes(stringsupport.UTF8ToSJIS(category.Description)) + } + + if len(campaignLinks) > 255 { + bf.WriteUint8(255) + bf.WriteUint16(uint16(len(campaignLinks))) + } else { + bf.WriteUint8(uint8(len(campaignLinks))) + } + for _, link := range campaignLinks { + bf.WriteUint16(link.CategoryID) + bf.WriteUint32(link.CampaignID) + } doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } @@ -25,7 +137,9 @@ func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfApplyCampaign) - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + bf := byteframe.NewByteFrame() + bf.WriteUint32(1) + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) { From f2947f90c0832cb3301b5ed807abcc20c69adda2 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 11:48:09 +1000 Subject: [PATCH 74/99] minor Campaign fixes --- server/channelserver/handlers_campaign.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/channelserver/handlers_campaign.go b/server/channelserver/handlers_campaign.go index 4cc61a1d3..2041b484b 100644 --- a/server/channelserver/handlers_campaign.go +++ b/server/channelserver/handlers_campaign.go @@ -108,10 +108,12 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { for _, category := range categories { bf.WriteUint16(category.ID) bf.WriteUint8(category.Type) - bf.WriteUint8(uint8(len(category.Title))) - bf.WriteUint8(uint8(len(category.Description))) - bf.WriteBytes(stringsupport.UTF8ToSJIS(category.Title)) - bf.WriteBytes(stringsupport.UTF8ToSJIS(category.Description)) + xTitle := stringsupport.UTF8ToSJIS(category.Title) + xDescription := stringsupport.UTF8ToSJIS(category.Description) + bf.WriteUint8(uint8(len(xTitle))) + bf.WriteUint8(uint8(len(xDescription))) + bf.WriteBytes(xTitle) + bf.WriteBytes(xDescription) } if len(campaignLinks) > 255 { @@ -130,7 +132,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStateCampaign) bf := byteframe.NewByteFrame() - bf.WriteUint16(0) + bf.WriteUint16(1) bf.WriteUint16(0) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } From 8425c0a99e7401909570de5c1676fa563286b93c Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 12:59:23 +1000 Subject: [PATCH 75/99] README formatting --- README.md | 66 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 60e50503e..ede542a20 100644 --- a/README.md +++ b/README.md @@ -51,31 +51,31 @@ This portion of the documentation goes over the `config.json` file. | PatchServerFile | | | | | ScreenshotAPIURL | This is the URL you want user sreenshots to go to | | | | DeleteOnSaveCorruption | This option deletes a users save from the database if they corrupt it, can be used as punishment for cheaters | false | | -| ClientMode | This tells the server what client it should run for | ZZ | Check compatible versions above | +| ClientMode | This tells the server what client version it should target | ZZ | Check compatible versions above | | DevMode | This enables DevModeOptions to be configured | true | | ### `DevModeOptions` Configuraiton -| Variable | Description | Default | Options | -|----------------------|----------------------------------------------------------------------------------------------------|----------|----------------------------------| -| AutoCreateAccount | This allows users that don't exist to auto create there account from initial login | true | | -| CleanDB | This cleans the database down | false | | -| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break World HR requirements | false | | -| LogInboundMessages | This will allow inbound messages to be logged in the stdout terminal you run the applicaiton from | false | | -| LogOutboundMessages | This will allow outbound messages to be logged in the stdout terminal you run the applicaiton from | false | | -| MaxHexdumpLength | This is the maximum amount of hex that will be dumped to stdout along side a message | 0 | | -| DivaEvent | This overrides the Diva event stage in game | 2 | 0/1/2/3/-1 | -| FestaEvent | This overrides the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | -| TournamentEvent | This overrides the Hunter Tournament event stage in game | 2 | 0/1/2/3/-1 | -| MezFesEvent | Enables whether the MezFes event & World are active | true | | -| MezFesAlt | Switches the multiplayer MezFes event | false | | -| DisableTokenCheck | This disables the random token that is generated at login from being checked, very insecure | false | | -| QuestDebugTools | Enable various quest debug logs | false | | -| EarthStatusOverride | Enables Pallone Fest, Tower and Conquest War events | 0 | 2=Conquest, 11=Pallone, 21=Tower | -| EarthIDOverride | A random event ID | 0 | | -| EarthMonsterOverride | Sets the ID of the monster targeted in the Conquest War | 0 | | -| SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | -| SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | +| Variable | Description | Default | Options | +|----------------------|---------------------------------------------------------------------------------------------|----------|----------------------------------| +| AutoCreateAccount | This allows users that don't exist to auto create there account from initial login | true | | +| CleanDB | This cleans the database down | false | | +| MaxLauncherHR | This sets the launcher value to HR7 to allow you to break World HR requirements | false | | +| LogInboundMessages | This will allow inbound messages to be logged to stdout | false | | +| LogOutboundMessages | This will allow outbound messages to be logged to stdout | false | | +| MaxHexdumpLength | This is the maximum amount of hex bytes that will be dumped to stdout | 0 | | +| DivaEvent | This overrides the Diva event stage in game | 2 | 0/1/2/3/-1 | +| FestaEvent | This overrides the Hunter Festival event stage in game | 2 | 0/1/2/3/-1 | +| TournamentEvent | This overrides the Hunter Tournament event stage in game | 2 | 0/1/2/3/-1 | +| MezFesEvent | Enables whether the MezFes event & World are active | true | | +| MezFesAlt | Switches the multiplayer MezFes event | false | | +| DisableTokenCheck | This disables the random token that is generated at login from being checked, very insecure | false | | +| QuestDebugTools | Enable various quest debug logs | false | | +| EarthStatusOverride | Enables Pallone Fest, Tower and Conquest War events | 0 | 2=Conquest, 11=Pallone, 21=Tower | +| EarthIDOverride | A random event ID | 0 | | +| EarthMonsterOverride | Sets the ID of the monster targeted in the Conquest War | 0 | | +| SaveDumps.Enables | Enables save dumps to a folder that is set at `SaveDumps.OutputDir` | true | | +| SaveDumps.OutputDir | The folder that save dumps are saved to | savedata | | ### `GameplayOptions` Configuraiton @@ -111,23 +111,23 @@ This may be either be removed or revamped in a future version. ### Commands There are several chat commands that can be turned on and off. Most of them are really for admins or debugging purposes. -| Name | command | Description | Options | -|----------|----------------|---------------------------------------------------------|---------------------| -| Rights | !rights | Changes rights interger to specifc interger | | -| Teleport | !tele | Teleports user to specific x,y,z | | -| Reload | !reload | Flush all objects and users and reload stage you are on | | -| KeyQuest | !kqf | | | -| Course | !course OPTION | Changes the players course | HL,EX,Premium,Boost | -| PSN | !psn USERNAME | Links Erupe account to PSN | | +| Name | command | Description | Options | +|----------|----------------|--------------------------------------------|---------------------| +| Rights | !rights VALUE | Sets the rights integer for your account | | +| Teleport | !tele X,Y | Teleports user to specific x,y coordinate | | +| Reload | !reload | Reloads all users and character objects | | +| KeyQuest | !kqf FLAGS | Sets the Key Quest Flag for your character | | +| Course | !course OPTION | Enables/Disables a course for your account | HL,EX,Premium,Boost | +| PSN | !psn USERNAME | Links the specified PSN to your account | | ### Ravi Sub Commands | Name | command | Description | |----------|----------------------------------|-------------------------------| | Raviente | !ravi start | Starts Ravi Event | -| Raviente | !ravi cm / !ravi checkmultiplier | Checks Ravi health multiplier | -| Raviente | !ravi ss | Send sedation | -| Raviente | !ravi sr | Send resurrection | -| Raviente | !ravi rs | Request sedation | +| Raviente | !ravi cm / !ravi checkmultiplier | Checks Ravi Damage Multiplier | +| Raviente | !ravi ss | Send Sedation Support | +| Raviente | !ravi sr | Send Resurrection Support | +| Raviente | !ravi rs | Request Sedation Support | ## World `Entries` config From 15e31d7786d36092598ad136bbe93eb0523b0d4c Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 13:00:25 +1000 Subject: [PATCH 76/99] decode EnumerateEvent --- server/channelserver/handlers_event.go | 34 +++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index ff84b4a7a..7797bd6fc 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -48,9 +48,41 @@ func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) { }) } +type Event struct { + Unk0 uint16 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 + Unk4 uint16 + Unk5 uint32 + Unk6 uint32 + Unk7 []uint16 +} + func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateEvent) - stubEnumerateNoResults(s, pkt.AckHandle) + bf := byteframe.NewByteFrame() + + events := []Event{} + + bf.WriteUint8(uint8(len(events))) + for _, event := range events { + bf.WriteUint16(event.Unk0) + bf.WriteUint16(event.Unk1) + bf.WriteUint16(event.Unk2) + bf.WriteUint16(event.Unk3) + bf.WriteUint16(event.Unk4) + bf.WriteUint32(event.Unk5) + bf.WriteUint32(event.Unk6) + if event.Unk0 == 2 { + bf.WriteUint8(uint8(len(event.Unk7))) + for _, u := range event.Unk7 { + bf.WriteUint16(u) + } + } + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type activeFeature struct { From d6b8ac96d8191de7a987c7e506c1769a954c5da2 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 16 Jul 2023 13:01:15 +1000 Subject: [PATCH 77/99] rename Campaign packet variables --- network/mhfpacket/msg_mhf_enumerate_item.go | 10 +++++----- network/mhfpacket/msg_mhf_state_campaign.go | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/network/mhfpacket/msg_mhf_enumerate_item.go b/network/mhfpacket/msg_mhf_enumerate_item.go index ae70deae7..fea4f3371 100644 --- a/network/mhfpacket/msg_mhf_enumerate_item.go +++ b/network/mhfpacket/msg_mhf_enumerate_item.go @@ -10,10 +10,10 @@ import ( // MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM type MsgMhfEnumerateItem struct { - AckHandle uint32 - Unk0 uint16 - Unk1 uint16 - Unk2 uint32 + AckHandle uint32 + Unk0 uint16 + Unk1 uint16 + CampaignID uint32 } // Opcode returns the ID associated with this packet type. @@ -26,7 +26,7 @@ func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint16() m.Unk1 = bf.ReadUint16() - m.Unk2 = bf.ReadUint32() + m.CampaignID = bf.ReadUint32() return nil } diff --git a/network/mhfpacket/msg_mhf_state_campaign.go b/network/mhfpacket/msg_mhf_state_campaign.go index 40a2cc341..ab6342c55 100644 --- a/network/mhfpacket/msg_mhf_state_campaign.go +++ b/network/mhfpacket/msg_mhf_state_campaign.go @@ -10,9 +10,9 @@ import ( // MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN type MsgMhfStateCampaign struct { - AckHandle uint32 - Unk0 uint32 - Unk1 uint16 + AckHandle uint32 + CampaignID uint32 + Unk1 uint16 } // Opcode returns the ID associated with this packet type. @@ -23,7 +23,7 @@ func (m *MsgMhfStateCampaign) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() + m.CampaignID = bf.ReadUint32() m.Unk1 = bf.ReadUint16() return nil } From 4826882bcda56586e4b7374128371365be65ccda Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 21:42:54 +1000 Subject: [PATCH 78/99] correctly parse SexChanger --- network/mhfpacket/msg_mhf_sex_changer.go | 14 ++++++++++---- server/channelserver/handlers_character.go | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/network/mhfpacket/msg_mhf_sex_changer.go b/network/mhfpacket/msg_mhf_sex_changer.go index 74186d84b..a8754feca 100644 --- a/network/mhfpacket/msg_mhf_sex_changer.go +++ b/network/mhfpacket/msg_mhf_sex_changer.go @@ -1,17 +1,20 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfSexChanger represents the MSG_MHF_SEX_CHANGER type MsgMhfSexChanger struct { AckHandle uint32 Gender uint8 + Unk0 uint8 + Unk1 uint8 + Unk2 uint8 } // Opcode returns the ID associated with this packet type. @@ -23,6 +26,9 @@ func (m *MsgMhfSexChanger) Opcode() network.PacketID { func (m *MsgMhfSexChanger) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Gender = bf.ReadUint8() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint8() return nil } diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 7a4c164fd..9541e1d30 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -203,5 +203,5 @@ func (save *CharacterSaveData) updateStructWithSaveData() { func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSexChanger) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } From cd189e7ca3a8188f886de6f77ef6021426119007 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 21:43:41 +1000 Subject: [PATCH 79/99] parse SetCaAchievementHist --- .../msg_mhf_set_ca_achievement_hist.go | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go b/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go index a04d6b89f..0b4fad343 100644 --- a/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go +++ b/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go @@ -1,18 +1,24 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) -// MsgMhfSetCaAchievementHist represents the MSG_MHF_SET_CA_ACHIEVEMENT_HIST -type MsgMhfSetCaAchievementHist struct{ - AckHandle uint32 +type CaAchievementHist struct { Unk0 uint32 - Unk1 uint32 + Unk1 uint8 +} + +// MsgMhfSetCaAchievementHist represents the MSG_MHF_SET_CA_ACHIEVEMENT_HIST +type MsgMhfSetCaAchievementHist struct { + AckHandle uint32 + Unk0 uint16 + Unk1 uint8 + Unk2 []CaAchievementHist } // Opcode returns the ID associated with this packet type. @@ -23,8 +29,14 @@ func (m *MsgMhfSetCaAchievementHist) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSetCaAchievementHist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() - m.Unk1 = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + for i := 0; i < int(m.Unk1); i++ { + var temp CaAchievementHist + temp.Unk0 = bf.ReadUint32() + temp.Unk1 = bf.ReadUint8() + m.Unk2 = append(m.Unk2, temp) + } return nil } From 5c68dc1ddc59c5a7cee184a0ef825da524c7d26e Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 21:44:00 +1000 Subject: [PATCH 80/99] parse ReadLastWeekBeatRanking --- .../msg_mhf_read_last_week_beat_ranking.go | 19 +++++++++++++------ server/channelserver/handlers_seibattle.go | 10 +++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go b/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go index 90635dd3f..b52195578 100644 --- a/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go +++ b/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go @@ -1,15 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfReadLastWeekBeatRanking represents the MSG_MHF_READ_LAST_WEEK_BEAT_RANKING -type MsgMhfReadLastWeekBeatRanking struct{} +type MsgMhfReadLastWeekBeatRanking struct { + AckHandle uint32 + Unk0 uint32 + Unk1 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfReadLastWeekBeatRanking) Opcode() network.PacketID { @@ -18,7 +22,10 @@ func (m *MsgMhfReadLastWeekBeatRanking) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfReadLastWeekBeatRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadInt32() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers_seibattle.go b/server/channelserver/handlers_seibattle.go index 4df05c67d..caf5c19c9 100644 --- a/server/channelserver/handlers_seibattle.go +++ b/server/channelserver/handlers_seibattle.go @@ -68,7 +68,15 @@ func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { doAckBufSucceed(s, pkt.AckHandle, resp.Data()) } -func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadLastWeekBeatRanking) + bf := byteframe.NewByteFrame() + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + bf.WriteInt32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel) From db67746c30fddb9a6740683b4d575d134b590fad Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 21:44:24 +1000 Subject: [PATCH 81/99] parse & handle GetSenyuDailyCount --- .../mhfpacket/msg_mhf_get_senyu_daily_count.go | 15 +++++++++------ server/channelserver/handlers.go | 8 +++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/network/mhfpacket/msg_mhf_get_senyu_daily_count.go b/network/mhfpacket/msg_mhf_get_senyu_daily_count.go index c4d34089e..4bc9f41d2 100644 --- a/network/mhfpacket/msg_mhf_get_senyu_daily_count.go +++ b/network/mhfpacket/msg_mhf_get_senyu_daily_count.go @@ -1,15 +1,17 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfGetSenyuDailyCount represents the MSG_MHF_GET_SENYU_DAILY_COUNT -type MsgMhfGetSenyuDailyCount struct{} +type MsgMhfGetSenyuDailyCount struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetSenyuDailyCount) Opcode() network.PacketID { @@ -18,7 +20,8 @@ func (m *MsgMhfGetSenyuDailyCount) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetSenyuDailyCount) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index a8a37d181..9c25638b5 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1630,7 +1630,13 @@ func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetSenyuDailyCount) + bf := byteframe.NewByteFrame() + bf.WriteUint16(0) + bf.WriteUint16(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} type SeibattleTimetable struct { Start time.Time From d700b8bd910cf009a480eb75aa9338017459f1d5 Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 22:13:01 +1000 Subject: [PATCH 82/99] simplify Savedata pointers --- server/channelserver/handlers_character.go | 133 +++++++++++---------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 9541e1d30..0dac950ff 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -12,41 +12,29 @@ import ( "go.uber.org/zap" ) +type SavePointer int + const ( - pointerGender = 0x51 // +1 - - pointerRP = 0x22D16 // +2 - pointerHouseTier = 0x1FB6C // +5 - pointerHouseData = 0x1FE01 // +195 - pointerBookshelfData = 0x22298 // +5576 - // Gallery data also exists at 0x21578, is this the contest submission? - pointerGalleryData = 0x22320 // +1748 - pointerToreData = 0x1FCB4 // +240 - pointerGardenData = 0x22C58 // +68 - pointerWeaponType = 0x1F715 // +1 - pointerWeaponID = 0x1F60A // +2 - pointerHRP = 0x1FDF6 // +2 - pointerGRP = 0x1FDFC // +4 - pointerKQF = 0x23D20 // +8 - - pointerRPZ = 0x1A076 - pointerHouseTierZ = 0x16ECC - pointerHouseDataZ = 0x17161 - pointerBookshelfDataZ = 0x195F8 - pointerGalleryDataZ = 0x19680 - pointerToreDataZ = 0x17014 - pointerGardenDataZ = 0x19FB8 - pointerWeaponTypeZ = 0x16A75 - pointerWeaponIDZ = 0x1696A - pointerHRPZ = 0x17156 - pointerGRPZ = 0x1715C - pointerKQFZ = 0x1B080 + pGender = iota // +1 + pRP // +2 + pHouseTier // +5 + pHouseData // +195 + pBookshelfData // +5576 + pGalleryData // +1748 + pToreData // +240 + pGardenData // +68 + pWeaponType // +1 + pWeaponID // +2 + pHRP // +2 + pGRP // +4 + pKQF // +8 ) type CharacterSaveData struct { CharID uint32 Name string IsNewCharacter bool + Pointers map[SavePointer]int Gender bool RP uint16 @@ -66,6 +54,39 @@ type CharacterSaveData struct { decompSave []byte } +func getPointers() map[SavePointer]int { + pointers := map[SavePointer]int{pGender: 81} + switch _config.ErupeConfig.RealClientMode { + case _config.ZZ: + pointers[pWeaponID] = 128522 + pointers[pWeaponType] = 128789 + pointers[pHouseTier] = 129900 + pointers[pToreData] = 130228 + pointers[pHRP] = 130550 + pointers[pGRP] = 130556 + pointers[pHouseData] = 130561 + pointers[pBookshelfData] = 139928 + pointers[pGalleryData] = 140064 + pointers[pGardenData] = 142424 + pointers[pRP] = 142614 + pointers[pKQF] = 146720 + case _config.Z2, _config.Z1, _config.G101, _config.G10: + pointers[pWeaponID] = 92522 + pointers[pWeaponType] = 92789 + pointers[pHouseTier] = 93900 + pointers[pToreData] = 94228 + pointers[pHRP] = 94550 + pointers[pGRP] = 94556 + pointers[pHouseData] = 94561 + pointers[pBookshelfData] = 103928 + pointers[pGalleryData] = 104064 + pointers[pGardenData] = 106424 + pointers[pRP] = 106614 + pointers[pKQF] = 110720 + } + return pointers +} + func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) { result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID) if err != nil { @@ -79,7 +100,9 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) return nil, err } - saveData := &CharacterSaveData{} + saveData := &CharacterSaveData{ + Pointers: getPointers(), + } err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name) if err != nil { s.logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID)) @@ -148,54 +171,36 @@ func (save *CharacterSaveData) Decompress() error { func (save *CharacterSaveData) updateSaveDataWithStruct() { rpBytes := make([]byte, 2) binary.LittleEndian.PutUint16(rpBytes, save.RP) - if _config.ErupeConfig.RealClientMode == _config.ZZ { - copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) - copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) - } else if _config.ErupeConfig.RealClientMode >= _config.Z1 { - copy(save.decompSave[pointerRPZ:pointerRPZ+2], rpBytes) - copy(save.decompSave[pointerKQFZ:pointerKQFZ+8], save.KQF) + if _config.ErupeConfig.RealClientMode >= _config.G10 { + copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes) + copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF) } } // This will update the save struct with the values stored in the character save func (save *CharacterSaveData) updateStructWithSaveData() { save.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(save.decompSave[88:100])) - if save.decompSave[pointerGender] == 1 { + if save.decompSave[save.Pointers[pGender]] == 1 { save.Gender = true } else { save.Gender = false } if !save.IsNewCharacter { - if _config.ErupeConfig.RealClientMode == _config.ZZ { - save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2]) - save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5] - save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195] - save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576] - save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748] - save.ToreData = save.decompSave[pointerToreData : pointerToreData+240] - save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68] - save.WeaponType = save.decompSave[pointerWeaponType] - save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2]) - save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2]) + if _config.ErupeConfig.RealClientMode >= _config.G10 { + save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+2]) + save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+5] + save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+195] + save.BookshelfData = save.decompSave[save.Pointers[pBookshelfData] : save.Pointers[pBookshelfData]+5576] + save.GalleryData = save.decompSave[save.Pointers[pGalleryData] : save.Pointers[pGalleryData]+1748] + save.ToreData = save.decompSave[save.Pointers[pToreData] : save.Pointers[pToreData]+240] + save.GardenData = save.decompSave[save.Pointers[pGardenData] : save.Pointers[pGardenData]+68] + save.WeaponType = save.decompSave[save.Pointers[pWeaponType]] + save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2]) + save.HRP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHRP] : save.Pointers[pHRP]+2]) if save.HRP == uint16(999) { - save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4])) + save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4])) } - save.KQF = save.decompSave[pointerKQF : pointerKQF+8] - } else if _config.ErupeConfig.RealClientMode >= _config.Z1 { - save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRPZ : pointerRPZ+2]) - save.HouseTier = save.decompSave[pointerHouseTierZ : pointerHouseTierZ+5] - save.HouseData = save.decompSave[pointerHouseDataZ : pointerHouseDataZ+195] - save.BookshelfData = save.decompSave[pointerBookshelfDataZ : pointerBookshelfDataZ+5576] - save.GalleryData = save.decompSave[pointerGalleryDataZ : pointerGalleryDataZ+1748] - save.ToreData = save.decompSave[pointerToreDataZ : pointerToreDataZ+240] - save.GardenData = save.decompSave[pointerGardenDataZ : pointerGardenDataZ+68] - save.WeaponType = save.decompSave[pointerWeaponTypeZ] - save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponIDZ : pointerWeaponIDZ+2]) - save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRPZ : pointerHRPZ+2]) - if save.HRP == uint16(999) { - save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRPZ : pointerGRPZ+4])) - } - save.KQF = save.decompSave[pointerKQFZ : pointerKQFZ+8] + save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8] } } return From d3f2dcf7ed5255082c6c5af069e25ed45270f43e Mon Sep 17 00:00:00 2001 From: wish Date: Wed, 19 Jul 2023 22:14:17 +1000 Subject: [PATCH 83/99] change default SaveDumps destination --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 1e09daddd..dcf800fdb 100644 --- a/config.json +++ b/config.json @@ -32,7 +32,7 @@ "EarthMonsterOverride": 0, "SaveDumps": { "Enabled": true, - "OutputDir": "savedata" + "OutputDir": "save-backups" } }, "GameplayOptions": { From 6a34fc9a76ded8e9491026685a1d5ef9f48734ef Mon Sep 17 00:00:00 2001 From: wish Date: Thu, 20 Jul 2023 22:51:05 +1000 Subject: [PATCH 84/99] add KaijiEvent GameplayOption --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_quest.go | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index dcf800fdb..6e69bb0a8 100644 --- a/config.json +++ b/config.json @@ -55,6 +55,7 @@ "MaterialMultiplier": 1.00, "ExtraCarves": 0, "DisableHunterNavi": false, + "EnableKaijiEvent": false, "EnableHiganjimaEvent": false, "EnableNierEvent": false, "DisableRoad": false diff --git a/config/config.go b/config/config.go index 7ef6c9bad..c02296b26 100644 --- a/config/config.go +++ b/config/config.go @@ -140,6 +140,7 @@ type GameplayOptions struct { MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses DisableHunterNavi bool // Disables the Hunter Navi + EnableKaijiEvent bool // Enables the Kaiji event in the Rasta Bar EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar DisableRoad bool // Disables the Hunting Road diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 8f40f7539..f295b37fb 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -186,7 +186,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1102, Value: 5}, {ID: 1103, Value: 2}, {ID: 1104, Value: 10}, - {ID: 1106, Value: 0}, {ID: 1145, Value: 200}, {ID: 1146, Value: 0}, // isTower_invisible {ID: 1147, Value: 0}, // isVenom_playable @@ -458,6 +457,12 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, tuneValue{1037, 1}) } + if s.server.erupeConfig.GameplayOptions.EnableKaijiEvent { + tuneValues = append(tuneValues, tuneValue{1106, 1}) + } else { + tuneValues = append(tuneValues, tuneValue{1106, 0}) + } + if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent { tuneValues = append(tuneValues, tuneValue{1144, 1}) } else { From 2bcd3eb4f0ee2e3f2a859beba747da2158321d97 Mon Sep 17 00:00:00 2001 From: wish Date: Thu, 20 Jul 2023 22:51:26 +1000 Subject: [PATCH 85/99] fix EnumerateShop on G1 --- network/mhfpacket/msg_mhf_enumerate_shop.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/network/mhfpacket/msg_mhf_enumerate_shop.go b/network/mhfpacket/msg_mhf_enumerate_shop.go index 80ad5f432..153095db4 100644 --- a/network/mhfpacket/msg_mhf_enumerate_shop.go +++ b/network/mhfpacket/msg_mhf_enumerate_shop.go @@ -1,11 +1,12 @@ package mhfpacket -import ( - "errors" +import ( + "errors" + _config "erupe-ce/config" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfEnumerateShop represents the MSG_MHF_ENUMERATE_SHOP @@ -31,8 +32,10 @@ func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie m.ShopID = bf.ReadUint32() m.Unk2 = bf.ReadUint16() m.Unk3 = bf.ReadUint8() - m.Unk4 = bf.ReadUint8() - m.Unk5 = bf.ReadUint32() + if _config.ErupeConfig.RealClientMode >= _config.G2 { + m.Unk4 = bf.ReadUint8() + m.Unk5 = bf.ReadUint32() + } return nil } From 123434c374baab7eb786bda912a25e3806b012be Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 21 Jul 2023 20:18:14 +1000 Subject: [PATCH 86/99] add S6 Entrance compatibility --- server/entranceserver/make_resp.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 0e2466865..86256d02c 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -3,12 +3,11 @@ package entranceserver import ( "encoding/binary" "encoding/hex" + "erupe-ce/common/stringsupport" _config "erupe-ce/config" "fmt" "net" - "erupe-ce/common/stringsupport" - "erupe-ce/common/byteframe" "erupe-ce/server/channelserver" ) @@ -53,9 +52,15 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteUint16(uint16(len(si.Channels))) bf.WriteUint8(si.Type) bf.WriteUint8(season) - bf.WriteUint8(si.Recommended) + if s.erupeConfig.RealClientMode >= _config.G1 { + bf.WriteUint8(si.Recommended) + } - if s.erupeConfig.RealClientMode <= _config.GG { + if s.erupeConfig.RealClientMode <= _config.S6 { + combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) + combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) + bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) + } else if s.erupeConfig.RealClientMode <= _config.GG { combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) bf.WriteUint8(uint8(len(combined))) From a66a32936f7d9a6b264ad5ff24291a2996be546a Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 21 Jul 2023 20:54:36 +1000 Subject: [PATCH 87/99] add S6 Savedata compatibility --- network/mhfpacket/msg_mhf_savedata.go | 13 ++++++++----- server/channelserver/handlers_character.go | 15 ++++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/network/mhfpacket/msg_mhf_savedata.go b/network/mhfpacket/msg_mhf_savedata.go index e0fca29c5..cf41416f3 100644 --- a/network/mhfpacket/msg_mhf_savedata.go +++ b/network/mhfpacket/msg_mhf_savedata.go @@ -1,11 +1,12 @@ package mhfpacket -import ( - "errors" +import ( + "errors" + _config "erupe-ce/config" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfSavedata represents the MSG_MHF_SAVEDATA @@ -29,7 +30,9 @@ func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientCon m.AllocMemSize = bf.ReadUint32() m.SaveType = bf.ReadUint8() m.Unk1 = bf.ReadUint32() - m.DataSize = bf.ReadUint32() + if _config.ErupeConfig.RealClientMode >= _config.G1 { + m.DataSize = bf.ReadUint32() + } if m.DataSize == 0 { // seems to be used when DataSize = 0 rather than on savetype? m.RawDataPayload = bf.ReadBytes(uint(m.AllocMemSize)) } else { diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index 0dac950ff..bdbd2f744 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -133,13 +133,18 @@ func (save *CharacterSaveData) Save(s *Session) { save.updateSaveDataWithStruct() - err := save.Compress() - if err != nil { - s.logger.Error("Failed to compress savedata", zap.Error(err)) - return + if _config.ErupeConfig.RealClientMode >= _config.G1 { + err := save.Compress() + if err != nil { + s.logger.Error("Failed to compress savedata", zap.Error(err)) + return + } + } else { + // Saves were not compressed + save.compSave = save.decompSave } - _, err = s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hrp=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7 + _, err := s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hrp=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7 `, save.compSave, save.HRP, save.GR, save.Gender, save.WeaponType, save.WeaponID, save.CharID) if err != nil { s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID)) From 4c1393100035bdc547bebded2cdc488b5c8f0478 Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 21 Jul 2023 21:10:11 +1000 Subject: [PATCH 88/99] fix TerminalLog on S6 --- network/mhfpacket/msg_sys_terminal_log.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/network/mhfpacket/msg_sys_terminal_log.go b/network/mhfpacket/msg_sys_terminal_log.go index 536d35f18..27cc5b1f6 100644 --- a/network/mhfpacket/msg_sys_terminal_log.go +++ b/network/mhfpacket/msg_sys_terminal_log.go @@ -2,6 +2,7 @@ package mhfpacket import ( "errors" + _config "erupe-ce/config" "erupe-ce/common/byteframe" "erupe-ce/network" @@ -37,12 +38,16 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client m.EntryCount = bf.ReadUint16() m.Unk0 = bf.ReadUint16() + values := 15 + if _config.ErupeConfig.RealClientMode <= _config.S6 { + values = 7 + } for i := 0; i < int(m.EntryCount); i++ { e := &TerminalLogEntry{} e.Index = bf.ReadUint32() e.Type1 = bf.ReadUint8() e.Type2 = bf.ReadUint8() - for j := 0; j < 15; j++ { + for j := 0; j < values; j++ { e.Data = append(e.Data, bf.ReadInt16()) } m.Entries = append(m.Entries, e) From b3876f771fb2b9a0b338e761683bc79f8489e569 Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 21 Jul 2023 23:41:56 +1000 Subject: [PATCH 89/99] fix CreateAcquireSemaphore on S6 --- network/mhfpacket/msg_sys_create_acquire_semaphore.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/network/mhfpacket/msg_sys_create_acquire_semaphore.go b/network/mhfpacket/msg_sys_create_acquire_semaphore.go index 9f014ced7..65ec3580d 100644 --- a/network/mhfpacket/msg_sys_create_acquire_semaphore.go +++ b/network/mhfpacket/msg_sys_create_acquire_semaphore.go @@ -2,10 +2,9 @@ package mhfpacket import ( "errors" - "fmt" - - "erupe-ce/common/byteframe" "erupe-ce/common/bfutil" + "erupe-ce/common/byteframe" + _config "erupe-ce/config" "erupe-ce/network" "erupe-ce/network/clientctx" ) @@ -27,8 +26,9 @@ func (m *MsgSysCreateAcquireSemaphore) Opcode() network.PacketID { func (m *MsgSysCreateAcquireSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint16() - m.PlayerCount = bf.ReadUint8() - fmt.Printf("PLAYER COUNT :: %d", m.PlayerCount) + if _config.ErupeConfig.RealClientMode >= _config.G1 { + m.PlayerCount = bf.ReadUint8() + } SemaphoreIDLength := bf.ReadUint8() m.SemaphoreID = string(bfutil.UpToNull(bf.ReadBytes(uint(SemaphoreIDLength)))) return nil From 0b4dca5c453684f66bf876dcabcafbf8a0dd5293 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 03:00:07 +1000 Subject: [PATCH 90/99] fix RP not being consistent between clients --- server/channelserver/handlers_guild.go | 54 +++++++++++++------ .../channelserver/handlers_guild_alliance.go | 6 +-- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 0858d66c2..879969e79 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -63,7 +63,6 @@ type Guild struct { Recruiting bool `db:"recruiting"` FestivalColour FestivalColour `db:"festival_colour"` Souls uint32 `db:"souls"` - Rank uint16 `db:"rank"` AllianceID uint32 `db:"alliance_id"` Icon *GuildIcon `db:"icon"` @@ -116,6 +115,35 @@ func (gi *GuildIcon) Value() (valuer driver.Value, err error) { return json.Marshal(gi) } +func (g *Guild) Rank() uint16 { + rpMap := []uint32{ + 24, 48, 96, 144, 192, 240, 288, 360, 432, + 504, 600, 696, 792, 888, 984, 1080, 1200, + } + if _config.ErupeConfig.RealClientMode <= _config.Z2 { + rpMap = []uint32{ + 3500, 6000, 8500, 11000, 13500, 16000, 20000, 24000, 28000, + 33000, 38000, 43000, 48000, 55000, 70000, 90000, 120000, + } + } + for i, u := range rpMap { + if g.RankRP < u { + if _config.ErupeConfig.RealClientMode <= _config.S6 && i >= 12 { + return 12 + } else if _config.ErupeConfig.RealClientMode <= _config.G32 && i >= 14 { + return 14 + } + return uint16(i) + } + } + if _config.ErupeConfig.RealClientMode <= _config.S6 { + return 12 + } else if _config.ErupeConfig.RealClientMode <= _config.G32 { + return 14 + } + return 17 +} + const guildInfoSelectQuery = ` SELECT g.id, @@ -138,14 +166,6 @@ SELECT recruiting, COALESCE((SELECT team FROM festa_registrations fr WHERE fr.guild_id = g.id), 'none') AS festival_colour, (SELECT SUM(souls) FROM guild_characters gc WHERE gc.guild_id = g.id) AS souls, - CASE - WHEN rank_rp <= 48 THEN rank_rp/24 - WHEN rank_rp <= 288 THEN rank_rp/48+1 - WHEN rank_rp <= 504 THEN rank_rp/72+3 - WHEN rank_rp <= 1080 THEN (rank_rp-24)/96+5 - WHEN rank_rp < 1200 THEN 16 - ELSE 17 - END rank, COALESCE(( SELECT id FROM guild_alliances ga WHERE ga.parent_id = g.id OR @@ -912,7 +932,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(guild.ID) bf.WriteUint32(guild.LeaderCharID) - bf.WriteUint16(guild.Rank) + bf.WriteUint16(guild.Rank()) bf.WriteUint16(guild.MemberCount) bf.WriteUint8(guild.MainMotto) @@ -966,11 +986,11 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint32(guild.PugiOutfits) - if guild.Rank >= 3 { + if guild.Rank() >= 3 { bf.WriteUint8(40) - } else if guild.Rank >= 7 { + } else if guild.Rank() >= 7 { bf.WriteUint8(50) - } else if guild.Rank >= 10 { + } else if guild.Rank() >= 10 { bf.WriteUint8(60) } else { bf.WriteUint8(30) @@ -1008,7 +1028,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { } else { bf.WriteUint16(0) } - bf.WriteUint16(alliance.ParentGuild.Rank) + bf.WriteUint16(alliance.ParentGuild.Rank()) bf.WriteUint16(alliance.ParentGuild.MemberCount) ps.Uint16(bf, alliance.ParentGuild.Name, true) ps.Uint16(bf, alliance.ParentGuild.LeaderName, true) @@ -1020,7 +1040,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { } else { bf.WriteUint16(0) } - bf.WriteUint16(alliance.SubGuild1.Rank) + bf.WriteUint16(alliance.SubGuild1.Rank()) bf.WriteUint16(alliance.SubGuild1.MemberCount) ps.Uint16(bf, alliance.SubGuild1.Name, true) ps.Uint16(bf, alliance.SubGuild1.LeaderName, true) @@ -1033,7 +1053,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { } else { bf.WriteUint16(0) } - bf.WriteUint16(alliance.SubGuild2.Rank) + bf.WriteUint16(alliance.SubGuild2.Rank()) bf.WriteUint16(alliance.SubGuild2.MemberCount) ps.Uint16(bf, alliance.SubGuild2.Name, true) ps.Uint16(bf, alliance.SubGuild2.LeaderName, true) @@ -1309,7 +1329,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(guild.LeaderCharID) bf.WriteUint16(guild.MemberCount) bf.WriteUint16(0x0000) // Unk - bf.WriteUint16(guild.Rank) + bf.WriteUint16(guild.Rank()) bf.WriteUint32(uint32(guild.CreatedAt.Unix())) ps.Uint8(bf, guild.Name, true) ps.Uint8(bf, guild.LeaderName, true) diff --git a/server/channelserver/handlers_guild_alliance.go b/server/channelserver/handlers_guild_alliance.go index fbb285e0a..f27d67026 100644 --- a/server/channelserver/handlers_guild_alliance.go +++ b/server/channelserver/handlers_guild_alliance.go @@ -209,14 +209,14 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint32(alliance.ParentGuildID) bf.WriteUint32(alliance.ParentGuild.LeaderCharID) - bf.WriteUint16(alliance.ParentGuild.Rank) + bf.WriteUint16(alliance.ParentGuild.Rank()) bf.WriteUint16(alliance.ParentGuild.MemberCount) ps.Uint16(bf, alliance.ParentGuild.Name, true) ps.Uint16(bf, alliance.ParentGuild.LeaderName, true) if alliance.SubGuild1ID > 0 { bf.WriteUint32(alliance.SubGuild1ID) bf.WriteUint32(alliance.SubGuild1.LeaderCharID) - bf.WriteUint16(alliance.SubGuild1.Rank) + bf.WriteUint16(alliance.SubGuild1.Rank()) bf.WriteUint16(alliance.SubGuild1.MemberCount) ps.Uint16(bf, alliance.SubGuild1.Name, true) ps.Uint16(bf, alliance.SubGuild1.LeaderName, true) @@ -224,7 +224,7 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { if alliance.SubGuild2ID > 0 { bf.WriteUint32(alliance.SubGuild2ID) bf.WriteUint32(alliance.SubGuild2.LeaderCharID) - bf.WriteUint16(alliance.SubGuild2.Rank) + bf.WriteUint16(alliance.SubGuild2.Rank()) bf.WriteUint16(alliance.SubGuild2.MemberCount) ps.Uint16(bf, alliance.SubGuild2.Name, true) ps.Uint16(bf, alliance.SubGuild2.LeaderName, true) From c3ee5ef7598b76de82c910b30dabb69d648a8755 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 13:34:29 +1000 Subject: [PATCH 91/99] rewrite TransitMessage Find Party --- server/channelserver/handlers.go | 89 +++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 9c25638b5..3fc1cd976 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -6,6 +6,7 @@ import ( "erupe-ce/common/mhfcourse" ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" + _config "erupe-ce/config" "fmt" "io" "net" @@ -447,48 +448,78 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { } } case 4: // Find Party + type FindPartyParams struct { + StagePrefix string + RankRestriction uint16 + Targets []uint16 + } + findPartyParams := FindPartyParams{} bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) - setting := bf.ReadUint8() + numParams := int(bf.ReadUint8()) maxResults := bf.ReadUint16() - bf.Seek(2, 1) - partyType := bf.ReadUint16() - rankRestriction := uint16(0) - if setting >= 2 { - bf.Seek(2, 1) - rankRestriction = bf.ReadUint16() - } - targets := make([]uint16, 4) - if setting >= 3 { - bf.Seek(1, 1) - lenTargets := int(bf.ReadUint8()) - for i := 0; i < lenTargets; i++ { - targets[i] = bf.ReadUint16() + for i := 0; i < numParams; i++ { + switch bf.ReadUint8() { + case 0: + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + findPartyParams.RankRestriction = bf.ReadUint16() + } else { + findPartyParams.RankRestriction = uint16(bf.ReadInt8()) + } + } + case 1: + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + findPartyParams.Targets = append(findPartyParams.Targets, bf.ReadUint16()) + } else { + findPartyParams.Targets = append(findPartyParams.Targets, uint16(bf.ReadInt8())) + } + } + case 2: + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + var value int16 + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + value = bf.ReadInt16() + } else { + value = int16(bf.ReadInt8()) + } + switch value { + case 0: // Public Bar + findPartyParams.StagePrefix = "sl2Ls210" + case 1: // Tokotoko Partnya + findPartyParams.StagePrefix = "sl2Ls463" + case 2: // Hunting Prowess Match + findPartyParams.StagePrefix = "sl2Ls286" + case 3: // Volpakkun Together + findPartyParams.StagePrefix = "sl2Ls465" + case 5: // Quick Party + // Unk + } + } } } - var stagePrefix string - switch partyType { - case 0: // Public Bar - stagePrefix = "sl2Ls210" - case 1: // Tokotoko Partnya - stagePrefix = "sl2Ls463" - case 2: // Hunting Prowess Match - stagePrefix = "sl2Ls286" - case 3: // Volpakkun Together - stagePrefix = "sl2Ls465" - case 5: // Quick Party - // Unk - } for _, c := range s.server.Channels { for _, stage := range c.stages { if count == maxResults { break } - if strings.HasPrefix(stage.id, stagePrefix) { + if strings.HasPrefix(stage.id, findPartyParams.StagePrefix) { sb3 := byteframe.NewByteFrameFromBytes(stage.rawBinaryData[stageBinaryKey{1, 3}]) sb3.Seek(4, 0) stageRankRestriction := sb3.ReadUint16() stageTarget := sb3.ReadUint16() - if rankRestriction != 0xFFFF && stageRankRestriction < rankRestriction { + if stageRankRestriction > findPartyParams.RankRestriction { + continue + } + if len(findPartyParams.Targets) > 0 { + for _, target := range findPartyParams.Targets { + if target == stageTarget { + break + } + } continue } count++ From c625f595e3c201b7764182966d3f0af07de9e5db Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 13:40:01 +1000 Subject: [PATCH 92/99] set default StagePrefix for Find Party --- server/channelserver/handlers.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 3fc1cd976..04e08a8e8 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -453,7 +453,9 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { RankRestriction uint16 Targets []uint16 } - findPartyParams := FindPartyParams{} + findPartyParams := FindPartyParams{ + StagePrefix: "sl2Ls210", + } bf := byteframe.NewByteFrameFromBytes(pkt.MessageData) numParams := int(bf.ReadUint8()) maxResults := bf.ReadUint16() From cc428d85d35ec012ab7fe0f5ab3a83aac24f2126 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 13:49:30 +1000 Subject: [PATCH 93/99] read additional Find Party data into struct --- server/channelserver/handlers.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 04e08a8e8..81cd1838a 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -452,6 +452,9 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { StagePrefix string RankRestriction uint16 Targets []uint16 + Unk0 []uint16 + Unk1 []uint16 + QuestID []uint16 } findPartyParams := FindPartyParams{ StagePrefix: "sl2Ls210", @@ -501,6 +504,33 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { // Unk } } + case 3: // Unknown + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + findPartyParams.Unk0 = append(findPartyParams.Unk0, bf.ReadUint16()) + } else { + findPartyParams.Unk0 = append(findPartyParams.Unk0, uint16(bf.ReadInt8())) + } + } + case 4: // Looking for n or already have n + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + findPartyParams.Unk1 = append(findPartyParams.Unk1, bf.ReadUint16()) + } else { + findPartyParams.Unk1 = append(findPartyParams.Unk1, uint16(bf.ReadInt8())) + } + } + case 5: + values := int(bf.ReadUint8()) + for i := 0; i < values; i++ { + if _config.ErupeConfig.RealClientMode >= _config.Z1 { + findPartyParams.QuestID = append(findPartyParams.QuestID, bf.ReadUint16()) + } else { + findPartyParams.QuestID = append(findPartyParams.QuestID, uint16(bf.ReadInt8())) + } + } } } for _, c := range s.server.Channels { From dbedab4d33b8712d5feb942349239c23808662e0 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 16:47:44 +1000 Subject: [PATCH 94/99] add ClientMode support based on Forward.4 --- network/crypt_conn.go | 8 +++++--- network/mhfpacket/msg_mhf_acquire_cafe_item.go | 9 +++++++-- network/mhfpacket/msg_sys_terminal_log.go | 2 +- server/channelserver/handlers_guild.go | 4 ++++ server/entranceserver/make_resp.go | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/network/crypt_conn.go b/network/crypt_conn.go index 439e9e3a0..3a952ee19 100644 --- a/network/crypt_conn.go +++ b/network/crypt_conn.go @@ -47,8 +47,10 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) { return nil, err } + dataSize := uint32(cph.DataSize) + (uint32(cph.Pf0-0x03) * 0x1000) + // Now read the encrypted packet body after getting its size from the header. - encryptedPacketBody := make([]byte, cph.DataSize) + encryptedPacketBody := make([]byte, dataSize) _, err = io.ReadFull(cc.conn, encryptedPacketBody) if err != nil { return nil, err @@ -56,7 +58,7 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) { // Update the key rotation before decrypting. if cph.KeyRotDelta != 0 { - cc.readKeyRot = (uint32(cph.KeyRotDelta) * (cc.readKeyRot + 1)) + cc.readKeyRot = uint32(cph.KeyRotDelta) * (cc.readKeyRot + 1) } out, combinedCheck, check0, check1, check2 := crypto.Decrypt(encryptedPacketBody, cc.readKeyRot, nil) @@ -94,7 +96,7 @@ func (cc *CryptConn) SendPacket(data []byte) error { keyRotDelta := byte(3) if keyRotDelta != 0 { - cc.sendKeyRot = (uint32(keyRotDelta) * (cc.sendKeyRot + 1)) + cc.sendKeyRot = uint32(keyRotDelta) * (cc.sendKeyRot + 1) } // Encrypt the data diff --git a/network/mhfpacket/msg_mhf_acquire_cafe_item.go b/network/mhfpacket/msg_mhf_acquire_cafe_item.go index 8dcad0b53..04e603a44 100644 --- a/network/mhfpacket/msg_mhf_acquire_cafe_item.go +++ b/network/mhfpacket/msg_mhf_acquire_cafe_item.go @@ -2,10 +2,11 @@ package mhfpacket import ( "errors" + _config "erupe-ce/config" + "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" - "erupe-ce/common/byteframe" ) // MsgMhfAcquireCafeItem represents the MSG_MHF_ACQUIRE_CAFE_ITEM @@ -30,7 +31,11 @@ func (m *MsgMhfAcquireCafeItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl m.ItemType = bf.ReadUint16() m.ItemID = bf.ReadUint16() m.Quant = bf.ReadUint16() - m.PointCost = bf.ReadUint32() + if _config.ErupeConfig.RealClientMode >= _config.G1 { + m.PointCost = bf.ReadUint32() + } else { + m.PointCost = uint32(bf.ReadUint16()) + } m.Unk0 = bf.ReadUint16() return nil } diff --git a/network/mhfpacket/msg_sys_terminal_log.go b/network/mhfpacket/msg_sys_terminal_log.go index 27cc5b1f6..43bf43dd3 100644 --- a/network/mhfpacket/msg_sys_terminal_log.go +++ b/network/mhfpacket/msg_sys_terminal_log.go @@ -39,7 +39,7 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client m.Unk0 = bf.ReadUint16() values := 15 - if _config.ErupeConfig.RealClientMode <= _config.S6 { + if _config.ErupeConfig.RealClientMode <= _config.F4 { values = 7 } for i := 0; i < int(m.EntryCount); i++ { diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 879969e79..3c28a7bed 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -130,6 +130,8 @@ func (g *Guild) Rank() uint16 { if g.RankRP < u { if _config.ErupeConfig.RealClientMode <= _config.S6 && i >= 12 { return 12 + } else if _config.ErupeConfig.RealClientMode <= _config.F4 && i >= 13 { + return 13 } else if _config.ErupeConfig.RealClientMode <= _config.G32 && i >= 14 { return 14 } @@ -138,6 +140,8 @@ func (g *Guild) Rank() uint16 { } if _config.ErupeConfig.RealClientMode <= _config.S6 { return 12 + } else if _config.ErupeConfig.RealClientMode <= _config.F4 { + return 13 } else if _config.ErupeConfig.RealClientMode <= _config.G32 { return 14 } diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 86256d02c..3d64dd9f2 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -56,7 +56,7 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteUint8(si.Recommended) } - if s.erupeConfig.RealClientMode <= _config.S6 { + if s.erupeConfig.RealClientMode <= _config.F4 { combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) From aad9425a73f9838c558522d5f101e3947ae9eaf0 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 18:22:21 +1000 Subject: [PATCH 95/99] guess Forward.5 compatibility --- network/mhfpacket/msg_sys_terminal_log.go | 2 +- server/channelserver/handlers_guild.go | 4 ++-- server/entranceserver/make_resp.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/network/mhfpacket/msg_sys_terminal_log.go b/network/mhfpacket/msg_sys_terminal_log.go index 43bf43dd3..079ba5bd6 100644 --- a/network/mhfpacket/msg_sys_terminal_log.go +++ b/network/mhfpacket/msg_sys_terminal_log.go @@ -39,7 +39,7 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client m.Unk0 = bf.ReadUint16() values := 15 - if _config.ErupeConfig.RealClientMode <= _config.F4 { + if _config.ErupeConfig.RealClientMode <= _config.F5 { values = 7 } for i := 0; i < int(m.EntryCount); i++ { diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 3c28a7bed..5fdd2dac1 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -130,7 +130,7 @@ func (g *Guild) Rank() uint16 { if g.RankRP < u { if _config.ErupeConfig.RealClientMode <= _config.S6 && i >= 12 { return 12 - } else if _config.ErupeConfig.RealClientMode <= _config.F4 && i >= 13 { + } else if _config.ErupeConfig.RealClientMode <= _config.F5 && i >= 13 { return 13 } else if _config.ErupeConfig.RealClientMode <= _config.G32 && i >= 14 { return 14 @@ -140,7 +140,7 @@ func (g *Guild) Rank() uint16 { } if _config.ErupeConfig.RealClientMode <= _config.S6 { return 12 - } else if _config.ErupeConfig.RealClientMode <= _config.F4 { + } else if _config.ErupeConfig.RealClientMode <= _config.F5 { return 13 } else if _config.ErupeConfig.RealClientMode <= _config.G32 { return 14 diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 3d64dd9f2..619296fdb 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -56,7 +56,7 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { bf.WriteUint8(si.Recommended) } - if s.erupeConfig.RealClientMode <= _config.F4 { + if s.erupeConfig.RealClientMode <= _config.F5 { combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) From da3686b6536d476273536fb51640ec02ffcef344 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 19:00:25 +1000 Subject: [PATCH 96/99] fix encryption not working with S6 --- network/crypt_conn.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/network/crypt_conn.go b/network/crypt_conn.go index 3a952ee19..2fc302b18 100644 --- a/network/crypt_conn.go +++ b/network/crypt_conn.go @@ -3,6 +3,7 @@ package network import ( "encoding/hex" "errors" + _config "erupe-ce/config" "fmt" "io" "net" @@ -47,10 +48,15 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) { return nil, err } - dataSize := uint32(cph.DataSize) + (uint32(cph.Pf0-0x03) * 0x1000) - // Now read the encrypted packet body after getting its size from the header. - encryptedPacketBody := make([]byte, dataSize) + var encryptedPacketBody []byte + + // Don't know when support for this was added, works in Forward.4, doesn't work in Season 6.0 + if _config.ErupeConfig.RealClientMode < _config.F1 { + encryptedPacketBody = make([]byte, cph.DataSize) + } else { + encryptedPacketBody = make([]byte, uint32(cph.DataSize)+(uint32(cph.Pf0-0x03)*0x1000)) + } _, err = io.ReadFull(cc.conn, encryptedPacketBody) if err != nil { return nil, err From e6393d73dc993515a5e7d7a9cea9e28ed0161e13 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 21:11:53 +1000 Subject: [PATCH 97/99] fix and structise InfoFesta --- server/channelserver/handlers_festa.go | 108 +++++++++++++++++++------ 1 file changed, 82 insertions(+), 26 deletions(-) diff --git a/server/channelserver/handlers_festa.go b/server/channelserver/handlers_festa.go index 155cee3d8..df972c0a9 100644 --- a/server/channelserver/handlers_festa.go +++ b/server/channelserver/handlers_festa.go @@ -1,7 +1,6 @@ package channelserver import ( - "encoding/hex" "erupe-ce/common/byteframe" ps "erupe-ce/common/pascalstring" "erupe-ce/common/token" @@ -140,13 +139,26 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 { return timestamps } -type Trial struct { +type FestaTrial struct { ID uint32 `db:"id"` - Objective uint8 `db:"objective"` + Objective uint16 `db:"objective"` GoalID uint32 `db:"goal_id"` TimesReq uint16 `db:"times_req"` Locale uint16 `db:"locale_req"` Reward uint16 `db:"reward"` + Monopoly uint16 + Unk uint16 +} + +type FestaReward struct { + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 + Unk3 uint16 + Unk4 uint16 + Unk5 uint16 + Unk6 uint16 + Unk7 uint8 } func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { @@ -190,36 +202,70 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(blueSouls) bf.WriteUint32(redSouls) + var trials []FestaTrial + var trial FestaTrial rows, _ = s.server.db.Queryx("SELECT * FROM festa_trials") - trialData := byteframe.NewByteFrame() - var count uint16 for rows.Next() { - trial := &Trial{} err := rows.StructScan(&trial) if err != nil { continue } - count++ - trialData.WriteUint32(trial.ID) - trialData.WriteUint8(0) // Unk - trialData.WriteUint8(trial.Objective) - trialData.WriteUint32(trial.GoalID) - trialData.WriteUint16(trial.TimesReq) - trialData.WriteUint16(trial.Locale) - trialData.WriteUint16(trial.Reward) - trialData.WriteUint8(0xFF) // Unk - trialData.WriteUint8(0xFF) // MonopolyState - trialData.WriteUint16(0) // Unk + trials = append(trials, trial) + } + bf.WriteUint16(uint16(len(trials))) + for _, trial := range trials { + bf.WriteUint32(trial.ID) + bf.WriteUint16(trial.Objective) + bf.WriteUint32(trial.GoalID) + bf.WriteUint16(trial.TimesReq) + bf.WriteUint16(trial.Locale) + bf.WriteUint16(trial.Reward) + trial.Monopoly = 0xFFFF // NYI + bf.WriteUint16(trial.Monopoly) + bf.WriteUint16(trial.Unk) } - bf.WriteUint16(count) - bf.WriteBytes(trialData.Data()) - // Static bonus rewards - rewards, _ := hex.DecodeString("001901000007015E05F000000000000100000703E81B6300000000010100000C03E8000000000000000100000D0000000000000000000100000100000000000000000002000007015E05F000000000000200000703E81B6300000000010200000C03E8000000000000000200000D0000000000000000000200000400000000000000000003000007015E05F000000000000300000703E81B6300000000010300000C03E8000000000000000300000D0000000000000000000300000100000000000000000004000007015E05F000000000000400000703E81B6300000000010400000C03E8000000000000000400000D0000000000000000000400000400000000000000000005000007015E05F000000000000500000703E81B6300000000010500000C03E8000000000000000500000D00000000000000000005000001000000000000000000") - bf.WriteBytes(rewards) + rewards := []FestaReward{ + {1, 0, 7, 350, 1520, 0, 0, 0}, + {1, 0, 7, 1000, 7011, 0, 0, 1}, + {1, 0, 12, 1000, 0, 0, 0, 0}, + {1, 0, 13, 0, 0, 0, 0, 0}, + {1, 0, 1, 0, 0, 0, 0, 0}, + {2, 0, 7, 350, 1520, 0, 0, 0}, + {2, 0, 7, 1000, 7011, 0, 0, 1}, + {2, 0, 12, 1000, 0, 0, 0, 0}, + {2, 0, 13, 0, 0, 0, 0, 0}, + {2, 0, 4, 0, 0, 0, 0, 0}, + {3, 0, 7, 350, 1520, 0, 0, 0}, + {3, 0, 7, 1000, 7011, 0, 0, 1}, + {3, 0, 12, 1000, 0, 0, 0, 0}, + {3, 0, 13, 0, 0, 0, 0, 0}, + {3, 0, 1, 0, 0, 0, 0, 0}, + {4, 0, 7, 350, 1520, 0, 0, 0}, + {4, 0, 7, 1000, 7011, 0, 0, 1}, + {4, 0, 12, 1000, 0, 0, 0, 0}, + {4, 0, 13, 0, 0, 0, 0, 0}, + {4, 0, 4, 0, 0, 0, 0, 0}, + {5, 0, 7, 350, 1520, 0, 0, 0}, + {5, 0, 7, 1000, 7011, 0, 0, 1}, + {5, 0, 12, 1000, 0, 0, 0, 0}, + {5, 0, 13, 0, 0, 0, 0, 0}, + {5, 0, 1, 0, 0, 0, 0, 0}, + } + bf.WriteUint16(uint16(len(rewards))) + for _, reward := range rewards { + bf.WriteUint8(reward.Unk0) + bf.WriteUint8(reward.Unk1) + bf.WriteUint16(reward.Unk2) + bf.WriteUint16(reward.Unk3) + bf.WriteUint16(reward.Unk4) + bf.WriteUint16(reward.Unk5) + bf.WriteUint16(reward.Unk6) + bf.WriteUint8(reward.Unk7) + } - bf.WriteUint16(0x0001) - bf.WriteUint32(0xD4C001F4) + bf.WriteUint32(120000) + bf.WriteUint16(500) categoryWinners := uint16(0) // NYI bf.WriteUint16(categoryWinners) @@ -239,8 +285,18 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { ps.Uint8(bf, "", true) // Guild Name } - d, _ := hex.DecodeString("000000000000000100001388000007D0000003E800000064012C00C8009600640032") - bf.WriteBytes(d) + // Unknown values + bf.WriteUint32(1) + bf.WriteUint32(5000) + bf.WriteUint32(2000) + bf.WriteUint32(1000) + bf.WriteUint32(100) + bf.WriteUint16(300) + bf.WriteUint16(200) + bf.WriteUint16(150) + bf.WriteUint16(100) + bf.WriteUint16(50) + ps.Uint16(bf, "", false) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } From 769f989c918649ee92366743017f65629dd13139 Mon Sep 17 00:00:00 2001 From: wish Date: Sat, 22 Jul 2023 23:12:26 +1000 Subject: [PATCH 98/99] add MaximumFP option, hide null Festa Armor --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers_festa.go | 35 +++++++++++++------------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/config.json b/config.json index 6e69bb0a8..e752a93f1 100644 --- a/config.json +++ b/config.json @@ -39,6 +39,7 @@ "FeaturedWeapons": 1, "MaximumNP": 100000, "MaximumRP": 50000, + "MaximumFP": 120000, "DisableLoginBoost": false, "DisableBoostTime": false, "BoostTimeDuration": 120, diff --git a/config/config.go b/config/config.go index c02296b26..78ddd9e8a 100644 --- a/config/config.go +++ b/config/config.go @@ -124,6 +124,7 @@ type GameplayOptions struct { FeaturedWeapons int // Number of Active Feature weapons to generate daily MaximumNP int // Maximum number of NP held by a player MaximumRP uint16 // Maximum number of RP held by a player + MaximumFP uint32 // Maximum number of FP held by a player DisableLoginBoost bool // Disables the Login Boost system DisableBoostTime bool // Disables the daily NetCafe Boost Time BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for diff --git a/server/channelserver/handlers_festa.go b/server/channelserver/handlers_festa.go index df972c0a9..0f590b5d9 100644 --- a/server/channelserver/handlers_festa.go +++ b/server/channelserver/handlers_festa.go @@ -151,14 +151,14 @@ type FestaTrial struct { } type FestaReward struct { - Unk0 uint8 - Unk1 uint8 - Unk2 uint16 - Unk3 uint16 - Unk4 uint16 - Unk5 uint16 - Unk6 uint16 - Unk7 uint8 + Unk0 uint8 + Unk1 uint8 + ItemType uint16 + Quantity uint16 + ItemID uint16 + Unk5 uint16 + Unk6 uint16 + Unk7 uint8 } func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { @@ -225,46 +225,47 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(trial.Unk) } + // The Winner and Loser Armor IDs are missing rewards := []FestaReward{ {1, 0, 7, 350, 1520, 0, 0, 0}, {1, 0, 7, 1000, 7011, 0, 0, 1}, {1, 0, 12, 1000, 0, 0, 0, 0}, {1, 0, 13, 0, 0, 0, 0, 0}, - {1, 0, 1, 0, 0, 0, 0, 0}, + //{1, 0, 1, 0, 0, 0, 0, 0}, {2, 0, 7, 350, 1520, 0, 0, 0}, {2, 0, 7, 1000, 7011, 0, 0, 1}, {2, 0, 12, 1000, 0, 0, 0, 0}, {2, 0, 13, 0, 0, 0, 0, 0}, - {2, 0, 4, 0, 0, 0, 0, 0}, + //{2, 0, 4, 0, 0, 0, 0, 0}, {3, 0, 7, 350, 1520, 0, 0, 0}, {3, 0, 7, 1000, 7011, 0, 0, 1}, {3, 0, 12, 1000, 0, 0, 0, 0}, {3, 0, 13, 0, 0, 0, 0, 0}, - {3, 0, 1, 0, 0, 0, 0, 0}, + //{3, 0, 1, 0, 0, 0, 0, 0}, {4, 0, 7, 350, 1520, 0, 0, 0}, {4, 0, 7, 1000, 7011, 0, 0, 1}, {4, 0, 12, 1000, 0, 0, 0, 0}, {4, 0, 13, 0, 0, 0, 0, 0}, - {4, 0, 4, 0, 0, 0, 0, 0}, + //{4, 0, 4, 0, 0, 0, 0, 0}, {5, 0, 7, 350, 1520, 0, 0, 0}, {5, 0, 7, 1000, 7011, 0, 0, 1}, {5, 0, 12, 1000, 0, 0, 0, 0}, {5, 0, 13, 0, 0, 0, 0, 0}, - {5, 0, 1, 0, 0, 0, 0, 0}, + //{5, 0, 1, 0, 0, 0, 0, 0}, } bf.WriteUint16(uint16(len(rewards))) for _, reward := range rewards { bf.WriteUint8(reward.Unk0) bf.WriteUint8(reward.Unk1) - bf.WriteUint16(reward.Unk2) - bf.WriteUint16(reward.Unk3) - bf.WriteUint16(reward.Unk4) + bf.WriteUint16(reward.ItemType) + bf.WriteUint16(reward.Quantity) + bf.WriteUint16(reward.ItemID) bf.WriteUint16(reward.Unk5) bf.WriteUint16(reward.Unk6) bf.WriteUint8(reward.Unk7) } - bf.WriteUint32(120000) + bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MaximumFP) bf.WriteUint16(500) categoryWinners := uint16(0) // NYI From 19e1eae5e2fc3302bd3639c92a642f45ca00bb6c Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 23 Jul 2023 13:27:10 +1000 Subject: [PATCH 99/99] simplify and expand Stage Object indexer --- server/channelserver/sys_stage.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/server/channelserver/sys_stage.go b/server/channelserver/sys_stage.go index b69995724..7b8fb15eb 100644 --- a/server/channelserver/sys_stage.go +++ b/server/channelserver/sys_stage.go @@ -30,7 +30,7 @@ type Stage struct { // Objects objects map[uint32]*Object - objectIndex uint8 + objectIndex uint16 // Map of session -> charID. // These are clients that are CURRENTLY in the stage @@ -56,7 +56,6 @@ func NewStage(ID string) *Stage { clients: make(map[*Session]uint32), reservedClientSlots: make(map[uint32]bool), objects: make(map[uint32]*Object), - objectIndex: 0, rawBinaryData: make(map[stageBinaryKey][]byte), maxPlayers: 4, } @@ -97,16 +96,10 @@ func (s *Stage) isQuest() bool { } func (s *Stage) NextObjectID() uint32 { - s.objectIndex = s.objectIndex + 1 - // Objects beyond 127 do not duplicate correctly - // Indexes 0 and 127 does not update position correctly - if s.objectIndex == 127 { - s.objectIndex = 1 - } + s.objectIndex++ bf := byteframe.NewByteFrame() - bf.WriteUint8(0) - bf.WriteUint8(s.objectIndex) - bf.WriteUint16(0) - obj := uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<24 - return obj + bf.WriteUint16(127) + bf.WriteUint16(s.objectIndex) + bf.Seek(0, 0) + return bf.ReadUint32() }