work on packet struct manager w codegen
This commit is contained in:
parent
d714f293f8
commit
6d57815a14
175
defs/gen/registration.go
Normal file
175
defs/gen/registration.go
Normal file
@ -0,0 +1,175 @@
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// XMLDefinition represents the root element containing structs
|
||||
type XMLDefinition struct {
|
||||
XMLName xml.Name `xml:"structs"`
|
||||
Structs []XMLStruct `xml:"struct"`
|
||||
}
|
||||
|
||||
// XMLStruct represents a packet structure definition
|
||||
type XMLStruct struct {
|
||||
Name string `xml:"name,attr"`
|
||||
ClientVersion string `xml:"clientVersion,attr"`
|
||||
OpcodeName string `xml:"opcodeName,attr"`
|
||||
}
|
||||
|
||||
// Registration represents a packet registration entry
|
||||
type Registration struct {
|
||||
StructName string
|
||||
TypeName string
|
||||
Version uint16
|
||||
OpcodeName string
|
||||
}
|
||||
|
||||
// RegistrationData holds all registration data for template
|
||||
type RegistrationData struct {
|
||||
PackageName string
|
||||
Registrations []Registration
|
||||
}
|
||||
|
||||
const registrationTemplate = `// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated from XML packet definitions
|
||||
|
||||
package {{.PackageName}}
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"git.sharkk.net/EQ2/Protocol/defs/generated"
|
||||
)
|
||||
|
||||
// initializePacketMappings loads all packet structure definitions
|
||||
func (pm *PacketManager) initializePacketMappings() {
|
||||
{{range .Registrations}} pm.registerStruct("{{.StructName}}", {{.Version}}, "{{.OpcodeName}}", reflect.TypeOf(generated.{{.TypeName}}{}))
|
||||
{{end}}}
|
||||
`
|
||||
|
||||
func main() {
|
||||
// Process all XML files
|
||||
xmlDir := filepath.Join(".", "xml")
|
||||
outputFile := "registrations_generated.go"
|
||||
|
||||
registrations := []Registration{}
|
||||
|
||||
// Process common.xml
|
||||
commonFile := filepath.Join(xmlDir, "common.xml")
|
||||
if regs, err := processXMLFile(commonFile); err == nil {
|
||||
registrations = append(registrations, regs...)
|
||||
} else {
|
||||
log.Printf("Warning: Could not process common.xml: %v", err)
|
||||
}
|
||||
|
||||
// Process login.xml
|
||||
loginFile := filepath.Join(xmlDir, "login.xml")
|
||||
if regs, err := processXMLFile(loginFile); err == nil {
|
||||
registrations = append(registrations, regs...)
|
||||
} else {
|
||||
log.Printf("Warning: Could not process login.xml: %v", err)
|
||||
}
|
||||
|
||||
// Sort registrations by struct name, then version
|
||||
sort.Slice(registrations, func(i, j int) bool {
|
||||
if registrations[i].StructName != registrations[j].StructName {
|
||||
return registrations[i].StructName < registrations[j].StructName
|
||||
}
|
||||
return registrations[i].Version < registrations[j].Version
|
||||
})
|
||||
|
||||
// Generate the registration code
|
||||
if err := generateRegistrationCode(registrations, outputFile); err != nil {
|
||||
log.Fatalf("Failed to generate registration code: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Generated %s with %d registrations", outputFile, len(registrations))
|
||||
}
|
||||
|
||||
func processXMLFile(filename string) ([]Registration, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Wrap in root element if needed
|
||||
xmlContent := string(data)
|
||||
if !strings.Contains(xmlContent, "<structs>") {
|
||||
xmlContent = "<structs>\n" + xmlContent + "\n</structs>"
|
||||
}
|
||||
|
||||
var def XMLDefinition
|
||||
if err := xml.Unmarshal([]byte(xmlContent), &def); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse XML: %v", err)
|
||||
}
|
||||
|
||||
registrations := []Registration{}
|
||||
|
||||
for _, s := range def.Structs {
|
||||
if s.OpcodeName == "" {
|
||||
continue // Skip structs without opcodes
|
||||
}
|
||||
|
||||
version, err := strconv.ParseUint(s.ClientVersion, 10, 16)
|
||||
if err != nil {
|
||||
log.Printf("Warning: Invalid version %s for %s", s.ClientVersion, s.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
// Determine the Go type name (remove underscores from struct names)
|
||||
typeName := strings.ReplaceAll(s.Name, "_", "")
|
||||
if version > 1 {
|
||||
typeName = fmt.Sprintf("%sV%d", typeName, version)
|
||||
}
|
||||
|
||||
registrations = append(registrations, Registration{
|
||||
StructName: s.Name,
|
||||
TypeName: typeName,
|
||||
Version: uint16(version),
|
||||
OpcodeName: s.OpcodeName,
|
||||
})
|
||||
}
|
||||
|
||||
return registrations, nil
|
||||
}
|
||||
|
||||
func generateRegistrationCode(registrations []Registration, outputFile string) error {
|
||||
tmpl, err := template.New("registration").Parse(registrationTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse template: %v", err)
|
||||
}
|
||||
|
||||
out, err := os.Create(outputFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output file: %v", err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
data := RegistrationData{
|
||||
PackageName: "defs",
|
||||
Registrations: registrations,
|
||||
}
|
||||
|
||||
if err := tmpl.Execute(out, data); err != nil {
|
||||
return fmt.Errorf("failed to execute template: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
297
defs/manager.go
Normal file
297
defs/manager.go
Normal file
@ -0,0 +1,297 @@
|
||||
package defs
|
||||
|
||||
//go:generate go run gen/registration.go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.sharkk.net/EQ2/Protocol/opcodes"
|
||||
)
|
||||
|
||||
// PacketStruct represents a packet structure definition
|
||||
type PacketStruct struct {
|
||||
Name string
|
||||
Version uint16
|
||||
OpcodeName string
|
||||
StructType reflect.Type
|
||||
}
|
||||
|
||||
// PacketManager manages packet structure lookups for specific client versions
|
||||
type PacketManager struct {
|
||||
version uint16
|
||||
structs map[string][]*PacketStruct // map[name][]versions
|
||||
opcodeToName map[opcodes.EmuOpcode]string
|
||||
nameToStruct map[string]*PacketStruct // cached lookups for this version
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewPacketManager creates a new packet manager for the specified version
|
||||
func NewPacketManager(version uint16) *PacketManager {
|
||||
pm := &PacketManager{
|
||||
version: version,
|
||||
structs: make(map[string][]*PacketStruct),
|
||||
opcodeToName: make(map[opcodes.EmuOpcode]string),
|
||||
nameToStruct: make(map[string]*PacketStruct),
|
||||
}
|
||||
pm.initializePacketMappings()
|
||||
return pm
|
||||
}
|
||||
|
||||
// initializePacketMappings is generated in registrations_generated.go
|
||||
|
||||
// registerStruct adds a packet structure definition
|
||||
func (pm *PacketManager) registerStruct(name string, version uint16, opcodeName string, structType reflect.Type) {
|
||||
ps := &PacketStruct{
|
||||
Name: name,
|
||||
Version: version,
|
||||
OpcodeName: opcodeName,
|
||||
StructType: structType,
|
||||
}
|
||||
|
||||
pm.mu.Lock()
|
||||
defer pm.mu.Unlock()
|
||||
|
||||
if _, exists := pm.structs[name]; !exists {
|
||||
pm.structs[name] = make([]*PacketStruct, 0)
|
||||
}
|
||||
pm.structs[name] = append(pm.structs[name], ps)
|
||||
|
||||
// Map opcode to struct name for quick lookup
|
||||
// We'll need to add this mapping based on the actual opcode constants
|
||||
// For now, we map based on the opcode name string
|
||||
pm.mapOpcodeToStruct(opcodeName, name)
|
||||
}
|
||||
|
||||
// mapOpcodeToStruct maps opcode names to struct names
|
||||
// This should be updated when we have a proper opcode name mapping
|
||||
func (pm *PacketManager) mapOpcodeToStruct(opcodeName string, structName string) {
|
||||
// Map common opcodes - this will be expanded as needed
|
||||
switch opcodeName {
|
||||
case "OP_CreateCharacterRequestMsg":
|
||||
pm.opcodeToName[opcodes.OP_CreateCharacterRequestMsg] = structName
|
||||
case "OP_BadLanguageFilter":
|
||||
pm.opcodeToName[opcodes.OP_BadLanguageFilter] = structName
|
||||
// Login opcodes would need to be handled differently since they use LS_ prefix
|
||||
// We'll need to decide how to handle login vs world opcodes
|
||||
}
|
||||
}
|
||||
|
||||
// GetStruct returns the best matching packet struct for the given name and version
|
||||
// It finds the highest version that is <= the requested version (like C++ code)
|
||||
func (pm *PacketManager) GetStruct(name string, version uint16) *PacketStruct {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
// Check cache first
|
||||
cacheKey := fmt.Sprintf("%s_%d", name, version)
|
||||
if cached, ok := pm.nameToStruct[cacheKey]; ok {
|
||||
return cached
|
||||
}
|
||||
|
||||
versions, exists := pm.structs[name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
var bestMatch *PacketStruct
|
||||
for _, ps := range versions {
|
||||
// Find the highest version that's <= requested version
|
||||
if ps.Version <= version {
|
||||
if bestMatch == nil || ps.Version > bestMatch.Version {
|
||||
bestMatch = ps
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bestMatch != nil {
|
||||
// Cache the result
|
||||
pm.nameToStruct[cacheKey] = bestMatch
|
||||
}
|
||||
|
||||
return bestMatch
|
||||
}
|
||||
|
||||
// GetStructByVersion returns an exact version match (like C++ getStructByVersion)
|
||||
func (pm *PacketManager) GetStructByVersion(name string, version uint16) *PacketStruct {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
versions, exists := pm.structs[name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ps := range versions {
|
||||
if ps.Version == version {
|
||||
return ps
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStructByOpcode returns the packet struct for a given opcode
|
||||
func (pm *PacketManager) GetStructByOpcode(opcode opcodes.EmuOpcode) *PacketStruct {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
name, exists := pm.opcodeToName[opcode]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pm.GetStruct(name, pm.version)
|
||||
}
|
||||
|
||||
// CreateInstance creates a new instance of the packet struct
|
||||
func (pm *PacketManager) CreateInstance(name string) interface{} {
|
||||
ps := pm.GetStruct(name, pm.version)
|
||||
if ps == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return reflect.New(ps.StructType).Interface()
|
||||
}
|
||||
|
||||
// CreateInstanceByOpcode creates a new instance by opcode
|
||||
func (pm *PacketManager) CreateInstanceByOpcode(opcode opcodes.EmuOpcode) interface{} {
|
||||
ps := pm.GetStructByOpcode(opcode)
|
||||
if ps == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return reflect.New(ps.StructType).Interface()
|
||||
}
|
||||
|
||||
// GetAvailableVersions returns all versions available for a struct name
|
||||
func (pm *PacketManager) GetAvailableVersions(name string) []uint16 {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
versions, exists := pm.structs[name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result []uint16
|
||||
for _, ps := range versions {
|
||||
result = append(result, ps.Version)
|
||||
}
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i] < result[j]
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAllStructNames returns all registered struct names
|
||||
func (pm *PacketManager) GetAllStructNames() []string {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
var names []string
|
||||
for name := range pm.structs {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
// DumpStructs returns a formatted string of all loaded structs for debugging
|
||||
func (pm *PacketManager) DumpStructs() string {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("Packet Manager for version %d:\n", pm.version))
|
||||
sb.WriteString("=====================================\n")
|
||||
|
||||
names := pm.GetAllStructNames()
|
||||
for _, name := range names {
|
||||
versions := pm.GetAvailableVersions(name)
|
||||
sb.WriteString(fmt.Sprintf("%s: versions %v\n", name, versions))
|
||||
|
||||
// Show which version would be selected
|
||||
if ps := pm.GetStruct(name, pm.version); ps != nil {
|
||||
sb.WriteString(fmt.Sprintf(" -> Selected version %d for client %d\n", ps.Version, pm.version))
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// GetStats returns statistics about loaded packet structs
|
||||
func (pm *PacketManager) GetStats() map[string]int {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
totalStructs := 0
|
||||
for _, versions := range pm.structs {
|
||||
totalStructs += len(versions)
|
||||
}
|
||||
|
||||
return map[string]int{
|
||||
"version": int(pm.version),
|
||||
"unique_structs": len(pm.structs),
|
||||
"total_versions": totalStructs,
|
||||
"cached_lookups": len(pm.nameToStruct),
|
||||
}
|
||||
}
|
||||
|
||||
// Global managers cache
|
||||
var (
|
||||
managers = make(map[uint16]*PacketManager)
|
||||
managersMu sync.RWMutex
|
||||
)
|
||||
|
||||
// GetManager returns packet manager for a version
|
||||
func GetManager(version uint16) *PacketManager {
|
||||
managersMu.RLock()
|
||||
if mgr, ok := managers[version]; ok {
|
||||
managersMu.RUnlock()
|
||||
return mgr
|
||||
}
|
||||
managersMu.RUnlock()
|
||||
|
||||
managersMu.Lock()
|
||||
defer managersMu.Unlock()
|
||||
|
||||
// Double-check after acquiring write lock
|
||||
if mgr, ok := managers[version]; ok {
|
||||
return mgr
|
||||
}
|
||||
|
||||
mgr := NewPacketManager(version)
|
||||
managers[version] = mgr
|
||||
return mgr
|
||||
}
|
||||
|
||||
// ClearCache clears the cached managers (useful for testing)
|
||||
func ClearCache() {
|
||||
managersMu.Lock()
|
||||
defer managersMu.Unlock()
|
||||
managers = make(map[uint16]*PacketManager)
|
||||
}
|
||||
|
||||
// GetLoadedVersions returns all versions that have managers loaded
|
||||
func GetLoadedVersions() []uint16 {
|
||||
managersMu.RLock()
|
||||
defer managersMu.RUnlock()
|
||||
|
||||
var versions []uint16
|
||||
for v := range managers {
|
||||
versions = append(versions, v)
|
||||
}
|
||||
|
||||
sort.Slice(versions, func(i, j int) bool {
|
||||
return versions[i] < versions[j]
|
||||
})
|
||||
|
||||
return versions
|
||||
}
|
56
defs/registrations_generated.go
Normal file
56
defs/registrations_generated.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated from XML packet definitions
|
||||
|
||||
package defs
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"git.sharkk.net/EQ2/Protocol/defs/generated"
|
||||
)
|
||||
|
||||
// initializePacketMappings loads all packet structure definitions
|
||||
func (pm *PacketManager) initializePacketMappings() {
|
||||
pm.registerStruct("BadLanguageFilter", 1, "OP_BadLanguageFilter", reflect.TypeOf(generated.BadLanguageFilter{}))
|
||||
pm.registerStruct("CreateCharacter", 1, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacter{}))
|
||||
pm.registerStruct("CreateCharacter", 373, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV373{}))
|
||||
pm.registerStruct("CreateCharacter", 546, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV546{}))
|
||||
pm.registerStruct("CreateCharacter", 561, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV561{}))
|
||||
pm.registerStruct("CreateCharacter", 562, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV562{}))
|
||||
pm.registerStruct("CreateCharacter", 869, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV869{}))
|
||||
pm.registerStruct("CreateCharacter", 1096, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV1096{}))
|
||||
pm.registerStruct("CreateCharacter", 57080, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV57080{}))
|
||||
pm.registerStruct("CreateCharacter", 60085, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV60085{}))
|
||||
pm.registerStruct("CreateCharacter", 64659, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV64659{}))
|
||||
pm.registerStruct("CreateCharacter", 65534, "OP_CreateCharacterRequestMsg", reflect.TypeOf(generated.CreateCharacterV65534{}))
|
||||
pm.registerStruct("LS_CreateCharacterReply", 1, "OP_CreateCharacterReplyMsg", reflect.TypeOf(generated.LSCreateCharacterReply{}))
|
||||
pm.registerStruct("LS_CreateCharacterReply", 1189, "OP_CreateCharacterReplyMsg", reflect.TypeOf(generated.LSCreateCharacterReplyV1189{}))
|
||||
pm.registerStruct("LS_CreateCharacterReply", 60085, "OP_CreateCharacterReplyMsg", reflect.TypeOf(generated.LSCreateCharacterReplyV60085{}))
|
||||
pm.registerStruct("LS_DeleteCharacterRequest", 1, "OP_DeleteCharacterRequestMsg", reflect.TypeOf(generated.LSDeleteCharacterRequest{}))
|
||||
pm.registerStruct("LS_DeleteCharacterResponse", 1, "OP_DeleteCharacterReplyMsg", reflect.TypeOf(generated.LSDeleteCharacterResponse{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 1, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsg{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 284, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV284{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 843, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV843{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 1096, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV1096{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 1142, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV1142{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 1188, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV1188{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 57080, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV57080{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 60100, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV60100{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 63181, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV63181{}))
|
||||
pm.registerStruct("LS_LoginReplyMsg", 65534, "OP_LoginReplyMsg", reflect.TypeOf(generated.LSLoginReplyMsgV65534{}))
|
||||
pm.registerStruct("LS_LoginRequest", 1, "OP_LoginRequestMsg", reflect.TypeOf(generated.LSLoginRequest{}))
|
||||
pm.registerStruct("LS_LoginRequest", 562, "OP_LoginRequestMsg", reflect.TypeOf(generated.LSLoginRequestV562{}))
|
||||
pm.registerStruct("LS_LoginRequest", 1208, "OP_LoginRequestMsg", reflect.TypeOf(generated.LSLoginRequestV1208{}))
|
||||
pm.registerStruct("LS_PlayRequest", 1, "OP_PlayCharacterRequestMsg", reflect.TypeOf(generated.LSPlayRequest{}))
|
||||
pm.registerStruct("LS_PlayRequest", 284, "OP_PlayCharacterRequestMsg", reflect.TypeOf(generated.LSPlayRequestV284{}))
|
||||
pm.registerStruct("LS_PlayResponse", 1, "OP_PlayCharacterReplyMsg", reflect.TypeOf(generated.LSPlayResponse{}))
|
||||
pm.registerStruct("LS_PlayResponse", 1096, "OP_PlayCharacterReplyMsg", reflect.TypeOf(generated.LSPlayResponseV1096{}))
|
||||
pm.registerStruct("LS_PlayResponse", 60085, "OP_PlayCharacterReplyMsg", reflect.TypeOf(generated.LSPlayResponseV60085{}))
|
||||
pm.registerStruct("LS_PlayResponse", 60099, "OP_PlayCharacterReplyMsg", reflect.TypeOf(generated.LSPlayResponseV60099{}))
|
||||
pm.registerStruct("LS_WorldList", 1, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldList{}))
|
||||
pm.registerStruct("LS_WorldList", 373, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldListV373{}))
|
||||
pm.registerStruct("LS_WorldList", 546, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldListV546{}))
|
||||
pm.registerStruct("LS_WorldList", 562, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldListV562{}))
|
||||
pm.registerStruct("LS_WorldList", 60114, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldListV60114{}))
|
||||
pm.registerStruct("LS_WorldList", 65534, "OP_WorldListMsg", reflect.TypeOf(generated.LSWorldListV65534{}))
|
||||
pm.registerStruct("LS_WorldUpdate", 1, "OP_WorldStatusChangeMsg", reflect.TypeOf(generated.LSWorldUpdate{}))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user