interface to any

This commit is contained in:
Sky Johnson 2025-08-07 11:21:56 -05:00
parent 41f80008c9
commit 5cb4b5b56c
11 changed files with 808 additions and 809 deletions

View File

@ -27,10 +27,10 @@ type Config struct {
// Database wraps the SQL database connection // Database wraps the SQL database connection
type Database struct { type Database struct {
db *sql.DB db *sql.DB
pool *sqlitex.Pool // For achievements system compatibility (SQLite only) pool *sqlitex.Pool // For achievements system compatibility (SQLite only)
config Config config Config
mutex sync.RWMutex mutex sync.RWMutex
} }
// New creates a new database connection with the provided configuration // New creates a new database connection with the provided configuration
@ -101,19 +101,18 @@ func (d *Database) GetPool() *sqlitex.Pool {
return d.pool return d.pool
} }
// Query executes a query that returns rows // Query executes a query that returns rows
func (d *Database) Query(query string, args ...interface{}) (*sql.Rows, error) { func (d *Database) Query(query string, args ...any) (*sql.Rows, error) {
return d.db.Query(query, args...) return d.db.Query(query, args...)
} }
// QueryRow executes a query that returns a single row // QueryRow executes a query that returns a single row
func (d *Database) QueryRow(query string, args ...interface{}) *sql.Row { func (d *Database) QueryRow(query string, args ...any) *sql.Row {
return d.db.QueryRow(query, args...) return d.db.QueryRow(query, args...)
} }
// Exec executes a query that doesn't return rows // Exec executes a query that doesn't return rows
func (d *Database) Exec(query string, args ...interface{}) (sql.Result, error) { func (d *Database) Exec(query string, args ...any) (sql.Result, error) {
return d.db.Exec(query, args...) return d.db.Exec(query, args...)
} }
@ -174,7 +173,7 @@ func NewMySQL(dsn string) (*Database, error) {
} }
// GetZones retrieves all zones from the database // GetZones retrieves all zones from the database
func (d *Database) GetZones() ([]map[string]interface{}, error) { func (d *Database) GetZones() ([]map[string]any, error) {
rows, err := d.Query(` rows, err := d.Query(`
SELECT id, name, file, description, motd, min_level, max_level, SELECT id, name, file, description, motd, min_level, max_level,
min_version, xp_modifier, city_zone, weather_allowed, min_version, xp_modifier, city_zone, weather_allowed,
@ -187,10 +186,10 @@ func (d *Database) GetZones() ([]map[string]interface{}, error) {
} }
defer rows.Close() defer rows.Close()
var zones []map[string]interface{} var zones []map[string]any
for rows.Next() { for rows.Next() {
zone := make(map[string]interface{}) zone := make(map[string]any)
var id, minLevel, maxLevel, minVersion int var id, minLevel, maxLevel, minVersion int
var name, file, description, motd string var name, file, description, motd string
var xpModifier, safeX, safeY, safeZ, safeHeading float64 var xpModifier, safeX, safeY, safeZ, safeHeading float64

View File

@ -43,8 +43,8 @@ type WorldInterface interface {
// DatabaseInterface defines database operations needed by packet handlers // DatabaseInterface defines database operations needed by packet handlers
type DatabaseInterface interface { type DatabaseInterface interface {
GetCharacter(characterID int32) (map[string]interface{}, error) GetCharacter(characterID int32) (map[string]any, error)
SaveCharacter(characterID int32, data map[string]interface{}) error SaveCharacter(characterID int32, data map[string]any) error
// Add more database methods as needed // Add more database methods as needed
} }
@ -132,7 +132,7 @@ func (phr *PacketHandlerRegistry) GetRegisteredOpcodes() []InternalOpcode {
// PacketProcessor combines opcode management and handler dispatch // PacketProcessor combines opcode management and handler dispatch
type PacketProcessor struct { type PacketProcessor struct {
opcodeManager *OpcodeManager opcodeManager *OpcodeManager
handlerRegistry *PacketHandlerRegistry handlerRegistry *PacketHandlerRegistry
} }

View File

@ -212,7 +212,7 @@ All server data is persisted to SQLite:
func (d *Database) LoadRules() (map[string]map[string]string, error) func (d *Database) LoadRules() (map[string]map[string]string, error)
// Zone management // Zone management
func (d *Database) GetZones() ([]map[string]interface{}, error) func (d *Database) GetZones() ([]map[string]any, error)
// Character persistence (planned) // Character persistence (planned)
func (d *Database) SaveCharacter(character *Character) error func (d *Database) SaveCharacter(character *Character) error

View File

@ -80,7 +80,7 @@ const (
type AchievementEvent struct { type AchievementEvent struct {
Type AchievementEventType Type AchievementEventType
CharacterID int32 CharacterID int32
Data map[string]interface{} Data map[string]any
Timestamp int64 Timestamp int64
} }
@ -355,7 +355,7 @@ func (aeh *AchievementEventHandler) handleGenericEvent(event *AchievementEvent,
} }
// TriggerEvent is a convenience method for triggering achievement events // TriggerEvent is a convenience method for triggering achievement events
func (w *World) TriggerAchievementEvent(eventType AchievementEventType, characterID int32, data map[string]interface{}) { func (w *World) TriggerAchievementEvent(eventType AchievementEventType, characterID int32, data map[string]any) {
if w.achievementMgr == nil { if w.achievementMgr == nil {
return // Achievement system not initialized return // Achievement system not initialized
} }
@ -379,7 +379,7 @@ func (w *World) TriggerAchievementEvent(eventType AchievementEventType, characte
// OnNPCKill triggers an NPC kill achievement event // OnNPCKill triggers an NPC kill achievement event
func (w *World) OnNPCKill(characterID int32, npcID int32, npcLevel int32) { func (w *World) OnNPCKill(characterID int32, npcID int32, npcLevel int32) {
w.TriggerAchievementEvent(EventNPCKill, characterID, map[string]interface{}{ w.TriggerAchievementEvent(EventNPCKill, characterID, map[string]any{
"npc_id": npcID, "npc_id": npcID,
"level": npcLevel, "level": npcLevel,
}) })
@ -387,21 +387,21 @@ func (w *World) OnNPCKill(characterID int32, npcID int32, npcLevel int32) {
// OnQuestComplete triggers a quest completion achievement event // OnQuestComplete triggers a quest completion achievement event
func (w *World) OnQuestComplete(characterID int32, questID int32) { func (w *World) OnQuestComplete(characterID int32, questID int32) {
w.TriggerAchievementEvent(EventQuestCompleted, characterID, map[string]interface{}{ w.TriggerAchievementEvent(EventQuestCompleted, characterID, map[string]any{
"quest_id": questID, "quest_id": questID,
}) })
} }
// OnLevelGain triggers a level gain achievement event // OnLevelGain triggers a level gain achievement event
func (w *World) OnLevelGain(characterID int32, newLevel int32) { func (w *World) OnLevelGain(characterID int32, newLevel int32) {
w.TriggerAchievementEvent(EventLevelGain, characterID, map[string]interface{}{ w.TriggerAchievementEvent(EventLevelGain, characterID, map[string]any{
"level": newLevel, "level": newLevel,
}) })
} }
// OnItemDiscovered triggers an item discovery achievement event // OnItemDiscovered triggers an item discovery achievement event
func (w *World) OnItemDiscovered(characterID int32, itemID int32, rarity string) { func (w *World) OnItemDiscovered(characterID int32, itemID int32, rarity string) {
w.TriggerAchievementEvent(EventItemDiscovered, characterID, map[string]interface{}{ w.TriggerAchievementEvent(EventItemDiscovered, characterID, map[string]any{
"item_id": itemID, "item_id": itemID,
"rarity": rarity, "rarity": rarity,
}) })
@ -409,7 +409,7 @@ func (w *World) OnItemDiscovered(characterID int32, itemID int32, rarity string)
// OnZoneDiscovered triggers a zone discovery achievement event // OnZoneDiscovered triggers a zone discovery achievement event
func (w *World) OnZoneDiscovered(characterID int32, zoneID int32) { func (w *World) OnZoneDiscovered(characterID int32, zoneID int32) {
w.TriggerAchievementEvent(EventZoneDiscovered, characterID, map[string]interface{}{ w.TriggerAchievementEvent(EventZoneDiscovered, characterID, map[string]any{
"zone_id": zoneID, "zone_id": zoneID,
}) })
} }

View File

@ -10,12 +10,12 @@ import (
// AchievementManager manages achievements for the world server // AchievementManager manages achievements for the world server
type AchievementManager struct { type AchievementManager struct {
masterList *achievements.MasterList masterList *achievements.MasterList
playerManagers map[int32]*achievements.PlayerManager // CharacterID -> PlayerManager playerManagers map[int32]*achievements.PlayerManager // CharacterID -> PlayerManager
database *database.Database database *database.Database
world *World // Reference to world server for notifications world *World // Reference to world server for notifications
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewAchievementManager creates a new achievement manager // NewAchievementManager creates a new achievement manager
@ -289,15 +289,15 @@ func (am *AchievementManager) RemovePlayerManager(characterID int32) {
} }
// GetStatistics returns achievement system statistics // GetStatistics returns achievement system statistics
func (am *AchievementManager) GetStatistics() map[string]interface{} { func (am *AchievementManager) GetStatistics() map[string]any {
am.mutex.RLock() am.mutex.RLock()
defer am.mutex.RUnlock() defer am.mutex.RUnlock()
stats := map[string]interface{}{ stats := map[string]any{
"total_achievements": am.masterList.Size(), "total_achievements": am.masterList.Size(),
"online_players": len(am.playerManagers), "online_players": len(am.playerManagers),
"categories": am.masterList.GetCategories(), "categories": am.masterList.GetCategories(),
"expansions": am.masterList.GetExpansions(), "expansions": am.masterList.GetExpansions(),
} }
return stats return stats

View File

@ -15,64 +15,64 @@ import (
// Client represents a connected player client // Client represents a connected player client
type Client struct { type Client struct {
// Account information // Account information
AccountID int32 AccountID int32
AccountName string AccountName string
AdminLevel int AdminLevel int
// Character information // Character information
CharacterID int32 CharacterID int32
CharacterName string CharacterName string
Player *entity.Entity Player *entity.Entity
// Connection information // Connection information
Connection interface{} // TODO: Will be *udp.Connection Connection any // TODO: Will be *udp.Connection
IPAddress string IPAddress string
ConnectedTime time.Time ConnectedTime time.Time
LastActivity time.Time LastActivity time.Time
ClientVersion int32 // EQ2 client version ClientVersion int32 // EQ2 client version
// Zone information // Zone information
CurrentZone *ZoneServer CurrentZone *ZoneServer
ZoneID int32 ZoneID int32
// State flags // State flags
IsConnected bool IsConnected bool
IsLinkdead bool IsLinkdead bool
IsAFK bool IsAFK bool
IsAnonymous bool IsAnonymous bool
IsLFG bool IsLFG bool
// Chat state // Chat state
LastTellFrom string LastTellFrom string
IgnoreList map[string]bool IgnoreList map[string]bool
// Group/Guild // Group/Guild
GroupID int32 GroupID int32
GuildID int32 GuildID int32
// Pending operations // Pending operations
PendingZone *ZoneChangeDetails PendingZone *ZoneChangeDetails
mutex sync.RWMutex mutex sync.RWMutex
} }
// ZoneChangeDetails holds information about a zone change // ZoneChangeDetails holds information about a zone change
type ZoneChangeDetails struct { type ZoneChangeDetails struct {
ZoneID int32 ZoneID int32
InstanceID int32 InstanceID int32
X float32 X float32
Y float32 Y float32
Z float32 Z float32
Heading float32 Heading float32
} }
// ClientList manages all connected clients // ClientList manages all connected clients
type ClientList struct { type ClientList struct {
clients map[int32]*Client // CharacterID -> Client clients map[int32]*Client // CharacterID -> Client
clientsByName map[string]*Client // Lowercase name -> Client clientsByName map[string]*Client // Lowercase name -> Client
clientsByAcct map[int32][]*Client // AccountID -> Clients clientsByAcct map[int32][]*Client // AccountID -> Clients
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewClientList creates a new client list // NewClientList creates a new client list

View File

@ -10,17 +10,17 @@ import (
// ItemManager manages items for the world server // ItemManager manages items for the world server
type ItemManager struct { type ItemManager struct {
masterItemList *items.MasterItemList masterItemList *items.MasterItemList
itemSystemAdapter *items.ItemSystemAdapter itemSystemAdapter *items.ItemSystemAdapter
database *database.Database database *database.Database
world *World // Reference to world server world *World // Reference to world server
// World-specific item tracking // World-specific item tracking
playerInventories map[uint32]*items.PlayerItemList // Player ID -> Inventory playerInventories map[uint32]*items.PlayerItemList // Player ID -> Inventory
playerEquipment map[uint32]*items.EquipmentItemList // Player ID -> Equipment playerEquipment map[uint32]*items.EquipmentItemList // Player ID -> Equipment
worldDrops map[int32][]*items.Item // Zone ID -> Ground items worldDrops map[int32][]*items.Item // Zone ID -> Ground items
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewItemManager creates a new item manager for the world server // NewItemManager creates a new item manager for the world server
@ -61,7 +61,7 @@ func NewItemManager(db *database.Database) *ItemManager {
return &ItemManager{ return &ItemManager{
masterItemList: masterList, masterItemList: masterList,
itemSystemAdapter: systemAdapter, itemSystemAdapter: systemAdapter,
database: db, database: db,
playerInventories: make(map[uint32]*items.PlayerItemList), playerInventories: make(map[uint32]*items.PlayerItemList),
playerEquipment: make(map[uint32]*items.EquipmentItemList), playerEquipment: make(map[uint32]*items.EquipmentItemList),
worldDrops: make(map[int32][]*items.Item), worldDrops: make(map[int32][]*items.Item),
@ -272,7 +272,7 @@ func (im *ItemManager) SearchItems(name string, maxResults int32) []*items.Item
} }
// GetStatistics returns item system statistics // GetStatistics returns item system statistics
func (im *ItemManager) GetStatistics() map[string]interface{} { func (im *ItemManager) GetStatistics() map[string]any {
im.mutex.RLock() im.mutex.RLock()
defer im.mutex.RUnlock() defer im.mutex.RUnlock()
@ -284,7 +284,7 @@ func (im *ItemManager) GetStatistics() map[string]interface{} {
totalWorldDrops += len(drops) totalWorldDrops += len(drops)
} }
result := make(map[string]interface{}) result := make(map[string]any)
for k, v := range systemStats { for k, v := range systemStats {
result[k] = v result[k] = v
} }
@ -434,12 +434,12 @@ func (wdb *WorldItemDatabaseAdapter) LoadItemStats() (map[string]int32, map[int3
fmt.Println("Loading item stats - using placeholder data") fmt.Println("Loading item stats - using placeholder data")
statsStrings := map[string]int32{ statsStrings := map[string]int32{
"health": 1, "health": 1,
"power": 2, "power": 2,
"strength": 3, "strength": 3,
"stamina": 4, "stamina": 4,
"agility": 5, "agility": 5,
"wisdom": 6, "wisdom": 6,
"intelligence": 7, "intelligence": 7,
} }
@ -601,14 +601,14 @@ type MockPlayer struct {
alignment int8 alignment int8
} }
func (mp *MockPlayer) GetID() uint32 { return mp.id } func (mp *MockPlayer) GetID() uint32 { return mp.id }
func (mp *MockPlayer) GetName() string { return mp.name } func (mp *MockPlayer) GetName() string { return mp.name }
func (mp *MockPlayer) GetLevel() int16 { return mp.level } func (mp *MockPlayer) GetLevel() int16 { return mp.level }
func (mp *MockPlayer) GetAdventureClass() int8 { return mp.adventureClass } func (mp *MockPlayer) GetAdventureClass() int8 { return mp.adventureClass }
func (mp *MockPlayer) GetTradeskillClass() int8 { return mp.tradeskillClass } func (mp *MockPlayer) GetTradeskillClass() int8 { return mp.tradeskillClass }
func (mp *MockPlayer) GetRace() int8 { return mp.race } func (mp *MockPlayer) GetRace() int8 { return mp.race }
func (mp *MockPlayer) GetGender() int8 { return mp.gender } func (mp *MockPlayer) GetGender() int8 { return mp.gender }
func (mp *MockPlayer) GetAlignment() int8 { return mp.alignment } func (mp *MockPlayer) GetAlignment() int8 { return mp.alignment }
// MockItemQuestAdapter provides mock quest functionality // MockItemQuestAdapter provides mock quest functionality
type MockItemQuestAdapter struct{} type MockItemQuestAdapter struct{}

View File

@ -4,23 +4,23 @@ import (
"fmt" "fmt"
"sync" "sync"
"eq2emu/internal/database"
"eq2emu/internal/npc" "eq2emu/internal/npc"
"eq2emu/internal/npc/ai" "eq2emu/internal/npc/ai"
"eq2emu/internal/database"
) )
// NPCManager manages NPCs for the world server // NPCManager manages NPCs for the world server
type NPCManager struct { type NPCManager struct {
npcManager *npc.Manager npcManager *npc.Manager
aiManager *ai.AIManager aiManager *ai.AIManager
database *database.Database database *database.Database
world *World // Reference to world server world *World // Reference to world server
// World-specific NPC tracking // World-specific NPC tracking
npcsByZone map[int32][]*npc.NPC // Zone ID -> NPCs npcsByZone map[int32][]*npc.NPC // Zone ID -> NPCs
activeCombat map[int32]bool // NPC ID -> in combat activeCombat map[int32]bool // NPC ID -> in combat
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewNPCManager creates a new NPC manager for the world server // NewNPCManager creates a new NPC manager for the world server
@ -412,7 +412,7 @@ func (nm *NPCManager) RemoveNPCFromZone(zoneID int32, npcID int32) {
} }
// GetStatistics returns NPC system statistics // GetStatistics returns NPC system statistics
func (nm *NPCManager) GetStatistics() map[string]interface{} { func (nm *NPCManager) GetStatistics() map[string]any {
nm.mutex.RLock() nm.mutex.RLock()
defer nm.mutex.RUnlock() defer nm.mutex.RUnlock()
@ -423,17 +423,17 @@ func (nm *NPCManager) GetStatistics() map[string]interface{} {
totalZones := len(nm.npcsByZone) totalZones := len(nm.npcsByZone)
totalInCombat := len(nm.activeCombat) totalInCombat := len(nm.activeCombat)
result := map[string]interface{}{ result := map[string]any{
"total_npcs": stats.TotalNPCs, "total_npcs": stats.TotalNPCs,
"npcs_in_combat": stats.NPCsInCombat, "npcs_in_combat": stats.NPCsInCombat,
"npcs_with_spells": stats.NPCsWithSpells, "npcs_with_spells": stats.NPCsWithSpells,
"npcs_with_skills": stats.NPCsWithSkills, "npcs_with_skills": stats.NPCsWithSkills,
"spell_cast_count": stats.SpellCastCount, "spell_cast_count": stats.SpellCastCount,
"skill_usage_count": stats.SkillUsageCount, "skill_usage_count": stats.SkillUsageCount,
"runback_count": stats.RunbackCount, "runback_count": stats.RunbackCount,
"average_aggro_radius": stats.AverageAggroRadius, "average_aggro_radius": stats.AverageAggroRadius,
"ai_strategy_counts": stats.AIStrategyCounts, "ai_strategy_counts": stats.AIStrategyCounts,
"zones_with_npcs": totalZones, "zones_with_npcs": totalZones,
"world_npcs_in_combat": totalInCombat, "world_npcs_in_combat": totalInCombat,
} }
@ -459,9 +459,9 @@ func (nm *NPCManager) Shutdown() {
// NPCInfo represents basic information about an NPC // NPCInfo represents basic information about an NPC
type NPCInfo struct { type NPCInfo struct {
ID int32 ID int32
Name string Name string
Level int8 Level int8
ZoneID int32 ZoneID int32
} }

View File

@ -304,14 +304,14 @@ func (w *World) SendCharacterAchievements(client *Client) {
// Get all achievements with player progress // Get all achievements with player progress
allAchievements := w.achievementMgr.masterList.GetAllAchievements() allAchievements := w.achievementMgr.masterList.GetAllAchievements()
characterData := make(map[string]interface{}) characterData := make(map[string]any)
for achievementID, achievement := range allAchievements { for achievementID, achievement := range allAchievements {
progress := w.achievementMgr.GetPlayerProgress(characterID, achievementID) progress := w.achievementMgr.GetPlayerProgress(characterID, achievementID)
completed := w.achievementMgr.IsPlayerCompleted(characterID, achievementID) completed := w.achievementMgr.IsPlayerCompleted(characterID, achievementID)
percentage := w.achievementMgr.GetCompletionPercentage(characterID, achievementID) percentage := w.achievementMgr.GetCompletionPercentage(characterID, achievementID)
characterData[fmt.Sprintf("achievement_%d", achievementID)] = map[string]interface{}{ characterData[fmt.Sprintf("achievement_%d", achievementID)] = map[string]any{
"id": achievementID, "id": achievementID,
"title": achievement.Title, "title": achievement.Title,
"description": achievement.UncompletedText, "description": achievement.UncompletedText,
@ -564,7 +564,7 @@ func (w *World) SendNPCInfo(client *Client, npcID int32) {
} }
// SendNPCUpdate sends NPC update to clients in range // SendNPCUpdate sends NPC update to clients in range
func (w *World) SendNPCUpdate(npcID int32, updateType string, data map[string]interface{}) { func (w *World) SendNPCUpdate(npcID int32, updateType string, data map[string]any) {
// TODO: Implement NPC update broadcasting // TODO: Implement NPC update broadcasting
// This would send updates to all clients in range of the NPC // This would send updates to all clients in range of the NPC
@ -604,13 +604,13 @@ type WorldDatabaseAdapter struct {
} }
// GetCharacter implements packets.DatabaseInterface // GetCharacter implements packets.DatabaseInterface
func (wda *WorldDatabaseAdapter) GetCharacter(characterID int32) (map[string]interface{}, error) { func (wda *WorldDatabaseAdapter) GetCharacter(characterID int32) (map[string]any, error) {
// TODO: Implement character loading from database // TODO: Implement character loading from database
return nil, fmt.Errorf("character loading not yet implemented") return nil, fmt.Errorf("character loading not yet implemented")
} }
// SaveCharacter implements packets.DatabaseInterface // SaveCharacter implements packets.DatabaseInterface
func (wda *WorldDatabaseAdapter) SaveCharacter(characterID int32, data map[string]interface{}) error { func (wda *WorldDatabaseAdapter) SaveCharacter(characterID int32, data map[string]any) error {
// TODO: Implement character saving to database // TODO: Implement character saving to database
return fmt.Errorf("character saving not yet implemented") return fmt.Errorf("character saving not yet implemented")
} }
@ -902,7 +902,7 @@ func (w *World) HandleItemUpdate(ctx *packets.PacketContext, packet *packets.Pac
} }
// SendItemDetails sends detailed item information to a client // SendItemDetails sends detailed item information to a client
func (w *World) SendItemDetails(client *Client, item interface{}) { func (w *World) SendItemDetails(client *Client, item any) {
if w.itemMgr == nil { if w.itemMgr == nil {
return return
} }
@ -947,7 +947,7 @@ func (w *World) SendPlayerInventory(client *Client) {
} }
// SendItemUpdate sends item update to client // SendItemUpdate sends item update to client
func (w *World) SendItemUpdate(client *Client, updateType string, itemData map[string]interface{}) { func (w *World) SendItemUpdate(client *Client, updateType string, itemData map[string]any) {
if w.itemMgr == nil { if w.itemMgr == nil {
return return
} }
@ -961,7 +961,7 @@ func (w *World) SendItemUpdate(client *Client, updateType string, itemData map[s
} }
// BroadcastItemUpdate broadcasts item updates to nearby players // BroadcastItemUpdate broadcasts item updates to nearby players
func (w *World) BroadcastItemUpdate(sourcePlayerID uint32, updateType string, itemData map[string]interface{}) { func (w *World) BroadcastItemUpdate(sourcePlayerID uint32, updateType string, itemData map[string]any) {
// TODO: Implement item update broadcasting (for things like equipment changes visible to others) // TODO: Implement item update broadcasting (for things like equipment changes visible to others)
fmt.Printf("Broadcasting item update from player %d: %s - %v\n", fmt.Printf("Broadcasting item update from player %d: %s - %v\n",

View File

@ -4,17 +4,17 @@ import (
"fmt" "fmt"
"sync" "sync"
"eq2emu/internal/titles"
"eq2emu/internal/database" "eq2emu/internal/database"
"eq2emu/internal/titles"
) )
// TitleManager manages titles for the world server // TitleManager manages titles for the world server
type TitleManager struct { type TitleManager struct {
titleManager *titles.TitleManager titleManager *titles.TitleManager
integrationMgr *titles.IntegrationManager integrationMgr *titles.IntegrationManager
database *database.Database database *database.Database
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewTitleManager creates a new title manager for the world server // NewTitleManager creates a new title manager for the world server
@ -198,7 +198,7 @@ func (tm *TitleManager) ProcessAchievementCompletion(playerID int32, achievement
} }
// GetStatistics returns title system statistics // GetStatistics returns title system statistics
func (tm *TitleManager) GetStatistics() map[string]interface{} { func (tm *TitleManager) GetStatistics() map[string]any {
tm.mutex.RLock() tm.mutex.RLock()
defer tm.mutex.RUnlock() defer tm.mutex.RUnlock()
@ -206,8 +206,8 @@ func (tm *TitleManager) GetStatistics() map[string]interface{} {
titleManagerStats := tm.titleManager.GetStatistics() titleManagerStats := tm.titleManager.GetStatistics()
// Combine with our own statistics // Combine with our own statistics
stats := map[string]interface{}{ stats := map[string]any{
"total_titles": tm.titleManager.GetMasterList().GetTitleCount(), "total_titles": tm.titleManager.GetMasterList().GetTitleCount(),
} }
// Add statistics from the title manager // Add statistics from the title manager

View File

@ -16,87 +16,87 @@ import (
// World represents the main world server instance // World represents the main world server instance
type World struct { type World struct {
// Core components // Core components
db *database.Database db *database.Database
commandManager *commands.CommandManager commandManager *commands.CommandManager
rulesManager *rules.RuleManager rulesManager *rules.RuleManager
// Server configuration // Server configuration
config *WorldConfig config *WorldConfig
startTime time.Time startTime time.Time
shutdownTime *time.Time shutdownTime *time.Time
shutdownReason string shutdownReason string
// World time management // World time management
worldTime *WorldTime worldTime *WorldTime
worldTimeTicker *time.Ticker worldTimeTicker *time.Ticker
// Zones management // Zones management
zones *ZoneList zones *ZoneList
// Client management // Client management
clients *ClientList clients *ClientList
// Achievement system // Achievement system
achievementMgr *AchievementManager achievementMgr *AchievementManager
// Title system // Title system
titleMgr *TitleManager titleMgr *TitleManager
// NPC system // NPC system
npcMgr *NPCManager npcMgr *NPCManager
// Item system // Item system
itemMgr *ItemManager itemMgr *ItemManager
// Master lists (singletons) // Master lists (singletons)
masterSpells interface{} // TODO: implement spell manager masterSpells any // TODO: implement spell manager
masterQuests interface{} // TODO: implement quest manager masterQuests any // TODO: implement quest manager
masterSkills interface{} // TODO: implement skill manager masterSkills any // TODO: implement skill manager
masterFactions interface{} // TODO: implement faction manager masterFactions any // TODO: implement faction manager
// Server statistics // Server statistics
stats *ServerStatistics stats *ServerStatistics
// Synchronization // Synchronization
mutex sync.RWMutex mutex sync.RWMutex
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
wg sync.WaitGroup wg sync.WaitGroup
} }
// WorldConfig holds world server configuration // WorldConfig holds world server configuration
type WorldConfig struct { type WorldConfig struct {
// Network settings // Network settings
ListenAddr string `json:"listen_addr"` ListenAddr string `json:"listen_addr"`
ListenPort int `json:"listen_port"` ListenPort int `json:"listen_port"`
MaxClients int `json:"max_clients"` MaxClients int `json:"max_clients"`
// Web interface settings // Web interface settings
WebAddr string `json:"web_addr"` WebAddr string `json:"web_addr"`
WebPort int `json:"web_port"` WebPort int `json:"web_port"`
WebCertFile string `json:"web_cert_file"` WebCertFile string `json:"web_cert_file"`
WebKeyFile string `json:"web_key_file"` WebKeyFile string `json:"web_key_file"`
WebKeyPassword string `json:"web_key_password"` WebKeyPassword string `json:"web_key_password"`
// Database settings // Database settings
DatabaseType string `json:"database_type"` // "sqlite" or "mysql" DatabaseType string `json:"database_type"` // "sqlite" or "mysql"
DatabasePath string `json:"database_path"` // For SQLite: file path DatabasePath string `json:"database_path"` // For SQLite: file path
DatabaseHost string `json:"database_host"` // For MySQL: hostname DatabaseHost string `json:"database_host"` // For MySQL: hostname
DatabasePort int `json:"database_port"` // For MySQL: port DatabasePort int `json:"database_port"` // For MySQL: port
DatabaseName string `json:"database_name"` // For MySQL: database name DatabaseName string `json:"database_name"` // For MySQL: database name
DatabaseUser string `json:"database_user"` // For MySQL: username DatabaseUser string `json:"database_user"` // For MySQL: username
DatabasePass string `json:"database_pass"` // For MySQL: password DatabasePass string `json:"database_pass"` // For MySQL: password
// Server settings // Server settings
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
ServerMOTD string `json:"server_motd"` ServerMOTD string `json:"server_motd"`
LogLevel string `json:"log_level"` LogLevel string `json:"log_level"`
// Game settings // Game settings
XPRate float32 `json:"xp_rate"` XPRate float32 `json:"xp_rate"`
TSXPRate float32 `json:"ts_xp_rate"` TSXPRate float32 `json:"ts_xp_rate"`
CoinRate float32 `json:"coin_rate"` CoinRate float32 `json:"coin_rate"`
LootRate float32 `json:"loot_rate"` LootRate float32 `json:"loot_rate"`
// Login server settings // Login server settings
LoginServerAddr string `json:"login_server_addr"` LoginServerAddr string `json:"login_server_addr"`
@ -117,29 +117,29 @@ type WorldTime struct {
// ServerStatistics tracks server metrics // ServerStatistics tracks server metrics
type ServerStatistics struct { type ServerStatistics struct {
// Server info // Server info
ServerCreated time.Time ServerCreated time.Time
ServerStartTime time.Time ServerStartTime time.Time
// Connection stats // Connection stats
TotalConnections int64 TotalConnections int64
CurrentConnections int32 CurrentConnections int32
MaxConnections int32 MaxConnections int32
// Character stats // Character stats
TotalAccounts int32 TotalAccounts int32
TotalCharacters int32 TotalCharacters int32
AverageCharLevel float32 AverageCharLevel float32
// Zone stats // Zone stats
ActiveZones int32 ActiveZones int32
ActiveInstances int32 ActiveInstances int32
// Performance stats // Performance stats
CPUUsage float32 CPUUsage float32
MemoryUsage int64 MemoryUsage int64
PeakMemoryUsage int64 PeakMemoryUsage int64
mutex sync.RWMutex mutex sync.RWMutex
} }
// NewWorld creates a new world server instance // NewWorld creates a new world server instance
@ -205,11 +205,11 @@ func NewWorld(config *WorldConfig) (*World, error) {
worldTime: &WorldTime{Year: 3721, Month: 1, Day: 1, Hour: 12, Minute: 0}, worldTime: &WorldTime{Year: 3721, Month: 1, Day: 1, Hour: 12, Minute: 0},
zones: NewZoneList(), zones: NewZoneList(),
clients: NewClientList(), clients: NewClientList(),
stats: &ServerStatistics{ stats: &ServerStatistics{
ServerStartTime: time.Now(), ServerStartTime: time.Now(),
}, },
ctx: ctx, ctx: ctx,
cancel: cancel, cancel: cancel,
} }
// Set world references for cross-system communication // Set world references for cross-system communication