add parsing tests to ls_structs
This commit is contained in:
parent
2912f871a5
commit
231f16e9de
641
internal/packets/ls_structs/ls_structs_test.go
Normal file
641
internal/packets/ls_structs/ls_structs_test.go
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
package ls_structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"eq2emu/internal/packets/parser"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeleteCharacterRequest(t *testing.T) {
|
||||||
|
// CharID=12345, ServerID=1, Unknown=0, Name="TestChar"
|
||||||
|
data := []byte{
|
||||||
|
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||||
|
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Unknown = 0
|
||||||
|
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet DeleteCharacterRequest
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.CharID != 12345 {
|
||||||
|
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||||
|
}
|
||||||
|
if packet.ServerID != 1 {
|
||||||
|
t.Errorf("Expected ServerID=1, got %d", packet.ServerID)
|
||||||
|
}
|
||||||
|
if packet.Name.Data != "TestChar" {
|
||||||
|
t.Errorf("Expected Name='TestChar', got '%s'", packet.Name.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteCharacterResponse(t *testing.T) {
|
||||||
|
// Response=1, ServerID=1, CharID=12345, AccountID=54321, Name="TestChar", MaxCharacters=8
|
||||||
|
data := []byte{
|
||||||
|
0x01, // Response = 1
|
||||||
|
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||||
|
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||||
|
0x08, 0x00, 0x00, 0x00, // MaxCharacters = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet DeleteCharacterResponse
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.Response != 1 {
|
||||||
|
t.Errorf("Expected Response=1, got %d", packet.Response)
|
||||||
|
}
|
||||||
|
if packet.CharID != 12345 {
|
||||||
|
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||||
|
}
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
if packet.MaxCharacters != 8 {
|
||||||
|
t.Errorf("Expected MaxCharacters=8, got %d", packet.MaxCharacters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateCharacterReplyV1(t *testing.T) {
|
||||||
|
// AccountID=54321, Response=0, Name="NewChar"
|
||||||
|
data := []byte{
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x00, // Response = 0
|
||||||
|
0x07, 0x00, 'N', 'e', 'w', 'C', 'h', 'a', 'r', // Name = "NewChar"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet CreateCharacterReplyV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
if packet.Response != 0 {
|
||||||
|
t.Errorf("Expected Response=0, got %d", packet.Response)
|
||||||
|
}
|
||||||
|
if packet.Name.Data != "NewChar" {
|
||||||
|
t.Errorf("Expected Name='NewChar', got '%s'", packet.Name.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateCharacterReplyV1189(t *testing.T) {
|
||||||
|
// AccountID=54321, Unknown=100, Response=0, Name="NewChar"
|
||||||
|
data := []byte{
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x64, 0x00, 0x00, 0x00, // Unknown = 100
|
||||||
|
0x00, // Response = 0
|
||||||
|
0x07, 0x00, 'N', 'e', 'w', 'C', 'h', 'a', 'r', // Name = "NewChar"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet CreateCharacterReplyV1189
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
if packet.Unknown != 100 {
|
||||||
|
t.Errorf("Expected Unknown=100, got %d", packet.Unknown)
|
||||||
|
}
|
||||||
|
if packet.Response != 0 {
|
||||||
|
t.Errorf("Expected Response=0, got %d", packet.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginRequestV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
// SessionID = "session123"
|
||||||
|
0x0A, 0x00, 's', 'e', 's', 's', 'i', 'o', 'n', '1', '2', '3',
|
||||||
|
// SessionRecycleToken = "token456"
|
||||||
|
0x08, 0x00, 't', 'o', 'k', 'e', 'n', '4', '5', '6',
|
||||||
|
// Username = "testuser"
|
||||||
|
0x08, 0x00, 't', 'e', 's', 't', 'u', 's', 'e', 'r',
|
||||||
|
// Password = "testpass"
|
||||||
|
0x08, 0x00, 't', 'e', 's', 't', 'p', 'a', 's', 's',
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AcctNum = 54321
|
||||||
|
0x39, 0x30, 0x00, 0x00, // PassCode = 12345
|
||||||
|
0xDC, 0x05, // Version = 1500
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginRequestV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.SessionID.Data != "session123" {
|
||||||
|
t.Errorf("Expected SessionID='session123', got '%s'", packet.SessionID.Data)
|
||||||
|
}
|
||||||
|
if packet.Username.Data != "testuser" {
|
||||||
|
t.Errorf("Expected Username='testuser', got '%s'", packet.Username.Data)
|
||||||
|
}
|
||||||
|
if packet.AcctNum != 54321 {
|
||||||
|
t.Errorf("Expected AcctNum=54321, got %d", packet.AcctNum)
|
||||||
|
}
|
||||||
|
if packet.Version != 1500 {
|
||||||
|
t.Errorf("Expected Version=1500, got %d", packet.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginByNumRequestV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x39, 0x30, 0x00, 0x00, // AccessCode = 12345
|
||||||
|
0xDC, 0x05, // Version = 1500
|
||||||
|
// Unknown2 = [1, 2, 3, 4, 5]
|
||||||
|
0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginByNumRequestV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
if packet.AccessCode != 12345 {
|
||||||
|
t.Errorf("Expected AccessCode=12345, got %d", packet.AccessCode)
|
||||||
|
}
|
||||||
|
if packet.Version != 1500 {
|
||||||
|
t.Errorf("Expected Version=1500, got %d", packet.Version)
|
||||||
|
}
|
||||||
|
if len(packet.Unknown2) != 5 {
|
||||||
|
t.Errorf("Expected Unknown2 length=5, got %d", len(packet.Unknown2))
|
||||||
|
}
|
||||||
|
if packet.Unknown2[0] != 1 || packet.Unknown2[4] != 5 {
|
||||||
|
t.Errorf("Expected Unknown2=[1,2,3,4,5], got %v", packet.Unknown2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlayRequestV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||||
|
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet PlayRequestV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.CharID != 12345 {
|
||||||
|
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||||
|
}
|
||||||
|
if packet.Name.Data != "TestChar" {
|
||||||
|
t.Errorf("Expected Name='TestChar', got '%s'", packet.Name.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlayResponseV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x01, // Response = 1
|
||||||
|
0x09, '1', '2', '7', '.', '0', '.', '0', '.', '1', // Server = "127.0.0.1"
|
||||||
|
0xC4, 0x09, // Port = 2500
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x39, 0x30, 0x00, 0x00, // AccessCode = 12345
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet PlayResponseV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.Response != 1 {
|
||||||
|
t.Errorf("Expected Response=1, got %d", packet.Response)
|
||||||
|
}
|
||||||
|
if packet.Server.Data != "127.0.0.1" {
|
||||||
|
t.Errorf("Expected Server='127.0.0.1', got '%s'", packet.Server.Data)
|
||||||
|
}
|
||||||
|
if packet.Port != 2500 {
|
||||||
|
t.Errorf("Expected Port=2500, got %d", packet.Port)
|
||||||
|
}
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWorldListV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x02, // NumWorlds = 2
|
||||||
|
// World 1
|
||||||
|
0x01, 0x00, 0x00, 0x00, // ID = 1
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Name = "Antonia"
|
||||||
|
0x01, // Online = 1
|
||||||
|
0x00, // Locked = 0
|
||||||
|
0x00, // Unknown2 = 0
|
||||||
|
0x00, // Unknown3 = 0
|
||||||
|
0x32, // Load = 50
|
||||||
|
// World 2
|
||||||
|
0x02, 0x00, 0x00, 0x00, // ID = 2
|
||||||
|
0x08, 0x00, 'N', 'a', 'g', 'a', 'f', 'e', 'n', ' ', // Name = "Nagafen "
|
||||||
|
0x01, // Online = 1
|
||||||
|
0x01, // Locked = 1
|
||||||
|
0x00, // Unknown2 = 0
|
||||||
|
0x00, // Unknown3 = 0
|
||||||
|
0x64, // Load = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet WorldListV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.NumWorlds != 2 {
|
||||||
|
t.Errorf("Expected NumWorlds=2, got %d", packet.NumWorlds)
|
||||||
|
}
|
||||||
|
if len(packet.WorldList) != 2 {
|
||||||
|
t.Errorf("Expected 2 worlds, got %d", len(packet.WorldList))
|
||||||
|
}
|
||||||
|
if packet.WorldList[0].Name.Data != "Antonia" {
|
||||||
|
t.Errorf("Expected first world 'Antonia', got '%s'", packet.WorldList[0].Name.Data)
|
||||||
|
}
|
||||||
|
if packet.WorldList[0].Online != 1 {
|
||||||
|
t.Errorf("Expected first world online=1, got %d", packet.WorldList[0].Online)
|
||||||
|
}
|
||||||
|
if packet.WorldList[1].Locked != 1 {
|
||||||
|
t.Errorf("Expected second world locked=1, got %d", packet.WorldList[1].Locked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWorldListV373(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x01, // NumWorlds = 1
|
||||||
|
// World 1
|
||||||
|
0x01, 0x00, 0x00, 0x00, // ID = 1
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Name = "Antonia"
|
||||||
|
0x01, // Tag = 1
|
||||||
|
0x00, // Locked = 0
|
||||||
|
0x00, // Hidden = 0
|
||||||
|
0x00, // Unknown = 0
|
||||||
|
0x64, 0x00, // NumPlayers = 100
|
||||||
|
0x32, // Load = 50
|
||||||
|
0x01, // NumberOnlineFlag = 1
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, // AllowedRaces = 0xFFFFFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet WorldListV373
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.NumWorlds != 1 {
|
||||||
|
t.Errorf("Expected NumWorlds=1, got %d", packet.NumWorlds)
|
||||||
|
}
|
||||||
|
if packet.WorldList[0].NumPlayers != 100 {
|
||||||
|
t.Errorf("Expected NumPlayers=100, got %d", packet.WorldList[0].NumPlayers)
|
||||||
|
}
|
||||||
|
if packet.WorldList[0].AllowedRaces != 0xFFFFFFFF {
|
||||||
|
t.Errorf("Expected AllowedRaces=0xFFFFFFFF, got %d", packet.WorldList[0].AllowedRaces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginReplyMsgV1(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x00, // LoginResponse = 0 (success)
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // WorldName = "Antonia"
|
||||||
|
0x00, // ParentalControlFlag = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[0] = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[1] = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlNext = 0
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginReplyMsgV1
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.LoginResponse != 0 {
|
||||||
|
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||||
|
}
|
||||||
|
if packet.WorldName.Data != "Antonia" {
|
||||||
|
t.Errorf("Expected WorldName='Antonia', got '%s'", packet.WorldName.Data)
|
||||||
|
}
|
||||||
|
if packet.AccountID != 54321 {
|
||||||
|
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginReplyMsgV284WithClassItems(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x00, // LoginResponse = 0
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||||
|
0x00, // ParentalControlFlag = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // CacheSettingAccountID = 54321
|
||||||
|
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||||
|
0x00, // ResetAppearance = 0
|
||||||
|
0x00, // DoNotForceSoga = 0
|
||||||
|
0x00, 0x00, // Unknown5 = 0
|
||||||
|
0x00, // Unknown6 = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||||
|
0x00, 0x00, // Unknown8 (2 bytes)
|
||||||
|
0x01, // Unknown10 = 1 (truthy, so class items will be parsed)
|
||||||
|
0x01, // NumClassItems = 1
|
||||||
|
// ClassItem 1
|
||||||
|
0x05, // ClassID = 5
|
||||||
|
0x01, // NumItems = 1
|
||||||
|
// StartingItem 1
|
||||||
|
0x64, 0x00, // ModelID = 100
|
||||||
|
0x01, // SlotID = 1
|
||||||
|
0x01, // UseColor = 1
|
||||||
|
0x01, // UseHighlightColor = 1
|
||||||
|
0xFF, 0x00, 0x00, // ModelColor = Red
|
||||||
|
0x00, 0xFF, 0x00, // ModelHighlightColor = Green
|
||||||
|
0x00, // UnknownArray2Size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginReplyMsgV284
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.LoginResponse != 0 {
|
||||||
|
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||||
|
}
|
||||||
|
if packet.CacheSettingAccountID != 54321 {
|
||||||
|
t.Errorf("Expected CacheSettingAccountID=54321, got %d", packet.CacheSettingAccountID)
|
||||||
|
}
|
||||||
|
if packet.Unknown10 != 1 {
|
||||||
|
t.Errorf("Expected Unknown10=1, got %d", packet.Unknown10)
|
||||||
|
}
|
||||||
|
if packet.NumClassItems != 1 {
|
||||||
|
t.Errorf("Expected NumClassItems=1, got %d", packet.NumClassItems)
|
||||||
|
}
|
||||||
|
if len(packet.ClassItems) != 1 {
|
||||||
|
t.Errorf("Expected 1 class item, got %d", len(packet.ClassItems))
|
||||||
|
}
|
||||||
|
if packet.ClassItems[0].ClassID != 5 {
|
||||||
|
t.Errorf("Expected ClassID=5, got %d", packet.ClassItems[0].ClassID)
|
||||||
|
}
|
||||||
|
if len(packet.ClassItems[0].StartingItems) != 1 {
|
||||||
|
t.Errorf("Expected 1 starting item, got %d", len(packet.ClassItems[0].StartingItems))
|
||||||
|
}
|
||||||
|
if packet.ClassItems[0].StartingItems[0].ModelID != 100 {
|
||||||
|
t.Errorf("Expected ModelID=100, got %d", packet.ClassItems[0].StartingItems[0].ModelID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginReplyMsgV284WithoutClassItems(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x00, // LoginResponse = 0
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||||
|
0x00, // ParentalControlFlag = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // CacheSettingAccountID = 54321
|
||||||
|
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||||
|
0x00, // ResetAppearance = 0
|
||||||
|
0x00, // DoNotForceSoga = 0
|
||||||
|
0x00, 0x00, // Unknown5 = 0
|
||||||
|
0x00, // Unknown6 = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||||
|
0x00, 0x00, // Unknown8 (2 bytes)
|
||||||
|
0x00, // Unknown10 = 0 (falsy, so class items will be skipped)
|
||||||
|
0x00, // UnknownArray2Size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginReplyMsgV284
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.Unknown10 != 0 {
|
||||||
|
t.Errorf("Expected Unknown10=0, got %d", packet.Unknown10)
|
||||||
|
}
|
||||||
|
if packet.NumClassItems != 0 {
|
||||||
|
t.Errorf("Expected NumClassItems=0 (should be skipped), got %d", packet.NumClassItems)
|
||||||
|
}
|
||||||
|
if len(packet.ClassItems) != 0 {
|
||||||
|
t.Errorf("Expected 0 class items (should be skipped), got %d", len(packet.ClassItems))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionRegistryWithLoginReplyMsg(t *testing.T) {
|
||||||
|
registry := parser.NewVersionRegistry()
|
||||||
|
RegisterLoginServerStructs(registry)
|
||||||
|
|
||||||
|
// Test data for LoginReplyMsgV1
|
||||||
|
data := []byte{
|
||||||
|
0x00, // LoginResponse = 0
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // WorldName = "Antonia"
|
||||||
|
0x00, // ParentalControlFlag = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[0] = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[1] = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlNext = 0
|
||||||
|
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
result, err := parser.ParseWithVersion(registry, "LoginReplyMsg", "1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse with version error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
packet, ok := result.(LoginReplyMsgV1)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("Expected LoginReplyMsgV1 type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.LoginResponse != 0 {
|
||||||
|
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||||
|
}
|
||||||
|
if packet.WorldName.Data != "Antonia" {
|
||||||
|
t.Errorf("Expected WorldName='Antonia', got '%s'", packet.WorldName.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionRegistryFallback(t *testing.T) {
|
||||||
|
registry := parser.NewVersionRegistry()
|
||||||
|
RegisterLoginServerStructs(registry)
|
||||||
|
|
||||||
|
data := []byte{
|
||||||
|
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||||
|
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
|
||||||
|
// Request version 150 (doesn't exist), should fall back to version 1
|
||||||
|
result, err := parser.ParseWithVersion(registry, "PlayRequest", "150")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse with fallback error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should get PlayRequestV1 (nearest lower version)
|
||||||
|
packet, ok := result.(PlayRequestV1)
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected fallback to PlayRequestV1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.CharID != 12345 {
|
||||||
|
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWorldUpdate(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||||
|
0x01, // Up = 1
|
||||||
|
0x00, // Locked = 0
|
||||||
|
0x00, // Unknown1 = 0
|
||||||
|
0x32, // Unknown2 = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet WorldUpdate
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.ServerID != 1 {
|
||||||
|
t.Errorf("Expected ServerID=1, got %d", packet.ServerID)
|
||||||
|
}
|
||||||
|
if packet.Up != 1 {
|
||||||
|
t.Errorf("Expected Up=1, got %d", packet.Up)
|
||||||
|
}
|
||||||
|
if packet.Locked != 0 {
|
||||||
|
t.Errorf("Expected Locked=0, got %d", packet.Locked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoginResponseV60100WithComplexArrays(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
0x00, // LoginResponse = 0
|
||||||
|
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||||
|
0x00, // ParentalControlFlag = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||||
|
0x21, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||||
|
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||||
|
0x00, // ResetAppearance = 0
|
||||||
|
0x00, // DoNotForceSoga = 0
|
||||||
|
0x00, // Unknown4 = 0
|
||||||
|
0x00, 0x00, // Unknown5 = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, // Unknown6 (5 bytes)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||||
|
0x00, 0x00, // Unknown7a = 0
|
||||||
|
0x00, // RaceUnknown = 0
|
||||||
|
0x00, 0x00, 0x00, // Unknown8 (3 bytes)
|
||||||
|
0x00, 0x00, 0x00, // Unknown9 (3 bytes)
|
||||||
|
0x01, // Unknown10 = 1 (enables class items)
|
||||||
|
0x01, // NumClassItems = 1
|
||||||
|
// ClassItem 1
|
||||||
|
0x05, // ClassID = 5
|
||||||
|
0x01, // NumItems = 1
|
||||||
|
// StartingItem 1
|
||||||
|
0x64, 0x00, 0x00, 0x00, // ModelID = 100 (int32 in newer versions)
|
||||||
|
0x01, // SlotID = 1
|
||||||
|
0x01, // UseColor = 1
|
||||||
|
0x01, // UseHighlightColor = 1
|
||||||
|
0xFF, 0x00, 0x00, // ModelColor = Red
|
||||||
|
0x00, 0xFF, 0x00, // ModelHighlightColor = Green
|
||||||
|
0x00, // UnknownArray2Size = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Unknown11 = 0
|
||||||
|
0x00, 0x00, 0x00, 0x00, // SubLevel = 0
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, // RaceFlag = 0xFFFFFFFF
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, // ClassFlag = 0xFFFFFFFF
|
||||||
|
0x08, 0x00, 't', 'e', 's', 't', 'p', 'a', 's', 's', // Password = "testpass"
|
||||||
|
0x08, 0x00, 't', 'e', 's', 't', 'u', 's', 'e', 'r', // Username = "testuser"
|
||||||
|
0x07, 0x00, 's', 'e', 'r', 'v', 'i', 'c', 'e', // Service = "service"
|
||||||
|
0x01, // Unknown12 = 1 (enables Lvl90 class items)
|
||||||
|
0x01, // Lvl90NumClassItems = 1
|
||||||
|
// Lvl90 ClassItem 1
|
||||||
|
0x06, // ClassID = 6
|
||||||
|
0x01, // NumItems = 1
|
||||||
|
// StartingItem 1
|
||||||
|
0x65, 0x00, 0x00, 0x00, // ModelID = 101
|
||||||
|
0x02, // SlotID = 2
|
||||||
|
0x01, // UseColor = 1
|
||||||
|
0x01, // UseHighlightColor = 1
|
||||||
|
0x00, 0xFF, 0x00, // ModelColor = Green
|
||||||
|
0xFF, 0x00, 0x00, // ModelHighlightColor = Red
|
||||||
|
0x01, // Unknown13 = 1 (enables TimeLocked class items)
|
||||||
|
0x01, // TimeLockedNumClassItems = 1
|
||||||
|
// TimeLocked ClassItem 1
|
||||||
|
0x07, // ClassID = 7
|
||||||
|
0x01, // NumItems = 1
|
||||||
|
// StartingItem 1
|
||||||
|
0x66, 0x00, 0x00, 0x00, // ModelID = 102
|
||||||
|
0x03, // SlotID = 3
|
||||||
|
0x00, // UseColor = 0
|
||||||
|
0x00, // UseHighlightColor = 0
|
||||||
|
0x80, 0x80, 0x80, // ModelColor = Gray
|
||||||
|
0x40, 0x40, 0x40, // ModelHighlightColor = Dark gray
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown14 (13 bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := parser.NewParser(data)
|
||||||
|
var packet LoginResponseV60100
|
||||||
|
err := parser.ParseStruct(&packet)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test main class items
|
||||||
|
if len(packet.ClassItems) != 1 {
|
||||||
|
t.Errorf("Expected 1 class item, got %d", len(packet.ClassItems))
|
||||||
|
}
|
||||||
|
if packet.ClassItems[0].ClassID != 5 {
|
||||||
|
t.Errorf("Expected ClassID=5, got %d", packet.ClassItems[0].ClassID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Lvl90 class items
|
||||||
|
if len(packet.Lvl90ClassItems) != 1 {
|
||||||
|
t.Errorf("Expected 1 Lvl90 class item, got %d", len(packet.Lvl90ClassItems))
|
||||||
|
}
|
||||||
|
if packet.Lvl90ClassItems[0].ClassID != 6 {
|
||||||
|
t.Errorf("Expected Lvl90 ClassID=6, got %d", packet.Lvl90ClassItems[0].ClassID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test TimeLocked class items
|
||||||
|
if len(packet.TimeLockedClassItems) != 1 {
|
||||||
|
t.Errorf("Expected 1 TimeLocked class item, got %d", len(packet.TimeLockedClassItems))
|
||||||
|
}
|
||||||
|
if packet.TimeLockedClassItems[0].ClassID != 7 {
|
||||||
|
t.Errorf("Expected TimeLocked ClassID=7, got %d", packet.TimeLockedClassItems[0].ClassID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.RaceFlag != 0xFFFFFFFF {
|
||||||
|
t.Errorf("Expected RaceFlag=0xFFFFFFFF, got %d", packet.RaceFlag)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user