refactor(config): eliminate ErupeConfig global variable

Replace the mutable global `_config.ErupeConfig` with dependency
injection across 79 files. Config is now threaded through existing
paths: `ClientContext.RealClientMode` for packet encoding, `s.server.
erupeConfig` for channel handlers, and explicit parameters for utility
functions. This removes hidden coupling, enables test parallelism
without global save/restore, and prevents low-level packages from
reaching up to the config layer.

Key changes:
- Enrich ClientContext with RealClientMode for packet files
- Add mode parameter to CryptConn, mhfitem, mhfcourse functions
- Convert handlers_commands init() to lazy sync.Once initialization
- Delete global var, init(), and helper functions from config.go
- Update all tests to pass config explicitly
This commit is contained in:
Houmgaor
2026-02-20 17:07:42 +01:00
parent 8c7e95ce18
commit 5f3c843082
79 changed files with 509 additions and 723 deletions

View File

@@ -1,7 +1,6 @@
package mhfcourse
import (
_config "erupe-ce/config"
"math"
"sort"
"time"
@@ -70,9 +69,9 @@ func CourseExists(ID uint16, c []Course) bool {
}
// GetCourseStruct returns a slice of Course(s) from a rights integer
func GetCourseStruct(rights uint32) ([]Course, uint32) {
func GetCourseStruct(rights uint32, defaultCourses []uint16) ([]Course, uint32) {
var resp []Course
for _, c := range _config.ErupeConfig.DefaultCourses {
for _, c := range defaultCourses {
resp = append(resp, Course{ID: c})
}
s := Courses()

View File

@@ -1,7 +1,6 @@
package mhfcourse
import (
_config "erupe-ce/config"
"math"
"testing"
"time"
@@ -121,14 +120,7 @@ func TestCourseExists_EmptySlice(t *testing.T) {
}
func TestGetCourseStruct(t *testing.T) {
// Save original config and restore after test
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
// Set up test config
_config.ErupeConfig.DefaultCourses = []uint16{1, 2}
defaultCourses := []uint16{1, 2}
tests := []struct {
name string
@@ -164,7 +156,7 @@ func TestGetCourseStruct(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
courses, newRights := GetCourseStruct(tt.rights)
courses, newRights := GetCourseStruct(tt.rights, defaultCourses)
if len(courses) < tt.wantMinLen {
t.Errorf("GetCourseStruct(%d) returned %d courses, want at least %d", tt.rights, len(courses), tt.wantMinLen)
@@ -193,15 +185,8 @@ func TestGetCourseStruct(t *testing.T) {
}
func TestGetCourseStruct_NetcafeCourse(t *testing.T) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{}
// Course 26 (NetCafe) should add course 25
courses, _ := GetCourseStruct(1 << 26)
courses, _ := GetCourseStruct(1<<26, nil)
hasNetcafe := false
hasCafeSP := false
@@ -230,15 +215,8 @@ func TestGetCourseStruct_NetcafeCourse(t *testing.T) {
}
func TestGetCourseStruct_NCourse(t *testing.T) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{}
// Course 9 should add course 30
courses, _ := GetCourseStruct(1 << 9)
courses, _ := GetCourseStruct(1<<9, nil)
hasNCourse := false
hasRealNetcafe := false
@@ -260,15 +238,8 @@ func TestGetCourseStruct_NCourse(t *testing.T) {
}
func TestGetCourseStruct_HidenCourse(t *testing.T) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{}
// Course 10 (Hiden) should add course 31
courses, _ := GetCourseStruct(1 << 10)
courses, _ := GetCourseStruct(1<<10, nil)
hasHiden := false
hasHidenExtra := false
@@ -290,14 +261,7 @@ func TestGetCourseStruct_HidenCourse(t *testing.T) {
}
func TestGetCourseStruct_ExpiryDate(t *testing.T) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{}
courses, _ := GetCourseStruct(1 << 3)
courses, _ := GetCourseStruct(1<<3, nil)
expectedExpiry := time.Date(2030, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC+9", 9*60*60))
@@ -311,14 +275,7 @@ func TestGetCourseStruct_ExpiryDate(t *testing.T) {
}
func TestGetCourseStruct_ReturnsRecalculatedRights(t *testing.T) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{}
courses, newRights := GetCourseStruct(2 + 8 + 32) // courses 1, 3, 5
courses, newRights := GetCourseStruct(2+8+32, nil) // courses 1, 3, 5
// Calculate expected rights from returned courses
var expectedRights uint32
@@ -363,17 +320,11 @@ func BenchmarkCourseExists(b *testing.B) {
}
func BenchmarkGetCourseStruct(b *testing.B) {
// Save original config
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
defer func() {
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
}()
_config.ErupeConfig.DefaultCourses = []uint16{1, 2}
defaultCourses := []uint16{1, 2}
rights := uint32(2 + 8 + 32 + 128 + 512)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = GetCourseStruct(rights)
_, _ = GetCourseStruct(rights, defaultCourses)
}
}

View File

@@ -3,7 +3,7 @@ package mhfitem
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/token"
_config "erupe-ce/config"
"erupe-ce/config"
)
// MHFItem represents a single item identified by its in-game item ID.
@@ -113,7 +113,7 @@ func SerializeWarehouseItems(i []MHFItemStack) []byte {
// ReadWarehouseEquipment deserializes an MHFEquipment from a ByteFrame. The
// binary layout varies by game version: sigils are present from G1 onward and
// an additional field is present from Z1 onward.
func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
func ReadWarehouseEquipment(bf *byteframe.ByteFrame, mode _config.Mode) MHFEquipment {
var equipment MHFEquipment
equipment.Decorations = make([]MHFItem, 3)
equipment.Sigils = make([]MHFSigil, 3)
@@ -131,7 +131,7 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
for i := 0; i < 3; i++ {
equipment.Decorations[i].ItemID = bf.ReadUint16()
}
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if mode >= _config.G1 {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
equipment.Sigils[i].Effects[j].ID = bf.ReadUint16()
@@ -145,14 +145,14 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
equipment.Sigils[i].Unk3 = bf.ReadUint8()
}
}
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if mode >= _config.Z1 {
equipment.Unk1 = bf.ReadUint16()
}
return equipment
}
// ToBytes serializes the equipment to its binary protocol representation.
func (e MHFEquipment) ToBytes() []byte {
func (e MHFEquipment) ToBytes(mode _config.Mode) []byte {
bf := byteframe.NewByteFrame()
bf.WriteUint32(e.WarehouseID)
bf.WriteUint8(e.ItemType)
@@ -162,7 +162,7 @@ func (e MHFEquipment) ToBytes() []byte {
for i := 0; i < 3; i++ {
bf.WriteUint16(e.Decorations[i].ItemID)
}
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if mode >= _config.G1 {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
bf.WriteUint16(e.Sigils[i].Effects[j].ID)
@@ -176,7 +176,7 @@ func (e MHFEquipment) ToBytes() []byte {
bf.WriteUint8(e.Sigils[i].Unk3)
}
}
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if mode >= _config.Z1 {
bf.WriteUint16(e.Unk1)
}
return bf.Data()
@@ -184,12 +184,12 @@ func (e MHFEquipment) ToBytes() []byte {
// SerializeWarehouseEquipment serializes a slice of equipment with a uint16
// count header for transmission in warehouse response packets.
func SerializeWarehouseEquipment(i []MHFEquipment) []byte {
func SerializeWarehouseEquipment(i []MHFEquipment, mode _config.Mode) []byte {
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(len(i)))
bf.WriteUint16(0) // Unused
for _, j := range i {
bf.WriteBytes(j.ToBytes())
bf.WriteBytes(j.ToBytes(mode))
}
return bf.Data()
}

View File

@@ -119,11 +119,11 @@ func TestSerializeWarehouseItems_Empty(t *testing.T) {
func TestDiffItemStacks(t *testing.T) {
tests := []struct {
name string
old []MHFItemStack
update []MHFItemStack
wantLen int
checkFn func(t *testing.T, result []MHFItemStack)
name string
old []MHFItemStack
update []MHFItemStack
wantLen int
checkFn func(t *testing.T, result []MHFItemStack)
}{
{
name: "update existing quantity",
@@ -210,12 +210,7 @@ func TestDiffItemStacks(t *testing.T) {
}
func TestReadWarehouseEquipment(t *testing.T) {
// Save original config
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
_config.ErupeConfig.RealClientMode = _config.Z1
mode := _config.Z1
bf := byteframe.NewByteFrame()
bf.WriteUint32(12345) // WarehouseID
@@ -248,7 +243,7 @@ func TestReadWarehouseEquipment(t *testing.T) {
bf.WriteUint16(9999)
_, _ = bf.Seek(0, 0)
equipment := ReadWarehouseEquipment(bf)
equipment := ReadWarehouseEquipment(bf, mode)
if equipment.WarehouseID != 12345 {
t.Errorf("WarehouseID = %d, want 12345", equipment.WarehouseID)
@@ -274,12 +269,7 @@ func TestReadWarehouseEquipment(t *testing.T) {
}
func TestReadWarehouseEquipment_ZeroWarehouseID(t *testing.T) {
// Save original config
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
_config.ErupeConfig.RealClientMode = _config.Z1
mode := _config.Z1
bf := byteframe.NewByteFrame()
bf.WriteUint32(0) // WarehouseID = 0
@@ -304,7 +294,7 @@ func TestReadWarehouseEquipment_ZeroWarehouseID(t *testing.T) {
bf.WriteUint16(0)
_, _ = bf.Seek(0, 0)
equipment := ReadWarehouseEquipment(bf)
equipment := ReadWarehouseEquipment(bf, mode)
if equipment.WarehouseID == 0 {
t.Error("WarehouseID should be replaced with random value when input is 0")
@@ -312,12 +302,7 @@ func TestReadWarehouseEquipment_ZeroWarehouseID(t *testing.T) {
}
func TestMHFEquipment_ToBytes(t *testing.T) {
// Save original config
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
_config.ErupeConfig.RealClientMode = _config.Z1
mode := _config.Z1
equipment := MHFEquipment{
WarehouseID: 12345,
@@ -333,9 +318,9 @@ func TestMHFEquipment_ToBytes(t *testing.T) {
equipment.Sigils[i].Effects = make([]MHFSigilEffect, 3)
}
data := equipment.ToBytes()
data := equipment.ToBytes(mode)
bf := byteframe.NewByteFrameFromBytes(data)
readEquipment := ReadWarehouseEquipment(bf)
readEquipment := ReadWarehouseEquipment(bf, mode)
if readEquipment.WarehouseID != equipment.WarehouseID {
t.Errorf("WarehouseID = %d, want %d", readEquipment.WarehouseID, equipment.WarehouseID)
@@ -352,12 +337,7 @@ func TestMHFEquipment_ToBytes(t *testing.T) {
}
func TestSerializeWarehouseEquipment(t *testing.T) {
// Save original config
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
_config.ErupeConfig.RealClientMode = _config.Z1
mode := _config.Z1
equipment := []MHFEquipment{
{
@@ -383,7 +363,7 @@ func TestSerializeWarehouseEquipment(t *testing.T) {
}
}
data := SerializeWarehouseEquipment(equipment)
data := SerializeWarehouseEquipment(equipment, mode)
bf := byteframe.NewByteFrameFromBytes(data)
count := bf.ReadUint16()
@@ -393,12 +373,7 @@ func TestSerializeWarehouseEquipment(t *testing.T) {
}
func TestMHFEquipment_RoundTrip(t *testing.T) {
// Test that we can write and read back the same equipment
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
_config.ErupeConfig.RealClientMode = _config.Z1
mode := _config.Z1
original := MHFEquipment{
WarehouseID: 99999,
@@ -419,11 +394,11 @@ func TestMHFEquipment_RoundTrip(t *testing.T) {
}
// Write to bytes
data := original.ToBytes()
data := original.ToBytes(mode)
// Read back
bf := byteframe.NewByteFrameFromBytes(data)
recovered := ReadWarehouseEquipment(bf)
recovered := ReadWarehouseEquipment(bf, mode)
// Compare
if recovered.WarehouseID != original.WarehouseID {

View File

@@ -1,12 +1,9 @@
package _config
import (
"fmt"
"log"
"net"
"os"
"strings"
"time"
"github.com/spf13/viper"
)
@@ -308,36 +305,6 @@ func (c *EntranceChannelInfo) IsEnabled() bool {
return *c.Enabled
}
var ErupeConfig *Config
func init() {
var err error
ErupeConfig, err = LoadConfig()
if err != nil {
// In test environments or when config.toml is missing, use defaults
ErupeConfig = &Config{
ClientMode: "ZZ",
RealClientMode: ZZ,
}
// Only call preventClose if it's not a test environment
if !isTestEnvironment() {
preventClose(fmt.Sprintf("Failed to load config: %s", err.Error()))
}
}
}
func isTestEnvironment() bool {
// Check if we're running under test
for _, arg := range os.Args {
if arg == "-test.v" || arg == "-test.run" || arg == "-test.timeout" {
return true
}
if strings.Contains(arg, "test") {
return true
}
}
return false
}
// getOutboundIP4 gets the preferred outbound ip4 of this machine
// From https://stackoverflow.com/a/37382208
@@ -399,19 +366,3 @@ func LoadConfig() (*Config, error) {
return c, nil
}
func preventClose(text string) {
if ErupeConfig != nil && ErupeConfig.DisableSoftCrash {
os.Exit(0)
}
fmt.Println("\nFailed to start Erupe:\n" + text)
go wait()
fmt.Println("\nPress Enter/Return to exit...")
_, _ = fmt.Scanln()
os.Exit(0)
}
func wait() {
for {
time.Sleep(time.Millisecond * 100)
}
}

View File

@@ -94,14 +94,6 @@ func TestModeConstants(t *testing.T) {
}
}
// TestIsTestEnvironment tests the isTestEnvironment function
func TestIsTestEnvironment(t *testing.T) {
result := isTestEnvironment()
if !result {
t.Error("isTestEnvironment() should return true when running tests")
}
}
// TestVersionStringsLength verifies versionStrings has correct length
func TestVersionStringsLength(t *testing.T) {
expectedCount := 41 // S1 through ZZ = 41 versions
@@ -708,10 +700,3 @@ func BenchmarkGetOutboundIP4(b *testing.B) {
}
}
// BenchmarkIsTestEnvironment benchmarks test environment detection
func BenchmarkIsTestEnvironment(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = isTestEnvironment()
}
}

50
main.go
View File

@@ -42,26 +42,26 @@ var Commit = func() string {
return "unknown"
}
func setupDiscordBot(logger *zap.Logger) *discordbot.DiscordBot {
func setupDiscordBot(config *_config.Config, logger *zap.Logger) *discordbot.DiscordBot {
bot, err := discordbot.NewDiscordBot(discordbot.Options{
Logger: logger,
Config: _config.ErupeConfig,
Config: config,
})
if err != nil {
preventClose(fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
}
// Discord bot
err = bot.Start()
if err != nil {
preventClose(fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
}
_, err = bot.Session.ApplicationCommandBulkOverwrite(bot.Session.State.User.ID, "", discordbot.Commands)
if err != nil {
preventClose(fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Discord: Failed to start, %s", err.Error()))
}
return bot
@@ -71,17 +71,25 @@ func main() {
var err error
var zapLogger *zap.Logger
config := _config.ErupeConfig
zapLogger, _ = zap.NewDevelopment()
defer func() { _ = zapLogger.Sync() }()
logger := zapLogger.Named("main")
config, cfgErr := _config.LoadConfig()
if cfgErr != nil {
fmt.Println("\nFailed to start Erupe:\n" + fmt.Sprintf("Failed to load config: %s", cfgErr.Error()))
go wait()
fmt.Println("\nPress Enter/Return to exit...")
_, _ = fmt.Scanln()
os.Exit(0)
}
logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit()))
logger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.RealClientMode))
if config.Database.Password == "" {
preventClose("Database password is blank")
preventClose(config, "Database password is blank")
}
if net.ParseIP(config.Host) == nil {
@@ -93,7 +101,7 @@ func main() {
}
}
if net.ParseIP(config.Host) == nil {
preventClose("Invalid host address")
preventClose(config, "Invalid host address")
}
}
@@ -101,7 +109,7 @@ func main() {
var discordBot *discordbot.DiscordBot = nil
if config.Discord.Enabled {
discordBot = setupDiscordBot(logger)
discordBot = setupDiscordBot(config, logger)
logger.Info("Discord: Started successfully")
} else {
@@ -120,13 +128,13 @@ func main() {
db, err := sqlx.Open("postgres", connectString)
if err != nil {
preventClose(fmt.Sprintf("Database: Failed to open, %s", err.Error()))
preventClose(config, fmt.Sprintf("Database: Failed to open, %s", err.Error()))
}
// Test the DB connection.
err = db.Ping()
if err != nil {
preventClose(fmt.Sprintf("Database: Failed to ping, %s", err.Error()))
preventClose(config, fmt.Sprintf("Database: Failed to ping, %s", err.Error()))
}
logger.Info("Database: Started successfully")
@@ -174,12 +182,12 @@ func main() {
entranceServer = entranceserver.NewServer(
&entranceserver.Config{
Logger: logger.Named("entrance"),
ErupeConfig: _config.ErupeConfig,
ErupeConfig: config,
DB: db,
})
err = entranceServer.Start()
if err != nil {
preventClose(fmt.Sprintf("Entrance: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Entrance: Failed to start, %s", err.Error()))
}
logger.Info("Entrance: Started successfully")
} else {
@@ -193,12 +201,12 @@ func main() {
signServer = signserver.NewServer(
&signserver.Config{
Logger: logger.Named("sign"),
ErupeConfig: _config.ErupeConfig,
ErupeConfig: config,
DB: db,
})
err = signServer.Start()
if err != nil {
preventClose(fmt.Sprintf("Sign: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Sign: Failed to start, %s", err.Error()))
}
logger.Info("Sign: Started successfully")
} else {
@@ -211,12 +219,12 @@ func main() {
ApiServer = api.NewAPIServer(
&api.Config{
Logger: logger.Named("sign"),
ErupeConfig: _config.ErupeConfig,
ErupeConfig: config,
DB: db,
})
err = ApiServer.Start()
if err != nil {
preventClose(fmt.Sprintf("API: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("API: Failed to start, %s", err.Error()))
}
logger.Info("API: Started successfully")
} else {
@@ -242,7 +250,7 @@ func main() {
c := *channelserver.NewServer(&channelserver.Config{
ID: uint16(sid),
Logger: logger.Named("channel-" + fmt.Sprint(count)),
ErupeConfig: _config.ErupeConfig,
ErupeConfig: config,
DB: db,
DiscordBot: discordBot,
})
@@ -255,7 +263,7 @@ func main() {
c.GlobalID = fmt.Sprintf("%02d%02d", j+1, i+1)
err = c.Start()
if err != nil {
preventClose(fmt.Sprintf("Channel: Failed to start, %s", err.Error()))
preventClose(config, fmt.Sprintf("Channel: Failed to start, %s", err.Error()))
} else {
channelQuery += fmt.Sprintf(
`INSERT INTO servers (server_id, current_players, world_name, world_description, land) VALUES (%d, 0, '%s', '%s', %d);`,
@@ -326,8 +334,8 @@ func wait() {
}
}
func preventClose(text string) {
if _config.ErupeConfig.DisableSoftCrash {
func preventClose(config *_config.Config, text string) {
if config != nil && config.DisableSoftCrash {
os.Exit(0)
}
fmt.Println("\nFailed to start Erupe:\n" + text)

View File

@@ -1,4 +1,8 @@
package clientctx
import "erupe-ce/config"
// ClientContext holds contextual data required for packet encoding/decoding.
type ClientContext struct{}
type ClientContext struct {
RealClientMode _config.Mode
}

View File

@@ -3,7 +3,7 @@ package network
import (
"encoding/hex"
"errors"
_config "erupe-ce/config"
"erupe-ce/config"
"erupe-ce/network/crypto"
"fmt"
"io"
@@ -24,6 +24,7 @@ type Conn interface {
// it automatically handles encryption, decryption, and key rotation via it's methods.
type CryptConn struct {
conn net.Conn
realClientMode _config.Mode
readKeyRot uint32
sendKeyRot uint32
sentPackets int32
@@ -32,11 +33,12 @@ type CryptConn struct {
}
// NewCryptConn creates a new CryptConn with proper default values.
func NewCryptConn(conn net.Conn) *CryptConn {
func NewCryptConn(conn net.Conn, mode _config.Mode) *CryptConn {
cc := &CryptConn{
conn: conn,
readKeyRot: 995117,
sendKeyRot: 995117,
conn: conn,
realClientMode: mode,
readKeyRot: 995117,
sendKeyRot: 995117,
}
return cc
}
@@ -61,7 +63,7 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) {
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 {
if cc.realClientMode < _config.F1 {
encryptedPacketBody = make([]byte, cph.DataSize)
} else {
encryptedPacketBody = make([]byte, uint32(cph.DataSize)+(uint32(cph.Pf0-0x03)*0x1000))

View File

@@ -54,7 +54,7 @@ func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
func TestNewCryptConn(t *testing.T) {
mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
if cc == nil {
t.Fatal("NewCryptConn() returned nil")
@@ -83,15 +83,13 @@ func TestNewCryptConn(t *testing.T) {
if cc.prevSendPacketCombinedCheck != 0 {
t.Errorf("prevSendPacketCombinedCheck = %d, want 0", cc.prevSendPacketCombinedCheck)
}
if cc.realClientMode != _config.ZZ {
t.Errorf("realClientMode = %d, want %d", cc.realClientMode, _config.ZZ)
}
}
func TestCryptConn_SendPacket(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
tests := []struct {
name string
data []byte
@@ -113,7 +111,7 @@ func TestCryptConn_SendPacket(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
err := cc.SendPacket(tt.data)
if err != nil {
@@ -157,7 +155,7 @@ func TestCryptConn_SendPacket(t *testing.T) {
func TestCryptConn_SendPacket_MultiplePackets(t *testing.T) {
mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
// Send first packet
err := cc.SendPacket([]byte{0x01, 0x02})
@@ -192,7 +190,7 @@ func TestCryptConn_SendPacket_MultiplePackets(t *testing.T) {
func TestCryptConn_SendPacket_KeyRotation(t *testing.T) {
mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
initialKey := cc.sendKeyRot
@@ -211,7 +209,7 @@ func TestCryptConn_SendPacket_KeyRotation(t *testing.T) {
func TestCryptConn_SendPacket_WriteError(t *testing.T) {
mockConn := newMockConn(nil)
mockConn.writeErr = errors.New("write error")
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
err := cc.SendPacket([]byte{0x01, 0x02, 0x03})
// Note: Current implementation doesn't return write error
@@ -222,13 +220,6 @@ func TestCryptConn_SendPacket_WriteError(t *testing.T) {
}
func TestCryptConn_ReadPacket_Success(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
_config.ErupeConfig.RealClientMode = _config.Z1 // Use older mode for simpler test
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
testData := []byte{0x74, 0x65, 0x73, 0x74} // "test"
key := uint32(0)
@@ -253,7 +244,7 @@ func TestCryptConn_ReadPacket_Success(t *testing.T) {
packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.Z1)
// Set the key to match what we used for encryption
cc.readKeyRot = key
@@ -273,13 +264,6 @@ func TestCryptConn_ReadPacket_Success(t *testing.T) {
}
func TestCryptConn_ReadPacket_KeyRotation(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
_config.ErupeConfig.RealClientMode = _config.Z1
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
testData := []byte{0x01, 0x02, 0x03, 0x04}
key := uint32(995117)
keyRotDelta := byte(3)
@@ -306,7 +290,7 @@ func TestCryptConn_ReadPacket_KeyRotation(t *testing.T) {
packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.Z1)
cc.readKeyRot = key
result, err := cc.ReadPacket()
@@ -325,13 +309,6 @@ func TestCryptConn_ReadPacket_KeyRotation(t *testing.T) {
}
func TestCryptConn_ReadPacket_NoKeyRotation(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
_config.ErupeConfig.RealClientMode = _config.Z1
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
testData := []byte{0x01, 0x02}
key := uint32(12345)
@@ -353,7 +330,7 @@ func TestCryptConn_ReadPacket_NoKeyRotation(t *testing.T) {
packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.Z1)
cc.readKeyRot = key
originalKeyRot := cc.readKeyRot
@@ -375,7 +352,7 @@ func TestCryptConn_ReadPacket_NoKeyRotation(t *testing.T) {
func TestCryptConn_ReadPacket_HeaderReadError(t *testing.T) {
mockConn := newMockConn([]byte{0x01, 0x02}) // Only 2 bytes, header needs 14
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
_, err := cc.ReadPacket()
if err == nil {
@@ -391,7 +368,7 @@ func TestCryptConn_ReadPacket_InvalidHeader(t *testing.T) {
// Create invalid header data (wrong endianness or malformed)
invalidHeader := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
mockConn := newMockConn(invalidHeader)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.ZZ)
_, err := cc.ReadPacket()
if err == nil {
@@ -400,13 +377,6 @@ func TestCryptConn_ReadPacket_InvalidHeader(t *testing.T) {
}
func TestCryptConn_ReadPacket_BodyReadError(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
_config.ErupeConfig.RealClientMode = _config.Z1
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
// Create valid header but incomplete body
header := &CryptPacketHeader{
Pf0: 0x03,
@@ -425,7 +395,7 @@ func TestCryptConn_ReadPacket_BodyReadError(t *testing.T) {
packet := append(headerBytes, incompleteBody...)
mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.Z1)
_, err := cc.ReadPacket()
if err == nil {
@@ -434,13 +404,6 @@ func TestCryptConn_ReadPacket_BodyReadError(t *testing.T) {
}
func TestCryptConn_ReadPacket_ChecksumMismatch(t *testing.T) {
// Save original config and restore after test
originalMode := _config.ErupeConfig.RealClientMode
_config.ErupeConfig.RealClientMode = _config.Z1
defer func() {
_config.ErupeConfig.RealClientMode = originalMode
}()
testData := []byte{0x01, 0x02, 0x03, 0x04}
key := uint32(0)
@@ -462,7 +425,7 @@ func TestCryptConn_ReadPacket_ChecksumMismatch(t *testing.T) {
packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn)
cc := NewCryptConn(mockConn, _config.Z1)
cc.readKeyRot = key
_, err := cc.ReadPacket()

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -63,7 +64,7 @@ func TestMsgSysPingRoundTrip(t *testing.T) {
AckHandle: 0x12345678,
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -105,7 +106,7 @@ func TestMsgSysTimeRoundTrip(t *testing.T) {
Timestamp: tt.timestamp,
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -239,7 +240,7 @@ func TestParserInterface(t *testing.T) {
bf.WriteUint32(123)
_, _ = bf.Seek(0, io.SeekStart)
err := p.Parse(bf, &clientctx.ClientContext{})
err := p.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Errorf("Parse() error = %v", err)
}
@@ -250,7 +251,7 @@ func TestBuilderInterface(t *testing.T) {
var b Builder = &MsgSysPing{AckHandle: 456}
bf := byteframe.NewByteFrame()
err := b.Build(bf, &clientctx.ClientContext{})
err := b.Build(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Errorf("Build() error = %v", err)
}
@@ -269,24 +270,21 @@ func TestOpcoderInterface(t *testing.T) {
}
}
func TestClientContextNilSafe(t *testing.T) {
// Some packets may need to handle nil ClientContext
func TestClientContextBuildSafe(t *testing.T) {
pkt := &MsgSysPing{AckHandle: 123}
bf := byteframe.NewByteFrame()
// This should not panic even with nil context (implementation dependent)
// Note: The actual behavior depends on implementation
err := pkt.Build(bf, nil)
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
err := pkt.Build(bf, ctx)
if err != nil {
// Error is acceptable if nil context is not supported
t.Logf("Build() with nil context returned error: %v", err)
t.Logf("Build() returned error: %v", err)
}
}
func TestMsgSysPingBuildFormat(t *testing.T) {
pkt := &MsgSysPing{AckHandle: 0x12345678}
bf := byteframe.NewByteFrame()
_ = pkt.Build(bf, &clientctx.ClientContext{})
_ = pkt.Build(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
data := bf.Data()
if len(data) != 4 {
@@ -305,7 +303,7 @@ func TestMsgSysTimeBuildFormat(t *testing.T) {
Timestamp: 0xDEADBEEF,
}
bf := byteframe.NewByteFrame()
_ = pkt.Build(bf, &clientctx.ClientContext{})
_ = pkt.Build(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
data := bf.Data()
if len(data) != 5 {
@@ -504,7 +502,7 @@ func TestMsgSysCreateStageParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCreateStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -556,7 +554,7 @@ func TestMsgSysEnterStageParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysEnterStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -605,7 +603,7 @@ func TestMsgSysMoveStageParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysMoveStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -651,7 +649,7 @@ func TestMsgSysLockStageParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLockStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -678,7 +676,7 @@ func TestMsgSysUnlockStageRoundTrip(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build (returns NOT IMPLEMENTED)
original := &MsgSysUnlockStage{}
@@ -719,7 +717,7 @@ func TestMsgSysBackStageParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysBackStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -749,7 +747,7 @@ func TestMsgSysLogoutParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLogout{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -803,7 +801,7 @@ func TestMsgSysLoginParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLogin{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -52,7 +53,7 @@ func TestBatchParseAckHandleOnly(t *testing.T) {
{"MsgMhfLoadPlateMyset", &MsgMhfLoadPlateMyset{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range packets {
t.Run(tc.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -97,7 +98,7 @@ func TestBatchParseTwoUint32(t *testing.T) {
{"MsgMhfInfoJoint", &MsgMhfInfoJoint{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range packets {
t.Run(tc.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -116,7 +117,7 @@ func TestBatchParseTwoUint32(t *testing.T) {
// TestBatchParseMultiField tests packets with various field combinations.
func TestBatchParseMultiField(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgMhfGetRengokuBinary", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -1041,7 +1042,7 @@ func TestBatchParseMultiField(t *testing.T) {
// TestBatchParseVariableLength tests packets with variable-length data.
func TestBatchParseVariableLength(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgMhfSaveFavoriteQuest", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -1344,7 +1345,7 @@ func TestBatchParseArrangeGuildMember(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfArrangeGuildMember{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if len(pkt.CharIDs) != 3 || pkt.CharIDs[2] != 30 {
@@ -1373,7 +1374,7 @@ func TestBatchParseUpdateGuildIcon(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateGuildIcon{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if len(pkt.IconParts) != 1 || pkt.IconParts[0].Red != 0xFF {
@@ -1392,7 +1393,7 @@ func TestBatchParseSysLoadRegister(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLoadRegister{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if pkt.RegisterID != 2 || pkt.Values != 3 {
@@ -1412,7 +1413,7 @@ func TestBatchParseSysLoadRegisterNonZeroPadding(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLoadRegister{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@@ -1438,7 +1439,7 @@ func TestBatchParseSysOperateRegister(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysOperateRegister{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if len(pkt.RawDataPayload) != 3 {
@@ -1457,7 +1458,7 @@ func TestBatchParseSysOperateRegisterNonZeroPadding(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysOperateRegister{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@@ -1474,7 +1475,7 @@ func TestBatchParseSysOperateRegisterNonZeroPadding(t *testing.T) {
// TestBatchParseSysGetFile tests the conditional scenario file packet.
func TestBatchParseSysGetFile(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("non-scenario", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -1529,7 +1530,7 @@ func TestBatchParseSysTerminalLog(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysTerminalLog{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if len(pkt.Entries) != 1 || pkt.Entries[0].Type1 != 1 {
@@ -1539,7 +1540,7 @@ func TestBatchParseSysTerminalLog(t *testing.T) {
// TestBatchParseNoOpPackets tests packets with empty Parse (return nil).
func TestBatchParseNoOpPackets(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
packets := []struct {
@@ -1563,7 +1564,7 @@ func TestBatchParseNoOpPackets(t *testing.T) {
// TestBatchParseNotImplemented tests that Parse returns NOT IMPLEMENTED for stub packets.
func TestBatchParseNotImplemented(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
packets := []MHFPacket{
@@ -1609,7 +1610,7 @@ func TestBatchParseNotImplemented(t *testing.T) {
// TestBatchBuildNotImplemented tests that Build returns NOT IMPLEMENTED for many packets.
func TestBatchBuildNotImplemented(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
packets := []MHFPacket{
@@ -1720,7 +1721,7 @@ func TestBatchBuildNotImplemented(t *testing.T) {
// TestBatchParseReserve188and18B tests reserve packets with AckHandle.
func TestBatchParseReserve188and18B(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range []struct {
name string
@@ -1742,7 +1743,7 @@ func TestBatchParseReserve188and18B(t *testing.T) {
// TestBatchParseStageStringPackets tests packets that read a stage ID string.
func TestBatchParseStageStringPackets(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgSysGetStageBinary", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -1848,7 +1849,7 @@ func TestBatchParseStampcardStamp(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfStampcardStamp{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if pkt.HR != 2 || pkt.GR != 3 || pkt.Stamps != 4 || pkt.Reward1 != 5 {
@@ -1869,7 +1870,7 @@ func TestBatchParseAnnounce(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAnnounce{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
if pkt.IPAddress != 0x7F000001 || pkt.Port != 54001 {
@@ -1879,7 +1880,7 @@ func TestBatchParseAnnounce(t *testing.T) {
// TestBatchParseOprtMail tests conditional parsing.
func TestBatchParseOprtMail(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("delete", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -1925,7 +1926,7 @@ func TestBatchParsePostTowerInfo(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfPostTowerInfo{}
if err := pkt.Parse(bf, &clientctx.ClientContext{}); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatal(err)
}
}
@@ -1933,7 +1934,7 @@ func TestBatchParsePostTowerInfo(t *testing.T) {
// TestBatchParseGuildHuntdata tests conditional guild huntdata.
// TestBatchParseAdditionalMultiField tests Parse for more packets with multiple fields.
func TestBatchParseAdditionalMultiField(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgMhfAcquireFesta", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -2202,7 +2203,7 @@ func TestBatchParseAdditionalMultiField(t *testing.T) {
}
func TestBatchParseGuildHuntdata(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("operation_0", func(t *testing.T) {
bf := byteframe.NewByteFrame()

View File

@@ -4,6 +4,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -302,7 +303,7 @@ func TestBuildCoverage_NotImplemented_Extended(t *testing.T) {
{"MsgMhfEnumerateCampaign", &MsgMhfEnumerateCampaign{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -346,7 +347,7 @@ func TestParseCoverage_NotImplemented_Extended(t *testing.T) {
{"MsgMhfRegistGuildAdventureDiva", &MsgMhfRegistGuildAdventureDiva{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -6,6 +6,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -25,7 +26,7 @@ func TestBuildParseDuplicateObject(t *testing.T) {
{"negative coords", 1, -1.0, -2.0, -3.0, 100, 200},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysDuplicateObject{
@@ -83,7 +84,7 @@ func TestBuildParsePositionObject(t *testing.T) {
{"max object id", 0xFFFFFFFF, 999.999, -999.999, 0.001},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysPositionObject{
@@ -136,7 +137,7 @@ func TestBuildParseCastedBinary(t *testing.T) {
{"larger payload", 42, 3, 4, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysCastedBinary{
@@ -187,7 +188,7 @@ func TestBuildParseLoadRegister(t *testing.T) {
{"max values", 0xFFFFFFFF, 0xFFFFFFFF, 255},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -230,7 +231,7 @@ func TestBuildParseOperateRegister(t *testing.T) {
{"large payload", 0xFFFFFFFF, 0xDEADBEEF, make([]byte, 256)},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -271,7 +272,7 @@ func TestBuildParseNotifyUserBinary(t *testing.T) {
{"max", 0xFFFFFFFF, 255},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysNotifyUserBinary{
@@ -314,7 +315,7 @@ func TestBuildParseTime(t *testing.T) {
{"typical timestamp", false, 1700000000},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysTime{
@@ -355,7 +356,7 @@ func TestBuildParseUpdateObjectBinary(t *testing.T) {
{"max", 0xFFFFFFFF, 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysUpdateObjectBinary{
@@ -400,7 +401,7 @@ func TestBuildParseArrangeGuildMember(t *testing.T) {
{"many members", 999, 400, []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -451,7 +452,7 @@ func TestBuildParseEnumerateGuildMember(t *testing.T) {
{"large values", 0xFFFFFFFF, 0xDEADBEEF, 0xCAFEBABE},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -494,7 +495,7 @@ func TestBuildParseStateCampaign(t *testing.T) {
{"max", 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -536,7 +537,7 @@ func TestBuildParseApplyCampaign(t *testing.T) {
{"max", 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF, make([]byte, 16)},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -579,7 +580,7 @@ func TestBuildParseEnumerateCampaign(t *testing.T) {
{"zero", 0, 0, 0},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfEnumerateCampaign{
@@ -622,7 +623,7 @@ func TestBuildParseEnumerateEvent(t *testing.T) {
{"nonzero", 42},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfEnumerateEvent{
@@ -661,7 +662,7 @@ func TestBuildParseAddUdTacticsPoint(t *testing.T) {
{"max", 0xFFFFFFFF, 0xFFFF, 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfAddUdTacticsPoint{
@@ -712,7 +713,7 @@ func TestBuildParseApplyDistItem(t *testing.T) {
{"max", 0xFFFFFFFF, 255, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -760,7 +761,7 @@ func TestBuildParseEnumerateDistItem(t *testing.T) {
{"zero", 0, 0, 0, 0},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfEnumerateDistItem{
@@ -813,7 +814,7 @@ func TestBuildParseAcquireExchangeShop(t *testing.T) {
{"larger payload", 0xDEADBEEF, []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfAcquireExchangeShop{
@@ -849,7 +850,7 @@ func TestBuildParseAcquireExchangeShop(t *testing.T) {
// TestBuildParseDisplayedAchievement verifies Parse for MsgMhfDisplayedAchievement.
// This struct has no exported fields; Parse only discards a single zeroed byte.
func TestBuildParseDisplayedAchievement(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
bf.WriteUint8(0) // Zeroed (discarded by Parse)
_, _ = bf.Seek(0, io.SeekStart)
@@ -872,7 +873,7 @@ func TestBuildParseAddKouryouPoint(t *testing.T) {
{"max", 0xFFFFFFFF, 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgMhfAddKouryouPoint{
@@ -913,7 +914,7 @@ func TestBuildParseCheckDailyCafepoint(t *testing.T) {
{"zero", 0, 0},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -947,7 +948,7 @@ func TestBuildParsePing(t *testing.T) {
{"max", 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysPing{
@@ -983,7 +984,7 @@ func TestBuildParseDeleteObject(t *testing.T) {
{"max", 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysDeleteObject{
@@ -1019,7 +1020,7 @@ func TestBuildParseNotifyRegister(t *testing.T) {
{"max", 0xFFFFFFFF},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysNotifyRegister{
@@ -1047,7 +1048,7 @@ func TestBuildParseNotifyRegister(t *testing.T) {
// TestBuildParseUnlockStage verifies Parse for MsgSysUnlockStage.
// This struct has no exported fields; Parse only discards a single zeroed uint16.
func TestBuildParseUnlockStage(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
bf.WriteUint16(0) // Zeroed (discarded by Parse)
_, _ = bf.Seek(0, io.SeekStart)
@@ -1068,7 +1069,7 @@ func TestBuildParseUnlockGlobalSema(t *testing.T) {
{"zero", 0},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
original := &MsgSysUnlockGlobalSema{
@@ -1096,7 +1097,7 @@ func TestBuildParseUnlockGlobalSema(t *testing.T) {
// TestBuildParseStageDestruct verifies Build/Parse round-trip for MsgSysStageDestruct.
// This packet has no fields at all.
func TestBuildParseStageDestruct(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
original := &MsgSysStageDestruct{}
bf := byteframe.NewByteFrame()
@@ -1117,7 +1118,7 @@ func TestBuildParseStageDestruct(t *testing.T) {
// TestBuildParseCastedBinaryPayloadIntegrity verifies that a large payload is preserved
// exactly through Build/Parse for MsgSysCastedBinary.
func TestBuildParseCastedBinaryPayloadIntegrity(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build a payload with recognizable pattern
payload := make([]byte, 1024)
@@ -1159,7 +1160,7 @@ func TestBuildParseCastedBinaryPayloadIntegrity(t *testing.T) {
// manual-build/Parse for MsgSysOperateRegister.
// Build is NOT IMPLEMENTED, so we manually write the binary representation.
func TestBuildParseOperateRegisterPayloadIntegrity(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
payload := make([]byte, 512)
for i := range payload {
@@ -1189,7 +1190,7 @@ func TestBuildParseOperateRegisterPayloadIntegrity(t *testing.T) {
// Build is NOT IMPLEMENTED, so we manually write the binary representation.
// Parse reads: uint32 AckHandle, uint32 GuildID, uint8 zeroed, uint8 charCount.
func TestBuildParseArrangeGuildMemberEmptySlice(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
bf.WriteUint32(1) // AckHandle
@@ -1216,7 +1217,7 @@ func TestBuildParseArrangeGuildMemberEmptySlice(t *testing.T) {
// TestBuildBinaryFormat verifies the exact binary output format of a Build call
// for MsgSysDuplicateObject to ensure correct endianness and field ordering.
func TestBuildBinaryFormat(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
pkt := &MsgSysDuplicateObject{
ObjID: 0x00000001,
X: 0,
@@ -1256,7 +1257,7 @@ func TestBuildBinaryFormat(t *testing.T) {
// TestBuildParseTimeBooleanEncoding verifies that the boolean field in MsgSysTime
// is encoded/decoded correctly for both true and false.
func TestBuildParseTimeBooleanEncoding(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, val := range []bool{true, false} {
t.Run("GetRemoteTime="+boolStr(val), func(t *testing.T) {
@@ -1302,7 +1303,7 @@ func boolStr(b bool) string {
// TestBuildParseSysAckBufferSmall verifies MsgSysAck round-trip with buffer response
// using the normal (non-extended) size field.
func TestBuildParseSysAckBufferSmall(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
payload := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
original := &MsgSysAck{
@@ -1340,7 +1341,7 @@ func TestBuildParseSysAckBufferSmall(t *testing.T) {
// TestBuildParseSysAckExtendedSize verifies MsgSysAck round-trip with a payload
// large enough to trigger the extended size field (>= 0xFFFF bytes).
func TestBuildParseSysAckExtendedSize(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
payload := make([]byte, 0x10000) // 65536 bytes, triggers extended size
for i := range payload {
payload[i] = byte(i % 256)
@@ -1375,7 +1376,7 @@ func TestBuildParseSysAckExtendedSize(t *testing.T) {
// TestBuildParseSysAckNonBuffer verifies MsgSysAck round-trip with non-buffer response
// (exactly 4 bytes of data always read in Parse).
func TestBuildParseSysAckNonBuffer(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
original := &MsgSysAck{
AckHandle: 100,
IsBufferResponse: false,

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -496,7 +497,7 @@ func TestAckHandlePacketsParse(t *testing.T) {
{"MsgMhfGetKijuInfo", network.MSG_MHF_GET_KIJU_INFO},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
@@ -546,7 +547,7 @@ func TestAddAchievementParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAddAchievement{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -586,7 +587,7 @@ func TestGetAchievementParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetAchievement{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -629,7 +630,7 @@ func TestBuildNotImplemented(t *testing.T) {
for _, pkt := range packetsToTest {
t.Run(pkt.Opcode().String(), func(t *testing.T) {
bf := byteframe.NewByteFrame()
err := pkt.Build(bf, &clientctx.ClientContext{})
err := pkt.Build(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err == nil {
t.Logf("Build() did not return error (implementation may exist)")
} else {

View File

@@ -31,7 +31,7 @@ func (m *MsgMhfAcquireCafeItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl
m.ItemType = bf.ReadUint16()
m.ItemID = bf.ReadUint16()
m.Quant = bf.ReadUint16()
if _config.ErupeConfig.RealClientMode >= _config.G6 {
if ctx.RealClientMode >= _config.G6 {
m.PointCost = bf.ReadUint32()
} else {
m.PointCost = uint32(bf.ReadUint16())

View File

@@ -10,13 +10,6 @@ import (
"erupe-ce/network/clientctx"
)
func init() {
// Initialize ErupeConfig for tests that access it
_config.ErupeConfig = &_config.Config{
RealClientMode: _config.ZZ, // Default to ZZ for tests
}
}
func TestMsgMhfAcquireCafeItemOpcode(t *testing.T) {
pkt := &MsgMhfAcquireCafeItem{}
if pkt.Opcode() != network.MSG_MHF_ACQUIRE_CAFE_ITEM {
@@ -38,7 +31,7 @@ func TestMsgMhfAcquireCafeItemParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireCafeItem{}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
err := pkt.Parse(bf, ctx)
if err != nil {
@@ -97,7 +90,7 @@ func TestMsgMhfAcquireCafeItemParseUint32PointCost(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireCafeItem{}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
err := pkt.Parse(bf, ctx)
if err != nil {
@@ -126,7 +119,7 @@ func TestMsgMhfAcquireCafeItemParseFieldOrder(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireCafeItem{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -161,7 +154,7 @@ func TestMsgMhfAcquireCafeItemBuildNotImplemented(t *testing.T) {
}
bf := byteframe.NewByteFrame()
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
err := pkt.Build(bf, ctx)
if err == nil {

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -51,7 +52,7 @@ func TestMsgMhfAcquireGuildTresureParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireGuildTresure{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -92,7 +93,7 @@ func TestMsgMhfAcquireTitleParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireTitle{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -133,7 +134,7 @@ func TestMsgMhfAcquireDistItemParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireDistItem{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -177,7 +178,7 @@ func TestMsgMhfAcquireMonthlyItemParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireMonthlyItem{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -231,7 +232,7 @@ func TestAcquirePacketEdgeCases(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireGuildTresure{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -250,7 +251,7 @@ func TestAcquirePacketEdgeCases(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAcquireDistItem{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v for type %d", err, i)
}

View File

@@ -27,10 +27,10 @@ func (m *MsgMhfApplyDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie
m.AckHandle = bf.ReadUint32()
m.DistributionType = bf.ReadUint8()
m.DistributionID = bf.ReadUint32()
if _config.ErupeConfig.RealClientMode >= _config.G8 {
if ctx.RealClientMode >= _config.G8 {
m.Unk2 = bf.ReadUint32()
}
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if ctx.RealClientMode >= _config.G10 {
m.Unk3 = bf.ReadUint32()
}
return nil

View File

@@ -28,7 +28,7 @@ func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.
m.DistType = bf.ReadUint8()
m.Unk1 = bf.ReadUint8()
m.MaxCount = bf.ReadUint16() // Hardcoded to 256
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if ctx.RealClientMode >= _config.Z1 {
m.Unk3 = bf.ReadBytes(uint(bf.ReadUint8()))
}
return nil

View File

@@ -30,7 +30,7 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli
m.Unk0 = bf.ReadUint8()
m.World = bf.ReadUint8()
m.Counter = bf.ReadUint16()
if _config.ErupeConfig.RealClientMode <= _config.Z1 {
if ctx.RealClientMode <= _config.Z1 {
m.Offset = uint16(bf.ReadUint8())
} else {
m.Offset = bf.ReadUint16()

View File

@@ -32,7 +32,7 @@ func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie
m.ShopID = bf.ReadUint32()
m.Limit = bf.ReadUint16()
m.Unk3 = bf.ReadUint8()
if _config.ErupeConfig.RealClientMode >= _config.G2 {
if ctx.RealClientMode >= _config.G2 {
m.Unk4 = bf.ReadUint8()
m.Unk5 = bf.ReadUint32()
}

View File

@@ -4,7 +4,9 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
func TestMsgMhfUpdateGuacotOpcode_Guacot(t *testing.T) {
@@ -39,7 +41,7 @@ func TestMsgMhfUpdateGuacotParse_SingleEntry(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -100,7 +102,7 @@ func TestMsgMhfUpdateGuacotParse_MultipleEntries(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -130,7 +132,7 @@ func TestMsgMhfUpdateGuacotParse_ZeroEntries(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -161,7 +163,7 @@ func TestMsgMhfUpdateGuacotParse_DeletionEntry(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -188,7 +190,7 @@ func TestMsgMhfUpdateGuacotParse_EmptyName(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -206,7 +208,7 @@ func TestMsgMhfEnumerateGuacotParse(t *testing.T) {
pkt := &MsgMhfEnumerateGuacot{}
_, _ = bf.Seek(0, 0)
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error: %v", err)
}
@@ -221,7 +223,7 @@ func TestMsgMhfEnumerateGuacotParse(t *testing.T) {
func TestMsgMhfUpdateGuacotBuild_NotImplemented(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
err := pkt.Build(byteframe.NewByteFrame(), nil)
err := pkt.Build(byteframe.NewByteFrame(), &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err == nil {
t.Error("Build() should return error (not implemented)")
}
@@ -229,7 +231,7 @@ func TestMsgMhfUpdateGuacotBuild_NotImplemented(t *testing.T) {
func TestMsgMhfEnumerateGuacotBuild_NotImplemented(t *testing.T) {
pkt := &MsgMhfEnumerateGuacot{}
err := pkt.Build(byteframe.NewByteFrame(), nil)
err := pkt.Build(byteframe.NewByteFrame(), &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err == nil {
t.Error("Build() should return error (not implemented)")
}
@@ -252,7 +254,7 @@ func TestGoocooStruct_Data1Size(t *testing.T) {
pkt := &MsgMhfUpdateGuacot{}
_, _ = bf.Seek(0, 0)
_ = pkt.Parse(bf, nil)
_ = pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
g := pkt.Goocoos[0]

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -520,7 +521,7 @@ func TestAchievementPacketParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAddAchievement{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -30,7 +30,7 @@ func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientCon
m.AllocMemSize = bf.ReadUint32()
m.SaveType = bf.ReadUint8()
m.Unk1 = bf.ReadUint32()
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if ctx.RealClientMode >= _config.G1 {
m.DataSize = bf.ReadUint32()
}
if m.DataSize == 0 { // seems to be used when DataSize = 0 rather than on savetype?

View File

@@ -32,12 +32,12 @@ func (m *MsgMhfStampcardStamp) Opcode() network.PacketID {
func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
m.HR = bf.ReadUint16()
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if ctx.RealClientMode >= _config.G1 {
m.GR = bf.ReadUint16()
}
m.Stamps = bf.ReadUint16()
bf.ReadUint16() // Zeroed
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
if ctx.RealClientMode >= _config.Z2 {
m.Reward1 = uint16(bf.ReadUint32())
m.Reward2 = uint16(bf.ReadUint32())
m.Item1 = uint16(bf.ReadUint32())

View File

@@ -23,11 +23,11 @@ func (m *MsgMhfUpdateMyhouseInfo) Opcode() network.PacketID {
// Parse parses the packet from binary
func (m *MsgMhfUpdateMyhouseInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if ctx.RealClientMode >= _config.G10 {
m.Data = bf.ReadBytes(362)
} else if _config.ErupeConfig.RealClientMode >= _config.GG {
} else if ctx.RealClientMode >= _config.GG {
m.Data = bf.ReadBytes(338)
} else if _config.ErupeConfig.RealClientMode >= _config.F5 {
} else if ctx.RealClientMode >= _config.F5 {
// G1 is a guess
m.Data = bf.ReadBytes(314)
} else {

View File

@@ -35,7 +35,7 @@ func (m *MsgMhfUpdateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl
case 0:
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
case 1:
m.UpdatedEquipment = append(m.UpdatedEquipment, mhfitem.ReadWarehouseEquipment(bf))
m.UpdatedEquipment = append(m.UpdatedEquipment, mhfitem.ReadWarehouseEquipment(bf, ctx.RealClientMode))
}
}
return nil

View File

@@ -4,6 +4,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -245,7 +246,7 @@ func TestBuildCoverage_NotImplemented(t *testing.T) {
{"MsgSysReserve1AF", &MsgSysReserve1AF{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -282,7 +283,7 @@ func TestParseCoverage_NotImplemented(t *testing.T) {
{"MsgMhfUpdateGuild", &MsgMhfUpdateGuild{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -5,6 +5,7 @@ import (
"erupe-ce/common/byteframe"
"erupe-ce/common/mhfcourse"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -12,7 +13,7 @@ import (
// method is implemented (reads from ByteFrame) but was not yet covered by tests.
// Each test provides a ByteFrame with enough bytes for the Parse to succeed.
func TestParseCoverage_Implemented(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
tests := []struct {
name string
@@ -75,7 +76,7 @@ func TestParseCoverage_Implemented(t *testing.T) {
// TestParseCoverage_VariableLength tests Parse for variable-length packets
// that require specific data layouts.
func TestParseCoverage_VariableLength(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgMhfAcquireItem_EmptyList", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -239,7 +240,7 @@ func TestParseCoverage_VariableLength(t *testing.T) {
// TestBuildCoverage_Implemented tests Build() on packet types whose Build method
// is implemented (writes to ByteFrame) but was not yet covered.
func TestBuildCoverage_Implemented(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgSysDeleteUser", func(t *testing.T) {
pkt := &MsgSysDeleteUser{CharID: 123}
@@ -306,7 +307,7 @@ func TestBuildCoverage_Implemented(t *testing.T) {
// TestParseCoverage_EmptyPackets tests Parse() for packets with no payload fields.
func TestParseCoverage_EmptyPackets(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgSysCleanupObject_Parse", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -343,7 +344,7 @@ func TestParseCoverage_EmptyPackets(t *testing.T) {
// TestParseCoverage_NotImplemented2 tests Parse/Build for packets that return NOT IMPLEMENTED.
func TestParseCoverage_NotImplemented2(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("MsgSysGetObjectOwner_Parse", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -366,7 +367,7 @@ func TestParseCoverage_NotImplemented2(t *testing.T) {
// TestParseCoverage_UpdateWarehouse tests MsgMhfUpdateWarehouse.Parse with different box types.
func TestParseCoverage_UpdateWarehouse(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("EmptyChanges", func(t *testing.T) {
bf := byteframe.NewByteFrame()

View File

@@ -6,12 +6,13 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
// TestParseLargeMsgSysUpdateRightBuild tests Build for MsgSysUpdateRight (no Parse implementation).
func TestParseLargeMsgSysUpdateRightBuild(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
original := &MsgSysUpdateRight{
ClientRespAckHandle: 0x12345678,
Bitfield: 0xDEADBEEF,
@@ -57,7 +58,7 @@ func TestParseLargeMsgMhfOperateWarehouse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfOperateWarehouse{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -92,7 +93,7 @@ func TestParseLargeMsgMhfOperateWarehouseEquip(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfOperateWarehouse{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -132,7 +133,7 @@ func TestParseLargeMsgMhfLoadHouse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfLoadHouse{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -171,7 +172,7 @@ func TestParseLargeMsgMhfSendMail(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfSendMail{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -232,7 +233,7 @@ func TestParseLargeMsgMhfApplyBbsArticle(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfApplyBbsArticle{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -270,7 +271,7 @@ func TestParseLargeMsgMhfChargeFesta(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfChargeFesta{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -305,7 +306,7 @@ func TestParseLargeMsgMhfChargeFestaZeroSouls(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfChargeFesta{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if len(pkt.Souls) != 0 {
@@ -328,7 +329,7 @@ func TestParseLargeMsgMhfOperateJoint(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfOperateJoint{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -364,7 +365,7 @@ func TestParseLargeMsgMhfOperationInvGuild(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfOperationInvGuild{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -403,7 +404,7 @@ func TestParseLargeMsgMhfSaveMercenary(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfSaveMercenary{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -445,7 +446,7 @@ func TestParseLargeMsgMhfUpdateHouse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateHouse{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -480,7 +481,7 @@ func TestParseLargeMsgSysCreateAcquireSemaphore(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCreateAcquireSemaphore{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -512,7 +513,7 @@ func TestParseLargeMsgMhfOperateGuild(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfOperateGuild{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -552,7 +553,7 @@ func TestParseLargeMsgMhfReadBeatLevel(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfReadBeatLevel{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -596,7 +597,7 @@ func TestParseLargeMsgSysCreateObject(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCreateObject{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -632,7 +633,7 @@ func TestParseLargeMsgSysLockGlobalSema(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLockGlobalSema{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -664,7 +665,7 @@ func TestParseLargeMsgMhfCreateJoint(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfCreateJoint{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -689,7 +690,7 @@ func TestParseLargeMsgMhfGetUdTacticsRemainingPoint(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetUdTacticsRemainingPoint{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -718,7 +719,7 @@ func TestParseLargeMsgMhfPostCafeDurationBonusReceived(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfPostCafeDurationBonusReceived{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -744,7 +745,7 @@ func TestParseLargeMsgMhfPostCafeDurationBonusReceivedEmpty(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfPostCafeDurationBonusReceived{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if len(pkt.CafeBonusID) != 0 {
@@ -762,7 +763,7 @@ func TestParseLargeMsgMhfRegistGuildAdventureDiva(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfRegistGuildAdventureDiva{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -787,7 +788,7 @@ func TestParseLargeMsgMhfStateFestaG(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfStateFestaG{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -812,7 +813,7 @@ func TestParseLargeMsgMhfStateFestaU(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfStateFestaU{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -838,7 +839,7 @@ func TestParseLargeMsgSysEnumerateStage(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysEnumerateStage{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -864,7 +865,7 @@ func TestParseLargeMsgSysReserveStage(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysReserveStage{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -6,6 +6,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -36,7 +37,7 @@ func TestParseMediumVoteFesta(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfVoteFesta{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -81,7 +82,7 @@ func TestParseMediumAcquireSemaphore(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysAcquireSemaphore{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -119,7 +120,7 @@ func TestParseMediumCheckSemaphore(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCheckSemaphore{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -156,7 +157,7 @@ func TestParseMediumGetUserBinary(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysGetUserBinary{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -195,7 +196,7 @@ func TestParseMediumSetObjectBinary(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysSetObjectBinary{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -234,7 +235,7 @@ func TestParseMediumSetUserBinary(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysSetUserBinary{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -274,7 +275,7 @@ func TestParseMediumGetUdRanking(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetUdRanking{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -309,7 +310,7 @@ func TestParseMediumGetUdTacticsRanking(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetUdTacticsRanking{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -346,7 +347,7 @@ func TestParseMediumRegistGuildTresure(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfRegistGuildTresure{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -377,7 +378,7 @@ func TestParseMediumUpdateMyhouseInfo(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateMyhouseInfo{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -399,7 +400,7 @@ func TestParseMediumUpdateMyhouseInfo(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateMyhouseInfo{}
if err := pkt.Parse(bf, nil); err != nil {
if err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ}); err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -517,7 +518,7 @@ func TestParseMediumAckHandleOnlyBatch(t *testing.T) {
},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
ackValues := []uint32{0x12345678, 0, 0xFFFFFFFF, 0xDEADBEEF}
for _, tc := range packets {
@@ -539,7 +540,7 @@ func TestParseMediumAckHandleOnlyBatch(t *testing.T) {
// TestParseMediumAckHandleOnlyVerifyValues tests each 3-stmt AckHandle-only
// packet individually, verifying that the AckHandle field is correctly populated.
func TestParseMediumAckHandleOnlyVerifyValues(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
ack := uint32(0xCAFEBABE)
makeFrame := func() *byteframe.ByteFrame {
@@ -738,7 +739,7 @@ func TestParseMediumDeleteUser(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysDeleteUser{}
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err == nil {
t.Fatal("Parse() should return error for NOT IMPLEMENTED")
}
@@ -755,7 +756,7 @@ func TestParseMediumInsertUser(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysInsertUser{}
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err == nil {
t.Fatal("Parse() should return error for NOT IMPLEMENTED")
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -59,7 +60,7 @@ func TestParseSmallNotImplemented(t *testing.T) {
{"MsgSysTransBinary", &MsgSysTransBinary{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range packets {
t.Run(tc.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -88,7 +89,7 @@ func TestParseSmallNoData(t *testing.T) {
{"MsgSysUnreserveStage", &MsgSysUnreserveStage{}},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tc := range packets {
t.Run(tc.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -111,7 +112,7 @@ func TestParseSmallLogout(t *testing.T) {
{"max", 255},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -133,7 +134,7 @@ func TestParseSmallLogout(t *testing.T) {
// TestParseSmallEnumerateHouse tests Parse for MsgMhfEnumerateHouse which reads
// AckHandle, CharID, Method, Unk, lenName, and optional Name.
func TestParseSmallEnumerateHouse(t *testing.T) {
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
t.Run("no name", func(t *testing.T) {
bf := byteframe.NewByteFrame()
@@ -196,7 +197,7 @@ func TestParseSmallEnumerateHouse(t *testing.T) {
}
// TestParseSmallNotImplementedDoesNotPanic ensures that calling Parse on NOT IMPLEMENTED
// packets with a nil ClientContext does not cause a nil pointer dereference panic.
// packets returns an error and does not panic.
func TestParseSmallNotImplementedDoesNotPanic(t *testing.T) {
packets := []MHFPacket{
&MsgMhfAcceptReadReward{},
@@ -204,10 +205,11 @@ func TestParseSmallNotImplementedDoesNotPanic(t *testing.T) {
&MsgSysSerialize{},
}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
for _, pkt := range packets {
t.Run("nil_ctx", func(t *testing.T) {
t.Run("not_implemented", func(t *testing.T) {
bf := byteframe.NewByteFrame()
err := pkt.Parse(bf, nil)
err := pkt.Parse(bf, ctx)
if err == nil {
t.Fatal("expected error, got nil")
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/clientctx"
)
@@ -17,7 +18,7 @@ func TestMsgMhfGetAchievementDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetAchievement{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -39,7 +40,7 @@ func TestMsgMhfAddAchievementDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfAddAchievement{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -81,7 +82,7 @@ func TestMsgSysCastBinaryDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCastBinary{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -119,7 +120,7 @@ func TestMsgSysLogoutDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLogout{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -147,7 +148,7 @@ func TestMsgSysBackStageDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysBackStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -174,7 +175,7 @@ func TestMsgSysPingDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysPing{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -203,7 +204,7 @@ func TestMsgSysTimeDetailedParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysTime{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -55,7 +56,7 @@ func TestMsgSysAckRoundTrip(t *testing.T) {
ErrorCode: tt.errorCode,
AckData: tt.ackData,
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -99,7 +100,7 @@ func TestMsgSysAckLargePayload(t *testing.T) {
ErrorCode: 0,
AckData: largeData,
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -130,7 +131,7 @@ func TestMsgSysAckOpcode(t *testing.T) {
func TestMsgSysNopRoundTrip(t *testing.T) {
original := &MsgSysNop{}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -161,7 +162,7 @@ func TestMsgSysNopOpcode(t *testing.T) {
func TestMsgSysEndRoundTrip(t *testing.T) {
original := &MsgSysEnd{}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
// Build
bf := byteframe.NewByteFrame()
@@ -198,7 +199,7 @@ func TestMsgSysAckNonBufferResponse(t *testing.T) {
ErrorCode: 0,
AckData: []byte{0xAA, 0xBB, 0xCC, 0xDD},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
err := original.Build(bf, ctx)
@@ -227,7 +228,7 @@ func TestMsgSysAckNonBufferShortData(t *testing.T) {
ErrorCode: 0,
AckData: []byte{0x01}, // Only 1 byte
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
err := original.Build(bf, ctx)
@@ -255,7 +256,7 @@ func TestMsgSysAckBuildFormat(t *testing.T) {
ErrorCode: 0x55,
AckData: []byte{0xAA, 0xBB},
}
ctx := &clientctx.ClientContext{}
ctx := &clientctx.ClientContext{RealClientMode: _config.ZZ}
bf := byteframe.NewByteFrame()
_ = pkt.Build(bf, ctx)

View File

@@ -25,7 +25,7 @@ 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()
if _config.ErupeConfig.RealClientMode >= _config.S7 { // Assuming this was added with Ravi?
if ctx.RealClientMode >= _config.S7 { // Assuming this was added with Ravi?
m.PlayerCount = bf.ReadUint8()
}
bf.ReadUint8() // SemaphoreID length

View File

@@ -26,7 +26,7 @@ func (m *MsgSysCreateSemaphore) Opcode() network.PacketID {
func (m *MsgSysCreateSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16()
if _config.ErupeConfig.RealClientMode >= _config.S7 { // Assuming this was added with Ravi?
if ctx.RealClientMode >= _config.S7 { // Assuming this was added with Ravi?
m.PlayerCount = bf.ReadUint8()
}
bf.ReadUint8() // SemaphoreID length

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -34,7 +35,7 @@ func TestMsgSysCastBinaryParse(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCastBinary{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
@@ -58,7 +59,7 @@ func TestMsgSysCreateStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCreateStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -102,7 +103,7 @@ func TestMsgSysEnterStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysEnterStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -142,7 +143,7 @@ func TestMsgSysMoveStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysMoveStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -184,7 +185,7 @@ func TestMsgSysLockStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysLockStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -218,7 +219,7 @@ func TestMsgSysUnlockStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysUnlockStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -245,7 +246,7 @@ func TestMsgSysBackStageFields(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysBackStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -274,7 +275,7 @@ func TestStageIDEdgeCases(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCreateStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
@@ -296,7 +297,7 @@ func TestStageIDEdgeCases(t *testing.T) {
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysEnterStage{}
err := pkt.Parse(bf, &clientctx.ClientContext{})
err := pkt.Parse(bf, &clientctx.ClientContext{RealClientMode: _config.ZZ})
if err != nil {
t.Fatalf("Parse() error = %v", err)
}

View File

@@ -49,7 +49,7 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client
e.Unk1 = bf.ReadInt32()
e.Unk2 = bf.ReadInt32()
e.Unk3 = bf.ReadInt32()
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if ctx.RealClientMode >= _config.G1 {
for j := 0; j < 4; j++ {
e.Unk4 = append(e.Unk4, bf.ReadInt32())
}

View File

@@ -118,12 +118,12 @@ func (gi *GuildIcon) Value() (valuer driver.Value, err error) {
return json.Marshal(gi)
}
func (g *Guild) Rank() uint16 {
func (g *Guild) Rank(mode _config.Mode) 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 {
if mode <= _config.Z2 {
rpMap = []uint32{
3500, 6000, 8500, 11000, 13500, 16000, 20000, 24000, 28000,
33000, 38000, 43000, 48000, 55000, 70000, 90000, 120000,
@@ -131,21 +131,21 @@ func (g *Guild) Rank() uint16 {
}
for i, u := range rpMap {
if g.RankRP < u {
if _config.ErupeConfig.RealClientMode <= _config.S6 && i >= 12 {
if mode <= _config.S6 && i >= 12 {
return 12
} else if _config.ErupeConfig.RealClientMode <= _config.F5 && i >= 13 {
} else if mode <= _config.F5 && i >= 13 {
return 13
} else if _config.ErupeConfig.RealClientMode <= _config.G32 && i >= 14 {
} else if mode <= _config.G32 && i >= 14 {
return 14
}
return uint16(i)
}
}
if _config.ErupeConfig.RealClientMode <= _config.S6 {
if mode <= _config.S6 {
return 12
} else if _config.ErupeConfig.RealClientMode <= _config.F5 {
} else if mode <= _config.F5 {
return 13
} else if _config.ErupeConfig.RealClientMode <= _config.G32 {
} else if mode <= _config.G32 {
return 14
}
return 17

View File

@@ -102,7 +102,7 @@ func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
cafeTime = uint32(TimeAdjusted().Unix()) - uint32(s.sessionStart) + cafeTime
}
bf.WriteUint32(cafeTime)
if _config.ErupeConfig.RealClientMode >= _config.ZZ {
if s.server.erupeConfig.RealClientMode >= _config.ZZ {
bf.WriteUint16(0)
ps.Uint16(bf, fmt.Sprintf(s.server.i18n.cafe.reset, int(cafeReset.Month()), cafeReset.Day()), true)
}

View File

@@ -71,7 +71,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
bf.WriteInt16(event.MaxHR)
bf.WriteInt16(event.MinSR)
bf.WriteInt16(event.MaxSR)
if _config.ErupeConfig.RealClientMode >= _config.G3 {
if s.server.erupeConfig.RealClientMode >= _config.G3 {
bf.WriteInt16(event.MinGR)
bf.WriteInt16(event.MaxGR)
}

View File

@@ -24,7 +24,8 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
}
saveData := &CharacterSaveData{
Pointers: getPointers(),
Mode: s.server.erupeConfig.RealClientMode,
Pointers: getPointers(s.server.erupeConfig.RealClientMode),
}
err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name)
if err != nil {
@@ -63,7 +64,7 @@ func (save *CharacterSaveData) Save(s *Session) {
save.updateSaveDataWithStruct()
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if s.server.erupeConfig.RealClientMode >= _config.G1 {
err := save.Compress()
if err != nil {
s.logger.Error("Failed to compress savedata", zap.Error(err))

View File

@@ -52,12 +52,7 @@ func TestGetPointers(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Save and restore original config
originalMode := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalMode }()
_config.ErupeConfig.RealClientMode = tt.clientMode
pointers := getPointers()
pointers := getPointers(tt.clientMode)
if pointers[pGender] != tt.wantGender {
t.Errorf("pGender = %d, want %d", pointers[pGender], tt.wantGender)
@@ -216,10 +211,6 @@ func TestCharacterSaveData_RoundTrip(t *testing.T) {
// TestCharacterSaveData_updateStructWithSaveData tests parsing save data
func TestCharacterSaveData_updateStructWithSaveData(t *testing.T) {
originalMode := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalMode }()
_config.ErupeConfig.RealClientMode = _config.Z2
tests := []struct {
name string
isNewCharacter bool
@@ -267,7 +258,8 @@ func TestCharacterSaveData_updateStructWithSaveData(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
save := &CharacterSaveData{
Pointers: getPointers(),
Mode: _config.Z2,
Pointers: getPointers(_config.Z2),
decompSave: tt.setupSaveData(),
IsNewCharacter: tt.isNewCharacter,
}
@@ -287,10 +279,6 @@ func TestCharacterSaveData_updateStructWithSaveData(t *testing.T) {
// TestCharacterSaveData_updateSaveDataWithStruct tests writing struct to save data
func TestCharacterSaveData_updateSaveDataWithStruct(t *testing.T) {
originalMode := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalMode }()
_config.ErupeConfig.RealClientMode = _config.G10
tests := []struct {
name string
rp uint16
@@ -320,7 +308,8 @@ func TestCharacterSaveData_updateSaveDataWithStruct(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
save := &CharacterSaveData{
Pointers: getPointers(),
Mode: _config.G10,
Pointers: getPointers(_config.G10),
decompSave: make([]byte, 150000),
RP: tt.rp,
KQF: tt.kqf,
@@ -388,11 +377,6 @@ func TestGetCharacterSaveData_Integration(t *testing.T) {
db := SetupTestDB(t)
defer TeardownTestDB(t, db)
// Save original config mode
originalMode := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalMode }()
_config.ErupeConfig.RealClientMode = _config.Z2
tests := []struct {
name string
charName string
@@ -430,6 +414,7 @@ func TestGetCharacterSaveData_Integration(t *testing.T) {
s := createTestSession(mock)
s.charID = charID
s.server.db = db
s.server.erupeConfig.RealClientMode = _config.Z2
// Get character save data
saveData, err := GetCharacterSaveData(s, charID)
@@ -464,11 +449,6 @@ func TestCharacterSaveData_Save_Integration(t *testing.T) {
db := SetupTestDB(t)
defer TeardownTestDB(t, db)
// Save original config mode
originalMode := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalMode }()
_config.ErupeConfig.RealClientMode = _config.Z2
// Create test user and character
userID := CreateTestUser(t, db, "savetest")
charID := CreateTestCharacter(t, db, userID, "SaveChar")
@@ -478,6 +458,7 @@ func TestCharacterSaveData_Save_Integration(t *testing.T) {
s := createTestSession(mock)
s.charID = charID
s.server.db = db
s.server.erupeConfig.RealClientMode = _config.Z2
// Load character save data
saveData, err := GetCharacterSaveData(s, charID)

View File

@@ -15,29 +15,29 @@ import (
"slices"
"strconv"
"strings"
"sync"
"time"
"go.uber.org/zap"
)
var commands map[string]_config.Command
var (
commands map[string]_config.Command
commandsOnce sync.Once
)
func init() {
commands = make(map[string]_config.Command)
zapConfig := zap.NewDevelopmentConfig()
zapConfig.DisableCaller = true
zapLogger, _ := zapConfig.Build()
defer func() { _ = zapLogger.Sync() }()
logger := zapLogger.Named("commands")
cmds := _config.ErupeConfig.Commands
for _, cmd := range cmds {
commands[cmd.Name] = cmd
if cmd.Enabled {
logger.Info(fmt.Sprintf("Command %s: Enabled, prefix: %s", cmd.Name, cmd.Prefix))
} else {
logger.Info(fmt.Sprintf("Command %s: Disabled", cmd.Name))
func initCommands(cmds []_config.Command, logger *zap.Logger) {
commandsOnce.Do(func() {
commands = make(map[string]_config.Command)
for _, cmd := range cmds {
commands[cmd.Name] = cmd
if cmd.Enabled {
logger.Info(fmt.Sprintf("Command %s: Enabled, prefix: %s", cmd.Name, cmd.Prefix))
} else {
logger.Info(fmt.Sprintf("Command %s: Disabled", cmd.Name))
}
}
}
})
}
func sendDisabledCommandMessage(s *Session, cmd _config.Command) {

View File

@@ -12,46 +12,30 @@ import (
// =============================================================================
func TestEquipSkinHistSize_Default(t *testing.T) {
orig := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = orig }()
_config.ErupeConfig.RealClientMode = _config.ZZ
got := equipSkinHistSize()
got := equipSkinHistSize(_config.ZZ)
if got != 3200 {
t.Errorf("equipSkinHistSize() with ZZ = %d, want 3200", got)
t.Errorf("equipSkinHistSize(ZZ) = %d, want 3200", got)
}
}
func TestEquipSkinHistSize_Z2(t *testing.T) {
orig := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = orig }()
_config.ErupeConfig.RealClientMode = _config.Z2
got := equipSkinHistSize()
got := equipSkinHistSize(_config.Z2)
if got != 2560 {
t.Errorf("equipSkinHistSize() with Z2 = %d, want 2560", got)
t.Errorf("equipSkinHistSize(Z2) = %d, want 2560", got)
}
}
func TestEquipSkinHistSize_Z1(t *testing.T) {
orig := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = orig }()
_config.ErupeConfig.RealClientMode = _config.Z1
got := equipSkinHistSize()
got := equipSkinHistSize(_config.Z1)
if got != 1280 {
t.Errorf("equipSkinHistSize() with Z1 = %d, want 1280", got)
t.Errorf("equipSkinHistSize(Z1) = %d, want 1280", got)
}
}
func TestEquipSkinHistSize_OlderMode(t *testing.T) {
orig := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = orig }()
_config.ErupeConfig.RealClientMode = _config.G1
got := equipSkinHistSize()
got := equipSkinHistSize(_config.G1)
if got != 1280 {
t.Errorf("equipSkinHistSize() with G1 = %d, want 1280", got)
t.Errorf("equipSkinHistSize(G1) = %d, want 1280", got)
}
}

View File

@@ -70,7 +70,7 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
characterSaveData.updateSaveDataWithStruct()
}
if characterSaveData.Name == s.Name || _config.ErupeConfig.RealClientMode <= _config.S10 {
if characterSaveData.Name == s.Name || s.server.erupeConfig.RealClientMode <= _config.S10 {
characterSaveData.Save(s)
s.logger.Info("Wrote recompressed savedata back to DB.")
} else {

View File

@@ -65,7 +65,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(dist.Rights)
bf.WriteUint16(dist.TimesAcceptable)
bf.WriteUint16(dist.TimesAccepted)
if _config.ErupeConfig.RealClientMode >= _config.G9 {
if s.server.erupeConfig.RealClientMode >= _config.G9 {
bf.WriteUint16(0) // Unk
}
bf.WriteInt16(dist.MinHR)
@@ -74,29 +74,29 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
bf.WriteInt16(dist.MaxSR)
bf.WriteInt16(dist.MinGR)
bf.WriteInt16(dist.MaxGR)
if _config.ErupeConfig.RealClientMode >= _config.G7 {
if s.server.erupeConfig.RealClientMode >= _config.G7 {
bf.WriteUint8(0) // Unk
}
if _config.ErupeConfig.RealClientMode >= _config.G6 {
if s.server.erupeConfig.RealClientMode >= _config.G6 {
bf.WriteUint16(0) // Unk
}
if _config.ErupeConfig.RealClientMode >= _config.G8 {
if s.server.erupeConfig.RealClientMode >= _config.G8 {
if dist.Selection {
bf.WriteUint8(2) // Selection
} else {
bf.WriteUint8(0)
}
}
if _config.ErupeConfig.RealClientMode >= _config.G7 {
if s.server.erupeConfig.RealClientMode >= _config.G7 {
bf.WriteUint16(0) // Unk
bf.WriteUint16(0) // Unk
}
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if s.server.erupeConfig.RealClientMode >= _config.G10 {
bf.WriteUint8(0) // Unk
}
ps.Uint8(bf, dist.EventName, true)
k := 6
if _config.ErupeConfig.RealClientMode >= _config.G8 {
if s.server.erupeConfig.RealClientMode >= _config.G8 {
k = 13
}
for i := 0; i < 6; i++ {
@@ -105,7 +105,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(0)
}
}
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
if s.server.erupeConfig.RealClientMode >= _config.Z2 {
i := uint8(0)
bf.WriteUint8(i)
if i <= 10 {
@@ -154,7 +154,7 @@ func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint8(item.ItemType)
bf.WriteUint32(item.ItemID)
bf.WriteUint32(item.Quantity)
if _config.ErupeConfig.RealClientMode >= _config.G8 {
if s.server.erupeConfig.RealClientMode >= _config.G8 {
bf.WriteUint32(item.ID)
}
}

View File

@@ -69,7 +69,7 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
err := s.server.db.QueryRowx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1`, t).StructScan(&temp)
if err != nil || temp.StartTime.IsZero() {
weapons := token.RNG.Intn(s.server.erupeConfig.GameplayOptions.MaxFeatureWeapons-s.server.erupeConfig.GameplayOptions.MinFeatureWeapons+1) + s.server.erupeConfig.GameplayOptions.MinFeatureWeapons
temp = generateFeatureWeapons(weapons)
temp = generateFeatureWeapons(weapons, s.server.erupeConfig.RealClientMode)
temp.StartTime = t
if _, err := s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures); err != nil {
s.logger.Error("Failed to insert feature weapon", zap.Error(err))
@@ -89,15 +89,15 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func generateFeatureWeapons(count int) activeFeature {
func generateFeatureWeapons(count int, mode _config.Mode) activeFeature {
_max := 14
if _config.ErupeConfig.RealClientMode < _config.ZZ {
if mode < _config.ZZ {
_max = 13
}
if _config.ErupeConfig.RealClientMode < _config.G10 {
if mode < _config.G10 {
_max = 12
}
if _config.ErupeConfig.RealClientMode < _config.GG {
if mode < _config.GG {
_max = 11
}
if count > _max {

View File

@@ -4,6 +4,7 @@ import (
"math/bits"
"testing"
_config "erupe-ce/config"
"erupe-ce/network/mhfpacket"
)
@@ -121,7 +122,7 @@ func TestGenerateFeatureWeapons(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := generateFeatureWeapons(tt.count)
result := generateFeatureWeapons(tt.count, _config.ZZ)
// Result should be non-zero for positive counts
if tt.count > 0 && result.ActiveFeatures == 0 {
@@ -142,7 +143,7 @@ func TestGenerateFeatureWeapons_Randomness(t *testing.T) {
iterations := 100
for i := 0; i < iterations; i++ {
result := generateFeatureWeapons(5)
result := generateFeatureWeapons(5, _config.ZZ)
results[result.ActiveFeatures]++
}
@@ -153,7 +154,7 @@ func TestGenerateFeatureWeapons_Randomness(t *testing.T) {
}
func TestGenerateFeatureWeapons_ZeroCount(t *testing.T) {
result := generateFeatureWeapons(0)
result := generateFeatureWeapons(0, _config.ZZ)
// Should return 0 for no weapons
if result.ActiveFeatures != 0 {
@@ -180,7 +181,7 @@ func TestGenerateFeatureWeapons_BitCount(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := generateFeatureWeapons(tt.count)
result := generateFeatureWeapons(tt.count, _config.ZZ)
setBits := bits.OnesCount32(result.ActiveFeatures)
if setBits != tt.wantBits {
t.Errorf("Set bits = %d, want %d (ActiveFeatures=0b%032b)",
@@ -194,7 +195,7 @@ func TestGenerateFeatureWeapons_BitCount(t *testing.T) {
// bits 0-13 (no bits above bit 13 should be set).
func TestGenerateFeatureWeapons_BitsInRange(t *testing.T) {
for i := 0; i < 50; i++ {
result := generateFeatureWeapons(7)
result := generateFeatureWeapons(7, _config.ZZ)
// Bits 14+ should never be set
if result.ActiveFeatures&^uint32(0x3FFF) != 0 {
t.Errorf("Bits above 13 are set: 0x%08X", result.ActiveFeatures)
@@ -205,7 +206,7 @@ func TestGenerateFeatureWeapons_BitsInRange(t *testing.T) {
// TestGenerateFeatureWeapons_MaxYieldsAllBits verifies that requesting 14
// weapons sets exactly bits 0-13 (the value 16383 = 0x3FFF).
func TestGenerateFeatureWeapons_MaxYieldsAllBits(t *testing.T) {
result := generateFeatureWeapons(14)
result := generateFeatureWeapons(14, _config.ZZ)
if result.ActiveFeatures != 0x3FFF {
t.Errorf("ActiveFeatures = 0x%04X, want 0x3FFF (all 14 bits set)", result.ActiveFeatures)
}
@@ -214,7 +215,7 @@ func TestGenerateFeatureWeapons_MaxYieldsAllBits(t *testing.T) {
// TestGenerateFeatureWeapons_StartTimeZero verifies that the returned
// activeFeature has a zero StartTime (not set by generateFeatureWeapons).
func TestGenerateFeatureWeapons_StartTimeZero(t *testing.T) {
result := generateFeatureWeapons(5)
result := generateFeatureWeapons(5, _config.ZZ)
if !result.StartTime.IsZero() {
t.Errorf("StartTime should be zero, got %v", result.StartTime)
}

View File

@@ -276,7 +276,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint16(trial.Locale)
bf.WriteUint16(trial.Reward)
bf.WriteInt16(FestivalColorCodes[trial.Monopoly])
if _config.ErupeConfig.RealClientMode >= _config.F4 { // Not in S6.0
if s.server.erupeConfig.RealClientMode >= _config.F4 { // Not in S6.0
bf.WriteUint16(trial.Unk)
}
}
@@ -320,13 +320,13 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint16(reward.Quantity)
bf.WriteUint16(reward.ItemID)
// Confirmed present in G3 via Wii U disassembly of import_festa_info
if _config.ErupeConfig.RealClientMode >= _config.G3 {
if s.server.erupeConfig.RealClientMode >= _config.G3 {
bf.WriteUint16(reward.MinHR)
bf.WriteUint16(reward.MinSR)
bf.WriteUint8(reward.MinGR)
}
}
if _config.ErupeConfig.RealClientMode <= _config.G61 {
if s.server.erupeConfig.RealClientMode <= _config.G61 {
if s.server.erupeConfig.GameplayOptions.MaximumFP > 0xFFFF {
s.server.erupeConfig.GameplayOptions.MaximumFP = 0xFFFF
}
@@ -393,7 +393,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint16(100) // Normal rate
bf.WriteUint16(50) // 50% penalty
if _config.ErupeConfig.RealClientMode >= _config.G52 {
if s.server.erupeConfig.RealClientMode >= _config.G52 {
ps.Uint16(bf, "", false)
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
@@ -480,7 +480,7 @@ func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint16(0) // Unk
for _, member := range validMembers {
bf.WriteUint32(member.CharID)
if _config.ErupeConfig.RealClientMode <= _config.Z1 {
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
bf.WriteUint16(uint16(member.Souls))
bf.WriteUint16(0)
} else {

View File

@@ -223,14 +223,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(s.server.erupeConfig.RealClientMode))
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(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(alliance.SubGuild1.MemberCount)
ps.Uint16(bf, alliance.SubGuild1.Name, true)
ps.Uint16(bf, alliance.SubGuild1.LeaderName, true)
@@ -238,7 +238,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(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(alliance.SubGuild2.MemberCount)
ps.Uint16(bf, alliance.SubGuild2.Name, true)
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)

View File

@@ -51,7 +51,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(guild.ID)
bf.WriteUint32(guild.LeaderCharID)
bf.WriteUint16(guild.Rank())
bf.WriteUint16(guild.Rank(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(guild.MemberCount)
bf.WriteUint8(guild.MainMotto)
@@ -114,7 +114,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
limit := s.server.erupeConfig.GameplayOptions.ClanMemberLimits[0][1]
for _, j := range s.server.erupeConfig.GameplayOptions.ClanMemberLimits {
if guild.Rank() >= uint16(j[0]) {
if guild.Rank(s.server.erupeConfig.RealClientMode) >= uint16(j[0]) {
limit = j[1]
}
}
@@ -155,7 +155,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.ParentGuild.Rank())
bf.WriteUint16(alliance.ParentGuild.Rank(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(alliance.ParentGuild.MemberCount)
ps.Uint16(bf, alliance.ParentGuild.Name, true)
ps.Uint16(bf, alliance.ParentGuild.LeaderName, true)
@@ -167,7 +167,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.SubGuild1.Rank())
bf.WriteUint16(alliance.SubGuild1.Rank(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(alliance.SubGuild1.MemberCount)
ps.Uint16(bf, alliance.SubGuild1.Name, true)
ps.Uint16(bf, alliance.SubGuild1.LeaderName, true)
@@ -180,7 +180,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} else {
bf.WriteUint16(0)
}
bf.WriteUint16(alliance.SubGuild2.Rank())
bf.WriteUint16(alliance.SubGuild2.Rank(s.server.erupeConfig.RealClientMode))
bf.WriteUint16(alliance.SubGuild2.MemberCount)
ps.Uint16(bf, alliance.SubGuild2.Name, true)
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)
@@ -460,7 +460,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(s.server.erupeConfig.RealClientMode))
bf.WriteUint32(uint32(guild.CreatedAt.Unix()))
ps.Uint8(bf, guild.Name, true)
ps.Uint8(bf, guild.LeaderName, true)

View File

@@ -117,16 +117,11 @@ func TestGuildRankCalculation(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
originalConfig := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalConfig }()
_config.ErupeConfig.RealClientMode = tt.config
guild := &Guild{
RankRP: tt.rankRP,
}
rank := guild.Rank()
rank := guild.Rank(tt.config)
if rank != tt.wantRank {
t.Errorf("guild rank calculation: got %d, want %d for RP %d", rank, tt.wantRank, tt.rankRP)
}

View File

@@ -65,7 +65,7 @@ func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
func updateRights(s *Session) {
rightsInt := uint32(2)
_ = s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt)
s.courses, rightsInt = mhfcourse.GetCourseStruct(rightsInt)
s.courses, rightsInt = mhfcourse.GetCourseStruct(rightsInt, s.server.erupeConfig.DefaultCourses)
update := &mhfpacket.MsgSysUpdateRight{
ClientRespAckHandle: 0,
Bitfield: rightsInt,

View File

@@ -133,7 +133,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint8(0)
}
bf.WriteUint16(house.HR)
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if s.server.erupeConfig.RealClientMode >= _config.G10 {
bf.WriteUint16(house.GR)
}
ps.Uint8(bf, house.Name, true)
@@ -516,7 +516,7 @@ func warehouseGetEquipment(s *Session, index uint8) []mhfitem.MHFEquipment {
numStacks := box.ReadUint16()
box.ReadUint16() // Unused
for i := 0; i < int(numStacks); i++ {
equipment = append(equipment, mhfitem.ReadWarehouseEquipment(box))
equipment = append(equipment, mhfitem.ReadWarehouseEquipment(box, s.server.erupeConfig.RealClientMode))
}
}
return equipment
@@ -531,7 +531,7 @@ func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) {
bf.WriteBytes(mhfitem.SerializeWarehouseItems(items))
case 1:
equipment := warehouseGetEquipment(s, pkt.BoxIndex)
bf.WriteBytes(mhfitem.SerializeWarehouseEquipment(equipment))
bf.WriteBytes(mhfitem.SerializeWarehouseEquipment(equipment, s.server.erupeConfig.RealClientMode))
}
if bf.Index() > 0 {
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
@@ -602,7 +602,7 @@ func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) {
}
}
serialized := mhfitem.SerializeWarehouseEquipment(fEquip)
serialized := mhfitem.SerializeWarehouseEquipment(fEquip, s.server.erupeConfig.RealClientMode)
dataSize = len(serialized)
s.logger.Debug("Warehouse save request",

View File

@@ -1,6 +1,7 @@
package channelserver
import (
_config "erupe-ce/config"
"erupe-ce/common/mhfitem"
"erupe-ce/common/token"
"testing"
@@ -92,7 +93,7 @@ func TestWarehouseEquipmentSerialization(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Serialize
serialized := mhfitem.SerializeWarehouseEquipment(tt.equipment)
serialized := mhfitem.SerializeWarehouseEquipment(tt.equipment, _config.ZZ)
// Basic validation
if serialized == nil {

View File

@@ -307,7 +307,7 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
{300, 5392, 1, 5392, 3},
{999, 5392, 1, 5392, 4},
}
if _config.ErupeConfig.RealClientMode <= _config.Z1 {
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
for _, reward := range rewards {
if pkt.HR >= reward.HR {
pkt.Item1 = reward.Item1
@@ -320,7 +320,7 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
bf := byteframe.NewByteFrame()
bf.WriteUint16(pkt.HR)
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if s.server.erupeConfig.RealClientMode >= _config.G1 {
bf.WriteUint16(pkt.GR)
}
var stamps, rewardTier, rewardUnk uint16

View File

@@ -79,7 +79,7 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
bf.WriteInt32(s.server.erupeConfig.EarthStatus)
bf.WriteInt32(s.server.erupeConfig.EarthID)
for i, m := range s.server.erupeConfig.EarthMonsters {
if _config.ErupeConfig.RealClientMode <= _config.G9 {
if s.server.erupeConfig.RealClientMode <= _config.G9 {
if i == 3 {
break
}
@@ -156,12 +156,12 @@ func handleMsgMhfGetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfSetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {}
func equipSkinHistSize() int {
func equipSkinHistSize(mode _config.Mode) int {
size := 3200
if _config.ErupeConfig.RealClientMode <= _config.Z2 {
if mode <= _config.Z2 {
size = 2560
}
if _config.ErupeConfig.RealClientMode <= _config.Z1 {
if mode <= _config.Z1 {
size = 1280
}
return size
@@ -169,7 +169,7 @@ func equipSkinHistSize() int {
func handleMsgMhfGetEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetEquipSkinHist)
size := equipSkinHistSize()
size := equipSkinHistSize(s.server.erupeConfig.RealClientMode)
var data []byte
err := s.server.db.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data)
if err != nil {
@@ -181,7 +181,7 @@ func handleMsgMhfGetEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateEquipSkinHist)
size := equipSkinHistSize()
size := equipSkinHistSize(s.server.erupeConfig.RealClientMode)
var data []byte
err := s.server.db.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data)
if err != nil {

View File

@@ -49,7 +49,7 @@ func equal(a, b []byte) bool {
}
// BackportQuest converts a quest binary to an older format.
func BackportQuest(data []byte) []byte {
func BackportQuest(data []byte, mode _config.Mode) []byte {
wp := binary.LittleEndian.Uint32(data[0:4]) + 96
rp := wp + 4
for i := uint32(0); i < 6; i++ {
@@ -61,16 +61,16 @@ func BackportQuest(data []byte) []byte {
}
fillLength := uint32(108)
if _config.ErupeConfig.RealClientMode <= _config.S6 {
if mode <= _config.S6 {
fillLength = 44
} else if _config.ErupeConfig.RealClientMode <= _config.F5 {
} else if mode <= _config.F5 {
fillLength = 52
} else if _config.ErupeConfig.RealClientMode <= _config.G101 {
} else if mode <= _config.G101 {
fillLength = 76
}
copy(data[wp:wp+fillLength], data[rp:rp+fillLength])
if _config.ErupeConfig.RealClientMode <= _config.G91 {
if mode <= _config.G91 {
patterns := [][]byte{
{0x0A, 0x00, 0x01, 0x33, 0xD7, 0x00}, // 10% Armor Sphere -> Stone
{0x06, 0x00, 0x02, 0x33, 0xD8, 0x00}, // 6% Armor Sphere+ -> Iron Ore
@@ -87,7 +87,7 @@ func BackportQuest(data []byte) []byte {
}
}
if _config.ErupeConfig.RealClientMode <= _config.S6 {
if mode <= _config.S6 {
binary.LittleEndian.PutUint32(data[16:20], binary.LittleEndian.Uint32(data[8:12]))
}
return data
@@ -133,8 +133,8 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
doAckBufFail(s, pkt.AckHandle, nil)
return
}
if _config.ErupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
data = BackportQuest(decryption.UnpackSimple(data))
if s.server.erupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
data = BackportQuest(decryption.UnpackSimple(data), s.server.erupeConfig.RealClientMode)
}
doAckBufSucceed(s, pkt.AckHandle, data)
}
@@ -230,21 +230,21 @@ func loadQuestFile(s *Session, questId int) []byte {
}
decrypted := decryption.UnpackSimple(file)
if _config.ErupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
decrypted = BackportQuest(decrypted)
if s.server.erupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
decrypted = BackportQuest(decrypted, s.server.erupeConfig.RealClientMode)
}
fileBytes := byteframe.NewByteFrameFromBytes(decrypted)
fileBytes.SetLE()
_, _ = fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
bodyLength := 320
if _config.ErupeConfig.RealClientMode <= _config.S6 {
if s.server.erupeConfig.RealClientMode <= _config.S6 {
bodyLength = 160
} else if _config.ErupeConfig.RealClientMode <= _config.F5 {
} else if s.server.erupeConfig.RealClientMode <= _config.F5 {
bodyLength = 168
} else if _config.ErupeConfig.RealClientMode <= _config.G101 {
} else if s.server.erupeConfig.RealClientMode <= _config.G101 {
bodyLength = 192
} else if _config.ErupeConfig.RealClientMode <= _config.Z1 {
} else if s.server.erupeConfig.RealClientMode <= _config.Z1 {
bodyLength = 224
}
@@ -318,7 +318,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
bf.WriteBool(true)
}
bf.WriteUint16(0) // Unk
if _config.ErupeConfig.RealClientMode >= _config.G2 {
if s.server.erupeConfig.RealClientMode >= _config.G2 {
bf.WriteUint32(mark)
}
bf.WriteUint16(0) // Unk
@@ -616,23 +616,23 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
tuneValues = temp
tuneLimit := 770
if _config.ErupeConfig.RealClientMode <= _config.G1 {
if s.server.erupeConfig.RealClientMode <= _config.G1 {
tuneLimit = 256
} else if _config.ErupeConfig.RealClientMode <= _config.G3 {
} else if s.server.erupeConfig.RealClientMode <= _config.G3 {
tuneLimit = 283
} else if _config.ErupeConfig.RealClientMode <= _config.GG {
} else if s.server.erupeConfig.RealClientMode <= _config.GG {
tuneLimit = 315
} else if _config.ErupeConfig.RealClientMode <= _config.G61 {
} else if s.server.erupeConfig.RealClientMode <= _config.G61 {
tuneLimit = 332
} else if _config.ErupeConfig.RealClientMode <= _config.G7 {
} else if s.server.erupeConfig.RealClientMode <= _config.G7 {
tuneLimit = 339
} else if _config.ErupeConfig.RealClientMode <= _config.G81 {
} else if s.server.erupeConfig.RealClientMode <= _config.G81 {
tuneLimit = 396
} else if _config.ErupeConfig.RealClientMode <= _config.G91 {
} else if s.server.erupeConfig.RealClientMode <= _config.G91 {
tuneLimit = 694
} else if _config.ErupeConfig.RealClientMode <= _config.G101 {
} else if s.server.erupeConfig.RealClientMode <= _config.G101 {
tuneLimit = 704
} else if _config.ErupeConfig.RealClientMode <= _config.Z2 {
} else if s.server.erupeConfig.RealClientMode <= _config.Z2 {
tuneLimit = 750
}
if len(tuneValues) > tuneLimit {

View File

@@ -8,13 +8,6 @@ import (
)
func TestBackportQuest_Basic(t *testing.T) {
// Set up config for the test
oldConfig := _config.ErupeConfig
defer func() { _config.ErupeConfig = oldConfig }()
_config.ErupeConfig = &_config.Config{}
_config.ErupeConfig.RealClientMode = _config.ZZ
// Create a quest data buffer large enough for BackportQuest to work with.
// The function reads a uint32 from data[0:4] as offset, then works at offset+96.
// We need at least offset + 96 + 108 + 6*8 bytes.
@@ -27,7 +20,7 @@ func TestBackportQuest_Basic(t *testing.T) {
data[i] = byte(i & 0xFF)
}
result := BackportQuest(data)
result := BackportQuest(data, _config.ZZ)
if result == nil {
t.Fatal("BackportQuest returned nil")
}
@@ -37,12 +30,6 @@ func TestBackportQuest_Basic(t *testing.T) {
}
func TestBackportQuest_S6Mode(t *testing.T) {
oldConfig := _config.ErupeConfig
defer func() { _config.ErupeConfig = oldConfig }()
_config.ErupeConfig = &_config.Config{}
_config.ErupeConfig.RealClientMode = _config.S6
data := make([]byte, 512)
binary.LittleEndian.PutUint32(data[0:4], 0)
@@ -56,7 +43,7 @@ func TestBackportQuest_S6Mode(t *testing.T) {
// Set some values at data[8:12] so we can check they get copied to data[16:20]
binary.LittleEndian.PutUint32(data[8:12], 0xDEADBEEF)
result := BackportQuest(data)
result := BackportQuest(data, _config.S6)
if result == nil {
t.Fatal("BackportQuest returned nil")
}
@@ -69,12 +56,6 @@ func TestBackportQuest_S6Mode(t *testing.T) {
}
func TestBackportQuest_G91Mode_PatternReplacement(t *testing.T) {
oldConfig := _config.ErupeConfig
defer func() { _config.ErupeConfig = oldConfig }()
_config.ErupeConfig = &_config.Config{}
_config.ErupeConfig.RealClientMode = _config.G91
data := make([]byte, 512)
binary.LittleEndian.PutUint32(data[0:4], 0)
@@ -86,7 +67,7 @@ func TestBackportQuest_G91Mode_PatternReplacement(t *testing.T) {
data[offset+2] = 0x01
data[offset+3] = 0x33
result := BackportQuest(data)
result := BackportQuest(data, _config.G91)
// After BackportQuest, the pattern's last 2 bytes should be replaced
if result[offset+2] != 0xD7 || result[offset+3] != 0x00 {
@@ -96,32 +77,20 @@ func TestBackportQuest_G91Mode_PatternReplacement(t *testing.T) {
}
func TestBackportQuest_F5Mode(t *testing.T) {
oldConfig := _config.ErupeConfig
defer func() { _config.ErupeConfig = oldConfig }()
_config.ErupeConfig = &_config.Config{}
_config.ErupeConfig.RealClientMode = _config.F5
data := make([]byte, 512)
binary.LittleEndian.PutUint32(data[0:4], 0)
result := BackportQuest(data)
result := BackportQuest(data, _config.F5)
if result == nil {
t.Fatal("BackportQuest returned nil")
}
}
func TestBackportQuest_G101Mode(t *testing.T) {
oldConfig := _config.ErupeConfig
defer func() { _config.ErupeConfig = oldConfig }()
_config.ErupeConfig = &_config.Config{}
_config.ErupeConfig.RealClientMode = _config.G101
data := make([]byte, 512)
binary.LittleEndian.PutUint32(data[0:4], 0)
result := BackportQuest(data)
result := BackportQuest(data, _config.G101)
if result == nil {
t.Fatal("BackportQuest returned nil")
}

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
"erupe-ce/network/mhfpacket"
"os"
"path/filepath"
@@ -61,7 +62,7 @@ func TestBackportQuestBasic(t *testing.T) {
}
}()
result := BackportQuest(data)
result := BackportQuest(data, _config.ZZ)
if result != nil && !tc.verify(result) {
t.Errorf("BackportQuest verification failed for result: %d bytes", len(result))
}
@@ -685,7 +686,7 @@ func BenchmarkBackportQuest(b *testing.B) {
binary.LittleEndian.PutUint32(data[0:4], 100)
for i := 0; i < b.N; i++ {
_ = BackportQuest(data)
_ = BackportQuest(data, _config.ZZ)
}
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"time"
_config "erupe-ce/config"
"erupe-ce/common/mhfitem"
"erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/nullcomp"
@@ -214,7 +215,7 @@ func TestSaveLoad_Warehouse(t *testing.T) {
}
// Serialize and save to warehouse
serializedEquip := mhfitem.SerializeWarehouseEquipment(equipment)
serializedEquip := mhfitem.SerializeWarehouseEquipment(equipment, _config.ZZ)
// Initialize warehouse row then update
_, _ = db.Exec("INSERT INTO warehouse (character_id) VALUES ($1) ON CONFLICT DO NOTHING", charID)
@@ -425,7 +426,7 @@ func TestSaveLoad_CraftedEquipment(t *testing.T) {
}
equipment := []mhfitem.MHFEquipment{equip}
serialized := mhfitem.SerializeWarehouseEquipment(equipment)
serialized := mhfitem.SerializeWarehouseEquipment(equipment, _config.ZZ)
// Save to warehouse
_, _ = db.Exec("INSERT INTO warehouse (character_id) VALUES ($1) ON CONFLICT DO NOTHING", charID)

View File

@@ -378,7 +378,7 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysRecordLog)
if _config.ErupeConfig.RealClientMode == _config.ZZ {
if s.server.erupeConfig.RealClientMode == _config.ZZ {
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
_, _ = bf.Seek(32, 0)
var val uint8
@@ -536,7 +536,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
resp.WriteUint16(uint16(len(r.userBin3)))
// TODO: This case might be <=G2
if _config.ErupeConfig.RealClientMode <= _config.G1 {
if s.server.erupeConfig.RealClientMode <= _config.G1 {
resp.WriteBytes(make([]byte, 8))
} else {
resp.WriteBytes(make([]byte, 40))
@@ -566,7 +566,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
case 0:
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.RankRestriction = bf.ReadInt16()
} else {
findPartyParams.RankRestriction = int16(bf.ReadInt8())
@@ -575,7 +575,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
case 1:
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Targets = append(findPartyParams.Targets, bf.ReadInt16())
} else {
findPartyParams.Targets = append(findPartyParams.Targets, int16(bf.ReadInt8()))
@@ -585,7 +585,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
var value int16
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
value = bf.ReadInt16()
} else {
value = int16(bf.ReadInt8())
@@ -606,7 +606,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
case 3: // Unknown
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Unk0 = append(findPartyParams.Unk0, bf.ReadInt16())
} else {
findPartyParams.Unk0 = append(findPartyParams.Unk0, int16(bf.ReadInt8()))
@@ -615,7 +615,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
case 4: // Looking for n or already have n
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.Unk1 = append(findPartyParams.Unk1, bf.ReadInt16())
} else {
findPartyParams.Unk1 = append(findPartyParams.Unk1, int16(bf.ReadInt8()))
@@ -624,7 +624,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
case 5:
values := bf.ReadUint8()
for i := uint8(0); i < values; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
findPartyParams.QuestID = append(findPartyParams.QuestID, bf.ReadInt16())
} else {
findPartyParams.QuestID = append(findPartyParams.QuestID, int16(bf.ReadInt8()))
@@ -661,15 +661,15 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
_, _ = sb3.Seek(4, 0)
stageDataParams := 7
if _config.ErupeConfig.RealClientMode <= _config.G10 {
if s.server.erupeConfig.RealClientMode <= _config.G10 {
stageDataParams = 4
} else if _config.ErupeConfig.RealClientMode <= _config.Z1 {
} else if s.server.erupeConfig.RealClientMode <= _config.Z1 {
stageDataParams = 6
}
var stageData []int16
for i := 0; i < stageDataParams; i++ {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
stageData = append(stageData, sb3.ReadInt16())
} else {
stageData = append(stageData, int16(sb3.ReadInt8()))
@@ -746,7 +746,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
resp.WriteUint8(uint8(len(sr.rawBinData1)))
for i := range sr.stageData {
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
if s.server.erupeConfig.RealClientMode >= _config.Z1 {
resp.WriteInt16(sr.stageData[i])
} else {
resp.WriteInt8(int8(sr.stageData[i]))

View File

@@ -25,11 +25,11 @@ type ShopItem struct {
RoadFatalis uint16 `db:"road_fatalis"`
}
func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem, mode _config.Mode) {
bf.WriteUint16(uint16(len(items)))
bf.WriteUint16(uint16(len(items)))
for _, item := range items {
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
if mode >= _config.Z2 {
bf.WriteUint32(item.ID)
}
bf.WriteUint32(item.ItemID)
@@ -37,19 +37,19 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
bf.WriteUint16(item.Quantity)
bf.WriteUint16(item.MinHR)
bf.WriteUint16(item.MinSR)
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
if mode >= _config.Z2 {
bf.WriteUint16(item.MinGR)
}
bf.WriteUint8(0) // Unk
bf.WriteUint8(item.StoreLevel)
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
if mode >= _config.Z2 {
bf.WriteUint16(item.MaxQuantity)
bf.WriteUint16(item.UsedQuantity)
}
if _config.ErupeConfig.RealClientMode == _config.Z1 {
if mode == _config.Z1 {
bf.WriteUint8(uint8(item.RoadFloors))
bf.WriteUint8(uint8(item.RoadFatalis))
} else if _config.ErupeConfig.RealClientMode >= _config.Z2 {
} else if mode >= _config.Z2 {
bf.WriteUint16(item.RoadFloors)
bf.WriteUint16(item.RoadFatalis)
}
@@ -90,7 +90,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
switch pkt.ShopType {
case 1: // Running gachas
// Fundamentally, gacha works completely differently, just hide it for now.
if _config.ErupeConfig.RealClientMode <= _config.G7 {
if s.server.erupeConfig.RealClientMode <= _config.G7 {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
@@ -123,7 +123,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
ps.Uint8(bf, g.Name, true)
ps.Uint8(bf, g.URLBanner, false)
ps.Uint8(bf, g.URLFeature, false)
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if s.server.erupeConfig.RealClientMode >= _config.G10 {
bf.WriteBool(g.Wide)
ps.Uint8(bf, g.URLThumbnail, false)
}
@@ -133,7 +133,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint16(0)
}
bf.WriteUint8(g.GachaType)
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if s.server.erupeConfig.RealClientMode >= _config.G10 {
bf.WriteBool(g.Hidden)
}
}
@@ -223,7 +223,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
if len(items) > int(pkt.Limit) {
items = items[:pkt.Limit]
}
writeShopItems(bf, items)
writeShopItems(bf, items, s.server.erupeConfig.RealClientMode)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
}
@@ -303,7 +303,7 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) {
exchanges = append(exchanges, exchange)
}
}
if _config.ErupeConfig.RealClientMode <= _config.Z2 {
if s.server.erupeConfig.RealClientMode <= _config.Z2 {
bf.WriteUint8(uint8(len(exchanges)))
bf.WriteUint8(uint8(buyables))
} else {

View File

@@ -4,13 +4,14 @@ import (
"testing"
"erupe-ce/common/byteframe"
_config "erupe-ce/config"
)
func TestWriteShopItems_Empty(t *testing.T) {
bf := byteframe.NewByteFrame()
items := []ShopItem{}
writeShopItems(bf, items)
writeShopItems(bf, items, _config.ZZ)
result := byteframe.NewByteFrameFromBytes(bf.Data())
count1 := result.ReadUint16()
@@ -43,7 +44,7 @@ func TestWriteShopItems_SingleItem(t *testing.T) {
},
}
writeShopItems(bf, items)
writeShopItems(bf, items, _config.ZZ)
result := byteframe.NewByteFrameFromBytes(bf.Data())
count1 := result.ReadUint16()
@@ -117,7 +118,7 @@ func TestWriteShopItems_MultipleItems(t *testing.T) {
{ID: 3, ItemID: 300, Cost: 2000, Quantity: 1},
}
writeShopItems(bf, items)
writeShopItems(bf, items, _config.ZZ)
result := byteframe.NewByteFrameFromBytes(bf.Data())
count1 := result.ReadUint16()

View File

@@ -75,7 +75,7 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
}
}
if _config.ErupeConfig.RealClientMode <= _config.G7 {
if s.server.erupeConfig.RealClientMode <= _config.G7 {
towerInfo.Level = towerInfo.Level[:1]
}

View File

@@ -621,16 +621,13 @@ func IntegrationTest_ClientVersionCompatibility(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
originalVersion := _config.ErupeConfig.RealClientMode
defer func() { _config.ErupeConfig.RealClientMode = originalVersion }()
_config.ErupeConfig.RealClientMode = tt.clientVersion
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := &Session{
sendPackets: make(chan packet, 100),
server: &Server{
erupeConfig: _config.ErupeConfig,
server: &Server{
erupeConfig: &_config.Config{
RealClientMode: tt.clientVersion,
},
},
}
s.cryptConn = mock

View File

@@ -35,6 +35,7 @@ type CharacterSaveData struct {
CharID uint32
Name string
IsNewCharacter bool
Mode _config.Mode
Pointers map[SavePointer]int
Gender bool
@@ -56,9 +57,9 @@ type CharacterSaveData struct {
decompSave []byte
}
func getPointers() map[SavePointer]int {
func getPointers(mode _config.Mode) map[SavePointer]int {
pointers := map[SavePointer]int{pGender: 81, lBookshelfData: 5576}
switch _config.ErupeConfig.RealClientMode {
switch mode {
case _config.ZZ:
pointers[pPlaytime] = 128356
pointers[pWeaponID] = 128522
@@ -114,9 +115,9 @@ func getPointers() map[SavePointer]int {
pointers[pGardenData] = 26424
pointers[pRP] = 26614
}
if _config.ErupeConfig.RealClientMode == _config.G5 {
if mode == _config.G5 {
pointers[lBookshelfData] = 5548
} else if _config.ErupeConfig.RealClientMode <= _config.GG {
} else if mode <= _config.GG {
pointers[lBookshelfData] = 4520
}
return pointers
@@ -144,10 +145,10 @@ func (save *CharacterSaveData) Decompress() error {
func (save *CharacterSaveData) updateSaveDataWithStruct() {
rpBytes := make([]byte, 2)
binary.LittleEndian.PutUint16(rpBytes, save.RP)
if _config.ErupeConfig.RealClientMode >= _config.F4 {
if save.Mode >= _config.F4 {
copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes)
}
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if save.Mode >= _config.G10 {
copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF)
}
}
@@ -161,7 +162,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
save.Gender = false
}
if !save.IsNewCharacter {
if _config.ErupeConfig.RealClientMode >= _config.S6 {
if save.Mode >= _config.S6 {
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]
@@ -173,12 +174,12 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
save.WeaponType = save.decompSave[save.Pointers[pWeaponType]]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2])
save.HR = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHR] : save.Pointers[pHR]+2])
if _config.ErupeConfig.RealClientMode >= _config.G1 {
if save.Mode >= _config.G1 {
if save.HR == uint16(999) {
save.GR = grpToGR(int(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4])))
}
}
if _config.ErupeConfig.RealClientMode >= _config.G10 {
if save.Mode >= _config.G10 {
save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8]
}
}

View File

@@ -176,7 +176,7 @@ func TestSessionLifecycle_WarehouseDataPersistence(t *testing.T) {
createTestEquipmentItem(102, 3),
}
serializedEquip := mhfitem.SerializeWarehouseEquipment(equipment)
serializedEquip := mhfitem.SerializeWarehouseEquipment(equipment, _config.ZZ)
// Save to warehouse directly (simulating a save handler)
_, _ = db.Exec("INSERT INTO warehouse (character_id) VALUES ($1) ON CONFLICT DO NOTHING", charID)
@@ -586,7 +586,9 @@ func createTestServerWithDB(t *testing.T, db *sqlx.DB) *Server {
userBinaryParts: make(map[userBinaryPartID][]byte),
minidataParts: make(map[uint32][]byte),
semaphore: make(map[string]*Semaphore),
erupeConfig: _config.ErupeConfig,
erupeConfig: &_config.Config{
RealClientMode: _config.ZZ,
},
isShuttingDown: false,
}

View File

@@ -145,6 +145,8 @@ func (s *Server) Start() error {
}
s.listener = l
initCommands(s.erupeConfig.Commands, s.logger)
go s.acceptClients()
go s.manageSessions()
go s.invalidateSessions()

View File

@@ -81,9 +81,9 @@ func NewSession(server *Server, conn net.Conn) *Session {
logger: server.logger.Named(conn.RemoteAddr().String()),
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, server.erupeConfig.RealClientMode),
sendPackets: make(chan packet, 20),
clientContext: &clientctx.ClientContext{},
clientContext: &clientctx.ClientContext{RealClientMode: server.erupeConfig.RealClientMode},
lastPacket: time.Now(),
objectID: server.getObjectId(),
sessionStart: TimeAdjusted().Unix(),

View File

@@ -104,7 +104,7 @@ func (s *Server) handleEntranceServerConnection(conn net.Conn) {
}
// Create a new encrypted connection handler and read a packet from it.
cc := network.NewCryptConn(conn)
cc := network.NewCryptConn(conn, s.erupeConfig.RealClientMode)
pkt, err := cc.ReadPacket()
if err != nil {
s.logger.Warn("Error reading packet", zap.Error(err))

View File

@@ -63,8 +63,8 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
for channelIdx, ci := range si.Channels {
sid := (serverIdx<<8 | 4096) + (channelIdx | 16)
if _config.ErupeConfig.DebugOptions.ProxyPort != 0 {
bf.WriteUint16(_config.ErupeConfig.DebugOptions.ProxyPort)
if config.DebugOptions.ProxyPort != 0 {
bf.WriteUint16(config.DebugOptions.ProxyPort)
} else {
bf.WriteUint16(ci.Port)
}

View File

@@ -105,7 +105,7 @@ func (s *Server) getUserRights(uid uint32) uint32 {
var rights uint32
if uid != 0 {
_ = s.db.QueryRow("SELECT rights FROM users WHERE id=$1", uid).Scan(&rights)
_, rights = mhfcourse.GetCourseStruct(rights)
_, rights = mhfcourse.GetCourseStruct(rights, s.erupeConfig.DefaultCourses)
}
return rights
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"time"
"erupe-ce/config"
"github.com/DATA-DOG/go-sqlmock"
"github.com/jmoiron/sqlx"
"go.uber.org/zap"
@@ -301,8 +302,9 @@ func newTestServerWithMock(t *testing.T) (*Server, sqlmock.Sqlmock) {
sqlxDB := sqlx.NewDb(db, "sqlmock")
server := &Server{
logger: zap.NewNop(),
db: sqlxDB,
logger: zap.NewNop(),
db: sqlxDB,
erupeConfig: &_config.Config{},
}
return server, mock

View File

@@ -75,7 +75,7 @@ func TestSessionStruct(t *testing.T) {
logger: logger,
server: nil,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, _config.ZZ),
}
if s.logger != logger {
@@ -145,7 +145,7 @@ func TestHandlePacketUnknownRequest(t *testing.T) {
logger: logger,
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, _config.ZZ),
}
bf := byteframe.NewByteFrame()
@@ -176,7 +176,7 @@ func TestHandlePacketWithDevModeLogging(t *testing.T) {
logger: logger,
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, _config.ZZ),
}
bf := byteframe.NewByteFrame()
@@ -214,7 +214,7 @@ func TestHandlePacketRequestTypes(t *testing.T) {
logger: logger,
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, _config.ZZ),
}
bf := byteframe.NewByteFrame()
@@ -324,7 +324,7 @@ func TestMockConnDeadlines(t *testing.T) {
func TestSessionWithCryptConn(t *testing.T) {
conn := newMockConn()
cryptConn := network.NewCryptConn(conn)
cryptConn := network.NewCryptConn(conn, _config.ZZ)
if cryptConn == nil {
t.Fatal("NewCryptConn() returned nil")
@@ -361,7 +361,7 @@ func TestSessionWorkWithDevModeLogging(t *testing.T) {
logger: logger,
server: server,
rawConn: serverConn,
cryptConn: network.NewCryptConn(serverConn),
cryptConn: network.NewCryptConn(serverConn, _config.ZZ),
}
_ = clientConn.Close()
@@ -386,7 +386,7 @@ func TestSessionWorkWithEmptyRead(t *testing.T) {
logger: logger,
server: server,
rawConn: serverConn,
cryptConn: network.NewCryptConn(serverConn),
cryptConn: network.NewCryptConn(serverConn, _config.ZZ),
}
_ = clientConn.Close()

View File

@@ -101,7 +101,7 @@ func (s *Server) handleConnection(conn net.Conn) {
logger: s.logger,
server: s,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
cryptConn: network.NewCryptConn(conn, s.erupeConfig.RealClientMode),
}
// Do the session's work.