package eq2net import ( "fmt" "log" ) // ExampleOpcodeData provides sample opcode data for different client versions // In production, this would be loaded from files or generated from packet captures var ExampleOpcodeData = map[uint16]map[string]uint16{ // Version 1193 opcodes (example values) 1193: { "OP_LoginRequestMsg": 0x00B3, "OP_LoginByNumRequestMsg": 0x00B4, "OP_WSLoginRequestMsg": 0x00B5, "OP_LoginReplyMsg": 0x00B6, "OP_WSStatusReplyMsg": 0x00B7, "OP_WorldListMsg": 0x00B8, "OP_WorldStatusMsg": 0x00B9, "OP_DeleteCharacterRequestMsg": 0x00BA, "OP_DeleteCharacterReplyMsg": 0x00BB, "OP_CreateCharacterRequestMsg": 0x00BC, "OP_CreateCharacterReplyMsg": 0x00BD, "OP_PlayCharacterRequestMsg": 0x00BE, "OP_PlayCharacterReplyMsg": 0x00BF, "OP_ServerListRequestMsg": 0x00C0, "OP_ServerListReplyMsg": 0x00C1, "OP_CharacterListRequestMsg": 0x00C2, "OP_CharacterListReplyMsg": 0x00C3, }, // Version 1208 opcodes (example values) 1208: { "OP_LoginRequestMsg": 0x00D1, "OP_LoginByNumRequestMsg": 0x00D2, "OP_WSLoginRequestMsg": 0x00D3, "OP_LoginReplyMsg": 0x00D4, "OP_WSStatusReplyMsg": 0x00D5, "OP_WorldListMsg": 0x00D6, "OP_WorldStatusMsg": 0x00D7, "OP_DeleteCharacterRequestMsg": 0x00D8, "OP_DeleteCharacterReplyMsg": 0x00D9, "OP_CreateCharacterRequestMsg": 0x00DA, "OP_CreateCharacterReplyMsg": 0x00DB, "OP_PlayCharacterRequestMsg": 0x00DC, "OP_PlayCharacterReplyMsg": 0x00DD, "OP_ServerListRequestMsg": 0x00DE, "OP_ServerListReplyMsg": 0x00DF, "OP_CharacterListRequestMsg": 0x00E0, "OP_CharacterListReplyMsg": 0x00E1, }, } // ImportExampleOpcodes imports the example opcode data into the database func ImportExampleOpcodes(service *OpcodeService) error { for version, opcodes := range ExampleOpcodeData { log.Printf("Importing %d opcodes for version %d", len(opcodes), version) if err := service.ImportOpcodes(version, opcodes); err != nil { return fmt.Errorf("failed to import opcodes for version %d: %w", version, err) } } log.Println("Successfully imported all example opcodes") return nil } // PrintOpcodeTable prints a formatted table of opcodes for a version func PrintOpcodeTable(service *OpcodeService, version uint16) error { manager, err := service.GetManager(version) if err != nil { return fmt.Errorf("failed to get opcode manager for version %d: %w", version, err) } fmt.Printf("\n=== Opcodes for Client Version %d ===\n", version) fmt.Printf("%-30s | %-10s | %-10s\n", "Opcode Name", "Emu Value", "EQ Value") fmt.Printf("%-30s-+-%-10s-+-%-10s\n", "------------------------------", "----------", "----------") // Print all known opcodes for emuOpcode, name := range OpcodeNames { eqOpcode := manager.EmuToEQ(emuOpcode) if eqOpcode != 0xFFFF { fmt.Printf("%-30s | 0x%04X | 0x%04X\n", name, emuOpcode, eqOpcode) } } return nil } // VerifyOpcodeIntegrity checks that opcode mappings are bidirectional func VerifyOpcodeIntegrity(service *OpcodeService, version uint16) error { manager, err := service.GetManager(version) if err != nil { return fmt.Errorf("failed to get opcode manager for version %d: %w", version, err) } errors := 0 for emuOpcode := range OpcodeNames { eqOpcode := manager.EmuToEQ(emuOpcode) if eqOpcode != 0xFFFF { // Verify reverse mapping reverseEmu := manager.EQToEmu(eqOpcode) if reverseEmu != emuOpcode { fmt.Printf("ERROR: Bidirectional mapping failed for %s (0x%04X)\n", OpcodeNames[emuOpcode], emuOpcode) fmt.Printf(" EmuToEQ: 0x%04X -> 0x%04X\n", emuOpcode, eqOpcode) fmt.Printf(" EQToEmu: 0x%04X -> 0x%04X\n", eqOpcode, reverseEmu) errors++ } } } if errors > 0 { return fmt.Errorf("found %d opcode integrity errors", errors) } fmt.Printf("✓ All opcode mappings verified for version %d\n", version) return nil } // ExampleUsage demonstrates how to use the opcode system func ExampleUsage() { // Connect to database dsn := "root:Root12!@tcp(localhost:3306)/eq2test?parseTime=true" db, err := ConnectDB(dsn) if err != nil { log.Fatalf("Failed to connect to database: %v", err) } defer db.Close() // Create tables if needed if err := CreateOpcodeTable(db); err != nil { log.Fatalf("Failed to create opcodes table: %v", err) } // Create opcode service service := NewOpcodeService(db) // Import example opcodes if err := ImportExampleOpcodes(service); err != nil { log.Fatalf("Failed to import example opcodes: %v", err) } // Print opcode tables for version := range ExampleOpcodeData { if err := PrintOpcodeTable(service, version); err != nil { log.Printf("Failed to print opcodes for version %d: %v", version, err) } if err := VerifyOpcodeIntegrity(service, version); err != nil { log.Printf("Integrity check failed for version %d: %v", version, err) } } // Example: Get manager for specific client version clientVersion := uint16(1193) opcodeVersion := GetOpcodeVersion(clientVersion) manager, err := service.GetManager(opcodeVersion) if err != nil { log.Fatalf("Failed to get opcode manager: %v", err) } // Example: Convert opcodes fmt.Printf("\n=== Example Opcode Conversions (Version %d) ===\n", opcodeVersion) // Emu to EQ emuOp := OP_LoginRequestMsg eqOp := manager.EmuToEQ(emuOp) fmt.Printf("EmuToEQ: %s (0x%04X) -> 0x%04X\n", OpcodeNames[emuOp], emuOp, eqOp) // EQ to Emu eqOp = 0x00B8 // OP_WorldListMsg for version 1193 emuOp = manager.EQToEmu(eqOp) fmt.Printf("EQToEmu: 0x%04X -> %s (0x%04X)\n", eqOp, OpcodeNames[emuOp], emuOp) // Get all supported versions versions, err := service.GetSupportedVersions() if err != nil { log.Printf("Failed to get supported versions: %v", err) } else { fmt.Printf("\n=== Supported Client Versions ===\n") for _, v := range versions { fmt.Printf(" Version %d\n", v) } } }