651 lines
18 KiB
Go
651 lines
18 KiB
Go
package entity
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"eq2emu/internal/packets"
|
|
)
|
|
|
|
// Manager provides centralized management for the entity system
|
|
// following the SIMPLIFICATION.md methodology while maintaining C++ API compatibility
|
|
type Manager struct {
|
|
// Thread safety
|
|
mutex sync.RWMutex
|
|
|
|
// Performance monitoring
|
|
stats struct {
|
|
// Entity operations
|
|
EntitiesCreated int64
|
|
EntitiesDestroyed int64
|
|
EntitiesUpdated int64
|
|
|
|
// Spell effect operations
|
|
SpellEffectsAdded int64
|
|
SpellEffectsRemoved int64
|
|
BonusCalculations int64
|
|
|
|
// Combat operations
|
|
DamageCalculations int64
|
|
HealingCalculations int64
|
|
CombatActions int64
|
|
|
|
// Packet operations
|
|
PacketsSent int64
|
|
PacketErrors int64
|
|
VerbRequests int64
|
|
|
|
// Cache performance
|
|
CacheHits int64
|
|
CacheMisses int64
|
|
}
|
|
|
|
// Configuration
|
|
config struct {
|
|
EnableStatistics bool
|
|
EnableValidation bool
|
|
EnableCombatLogging bool
|
|
MaxEntitiesPerZone int
|
|
EffectCleanupInterval time.Duration
|
|
BonusCalculationInterval time.Duration
|
|
PacketBuilderTimeout time.Duration
|
|
EnablePetManagement bool
|
|
EnableSpellEffectCaching bool
|
|
}
|
|
}
|
|
|
|
// NewManager creates a new entity manager with default configuration
|
|
func NewManager() *Manager {
|
|
m := &Manager{}
|
|
|
|
// Set default configuration
|
|
m.config.EnableStatistics = true
|
|
m.config.EnableValidation = true
|
|
m.config.EnableCombatLogging = false
|
|
m.config.MaxEntitiesPerZone = 10000
|
|
m.config.EffectCleanupInterval = 30 * time.Second
|
|
m.config.BonusCalculationInterval = 5 * time.Second
|
|
m.config.PacketBuilderTimeout = 30 * time.Second
|
|
m.config.EnablePetManagement = true
|
|
m.config.EnableSpellEffectCaching = true
|
|
|
|
return m
|
|
}
|
|
|
|
// === Entity Creation and Management ===
|
|
|
|
// CreateEntity creates a new Entity with proper initialization
|
|
func (m *Manager) CreateEntity() *Entity {
|
|
entity := NewEntity()
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.EntitiesCreated, 1)
|
|
}
|
|
|
|
return entity
|
|
}
|
|
|
|
// DestroyEntity properly cleans up an entity
|
|
func (m *Manager) DestroyEntity(entity *Entity) error {
|
|
if entity == nil {
|
|
return fmt.Errorf("entity cannot be nil")
|
|
}
|
|
|
|
// Clean up spell effects
|
|
entity.DeleteSpellEffects(false)
|
|
|
|
// Clean up pets
|
|
if entity.GetPet() != nil {
|
|
entity.SetPet(nil)
|
|
}
|
|
if entity.GetCharmedPet() != nil {
|
|
entity.SetCharmedPet(nil)
|
|
}
|
|
if entity.GetDeityPet() != nil {
|
|
entity.SetDeityPet(nil)
|
|
}
|
|
if entity.GetCosmeticPet() != nil {
|
|
entity.SetCosmeticPet(nil)
|
|
}
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.EntitiesDestroyed, 1)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// === C++ API Compatibility Methods ===
|
|
|
|
// GetEntityInfoStruct returns an entity's info structure (C++ API compatibility)
|
|
func (m *Manager) GetEntityInfoStruct(entity *Entity) *InfoStruct {
|
|
if entity == nil {
|
|
return nil
|
|
}
|
|
return entity.GetInfoStruct()
|
|
}
|
|
|
|
// SetEntityInfoStruct updates an entity's info structure (C++ API compatibility)
|
|
func (m *Manager) SetEntityInfoStruct(entity *Entity, info *InfoStruct) {
|
|
if entity != nil && info != nil {
|
|
entity.SetInfoStruct(info)
|
|
}
|
|
}
|
|
|
|
// IsEntityInCombat returns whether an entity is in combat (C++ API compatibility)
|
|
func (m *Manager) IsEntityInCombat(entity *Entity) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
return entity.IsInCombat()
|
|
}
|
|
|
|
// SetEntityInCombat updates an entity's combat state (C++ API compatibility)
|
|
func (m *Manager) SetEntityInCombat(entity *Entity, inCombat bool) {
|
|
if entity != nil {
|
|
entity.SetInCombat(inCombat)
|
|
if m.config.EnableStatistics && inCombat {
|
|
atomic.AddInt64(&m.stats.CombatActions, 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// IsEntityCasting returns whether an entity is casting (C++ API compatibility)
|
|
func (m *Manager) IsEntityCasting(entity *Entity) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
return entity.IsCasting()
|
|
}
|
|
|
|
// SetEntityCasting updates an entity's casting state (C++ API compatibility)
|
|
func (m *Manager) SetEntityCasting(entity *Entity, casting bool) {
|
|
if entity != nil {
|
|
entity.SetCasting(casting)
|
|
}
|
|
}
|
|
|
|
// === Spell Effect Management ===
|
|
|
|
// AddMaintainedSpell adds a maintained spell to an entity
|
|
func (m *Manager) AddMaintainedSpell(entity *Entity, name string, spellID int32, duration float32, concentration int8) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
|
|
success := entity.AddMaintainedSpell(name, spellID, duration, concentration)
|
|
|
|
if m.config.EnableStatistics && success {
|
|
atomic.AddInt64(&m.stats.SpellEffectsAdded, 1)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// RemoveMaintainedSpell removes a maintained spell from an entity
|
|
func (m *Manager) RemoveMaintainedSpell(entity *Entity, spellID int32) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
|
|
success := entity.RemoveMaintainedSpell(spellID)
|
|
|
|
if m.config.EnableStatistics && success {
|
|
atomic.AddInt64(&m.stats.SpellEffectsRemoved, 1)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// AddSpellEffect adds a temporary spell effect to an entity
|
|
func (m *Manager) AddSpellEffect(entity *Entity, spellID int32, casterID int32, duration float32) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
|
|
success := entity.AddSpellEffect(spellID, casterID, duration)
|
|
|
|
if m.config.EnableStatistics && success {
|
|
atomic.AddInt64(&m.stats.SpellEffectsAdded, 1)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// RemoveSpellEffect removes a spell effect from an entity
|
|
func (m *Manager) RemoveSpellEffect(entity *Entity, spellID int32) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
|
|
success := entity.RemoveSpellEffect(spellID)
|
|
|
|
if m.config.EnableStatistics && success {
|
|
atomic.AddInt64(&m.stats.SpellEffectsRemoved, 1)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// AddDetrimentalSpell adds a detrimental effect to an entity
|
|
func (m *Manager) AddDetrimentalSpell(entity *Entity, spellID int32, casterID int32, duration float32, detType int8) {
|
|
if entity != nil {
|
|
entity.AddDetrimentalSpell(spellID, casterID, duration, detType)
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.SpellEffectsAdded, 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// RemoveDetrimentalSpell removes a detrimental effect from an entity
|
|
func (m *Manager) RemoveDetrimentalSpell(entity *Entity, spellID int32, casterID int32) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
|
|
success := entity.RemoveDetrimentalSpell(spellID, casterID)
|
|
|
|
if m.config.EnableStatistics && success {
|
|
atomic.AddInt64(&m.stats.SpellEffectsRemoved, 1)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// CalculateEntityBonuses recalculates all bonuses for an entity
|
|
func (m *Manager) CalculateEntityBonuses(entity *Entity) {
|
|
if entity != nil {
|
|
entity.CalculateBonuses()
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.BonusCalculations, 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// === Pet Management ===
|
|
|
|
// SetEntityPet assigns a summon pet to an entity
|
|
func (m *Manager) SetEntityPet(entity *Entity, pet *Entity) {
|
|
if entity != nil {
|
|
entity.SetPet(pet)
|
|
}
|
|
}
|
|
|
|
// GetEntityPet returns an entity's summon pet
|
|
func (m *Manager) GetEntityPet(entity *Entity) *Entity {
|
|
if entity == nil {
|
|
return nil
|
|
}
|
|
return entity.GetPet()
|
|
}
|
|
|
|
// SetEntityCharmedPet assigns a charmed pet to an entity
|
|
func (m *Manager) SetEntityCharmedPet(entity *Entity, pet *Entity) {
|
|
if entity != nil {
|
|
entity.SetCharmedPet(pet)
|
|
}
|
|
}
|
|
|
|
// GetEntityCharmedPet returns an entity's charmed pet
|
|
func (m *Manager) GetEntityCharmedPet(entity *Entity) *Entity {
|
|
if entity == nil {
|
|
return nil
|
|
}
|
|
return entity.GetCharmedPet()
|
|
}
|
|
|
|
// DismissPet marks a pet for dismissal
|
|
func (m *Manager) DismissPet(pet *Entity) {
|
|
if pet != nil {
|
|
pet.SetPetDismissing(true)
|
|
}
|
|
}
|
|
|
|
// === Movement and Position ===
|
|
|
|
// UpdateEntityPosition updates an entity's position tracking
|
|
func (m *Manager) UpdateEntityPosition(entity *Entity) {
|
|
if entity != nil {
|
|
// Update last position from current position
|
|
x := entity.GetX()
|
|
y := entity.GetY()
|
|
z := entity.GetZ()
|
|
heading := entity.GetHeading()
|
|
|
|
entity.SetLastPosition(x, y, z, heading)
|
|
}
|
|
}
|
|
|
|
// HasEntityMoved checks if an entity has moved since last update
|
|
func (m *Manager) HasEntityMoved(entity *Entity) bool {
|
|
if entity == nil {
|
|
return false
|
|
}
|
|
return entity.HasMoved()
|
|
}
|
|
|
|
// GetEntityEffectiveSpeed calculates an entity's current effective speed
|
|
func (m *Manager) GetEntityEffectiveSpeed(entity *Entity) float32 {
|
|
if entity == nil {
|
|
return 0.0
|
|
}
|
|
return entity.CalculateEffectiveSpeed()
|
|
}
|
|
|
|
// === Stat Calculations ===
|
|
|
|
// GetEntityPrimaryStat returns an entity's highest primary stat
|
|
func (m *Manager) GetEntityPrimaryStat(entity *Entity) int16 {
|
|
if entity == nil {
|
|
return 0
|
|
}
|
|
return entity.GetPrimaryStat()
|
|
}
|
|
|
|
// GetEntityResistance returns an entity's resistance to a specific damage type
|
|
func (m *Manager) GetEntityResistance(entity *Entity, resistanceType string) int16 {
|
|
if entity == nil {
|
|
return 0
|
|
}
|
|
|
|
switch resistanceType {
|
|
case "heat":
|
|
return entity.GetHeatResistance()
|
|
case "cold":
|
|
return entity.GetColdResistance()
|
|
case "magic":
|
|
return entity.GetMagicResistance()
|
|
case "mental":
|
|
return entity.GetMentalResistance()
|
|
case "divine":
|
|
return entity.GetDivineResistance()
|
|
case "disease":
|
|
return entity.GetDiseaseResistance()
|
|
case "poison":
|
|
return entity.GetPoisonResistance()
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// === Packet Building Methods ===
|
|
|
|
// SendEntityVerbsRequest builds and returns entity verbs request packet data (C++ API compatibility)
|
|
func (m *Manager) SendEntityVerbsRequest(entityID int32, clientVersion uint32) ([]byte, error) {
|
|
packet, exists := packets.GetPacket("WS_EntityVerbsRequest")
|
|
if !exists {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to get WS_EntityVerbsRequest packet structure: packet not found")
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"entity_id": entityID,
|
|
}
|
|
|
|
builder := packets.NewPacketBuilder(packet, clientVersion, 0)
|
|
packetData, err := builder.Build(data)
|
|
if err != nil {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to build entity verbs request packet: %v", err)
|
|
}
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketsSent, 1)
|
|
atomic.AddInt64(&m.stats.VerbRequests, 1)
|
|
}
|
|
|
|
return packetData, nil
|
|
}
|
|
|
|
// SendEntityVerbsResponse builds and returns entity verbs response packet data (C++ API compatibility)
|
|
func (m *Manager) SendEntityVerbsResponse(entityID int32, clientVersion uint32, verbs []map[string]interface{}) ([]byte, error) {
|
|
packet, exists := packets.GetPacket("WS_EntityVerbsResponse")
|
|
if !exists {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to get WS_EntityVerbsResponse packet structure: packet not found")
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"entity_id": entityID,
|
|
"num_verbs": len(verbs),
|
|
"verbs_array": verbs,
|
|
}
|
|
|
|
builder := packets.NewPacketBuilder(packet, clientVersion, 0)
|
|
packetData, err := builder.Build(data)
|
|
if err != nil {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to build entity verbs response packet: %v", err)
|
|
}
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketsSent, 1)
|
|
}
|
|
|
|
return packetData, nil
|
|
}
|
|
|
|
// SendEntityVerbsVerb builds and returns entity verb action packet data (C++ API compatibility)
|
|
func (m *Manager) SendEntityVerbsVerb(entityID int32, targetID int32, clientVersion uint32, verbID int32, verbName string) ([]byte, error) {
|
|
packet, exists := packets.GetPacket("WS_EntityVerbsVerb")
|
|
if !exists {
|
|
// Try backup packet structure
|
|
packet, exists = packets.GetPacket("WS_EntityVerbsVerbBackup")
|
|
if !exists {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to get WS_EntityVerbsVerb packet structure: packet not found")
|
|
}
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"entity_id": entityID,
|
|
"target_id": targetID,
|
|
"verb_id": verbID,
|
|
"verb_name": verbName,
|
|
}
|
|
|
|
builder := packets.NewPacketBuilder(packet, clientVersion, 0)
|
|
packetData, err := builder.Build(data)
|
|
if err != nil {
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketErrors, 1)
|
|
}
|
|
return nil, fmt.Errorf("failed to build entity verb action packet: %v", err)
|
|
}
|
|
|
|
if m.config.EnableStatistics {
|
|
atomic.AddInt64(&m.stats.PacketsSent, 1)
|
|
}
|
|
|
|
return packetData, nil
|
|
}
|
|
|
|
// === Effect Processing ===
|
|
|
|
// ProcessEntityEffects handles periodic effect processing for an entity
|
|
func (m *Manager) ProcessEntityEffects(entity *Entity) {
|
|
if entity != nil {
|
|
entity.ProcessEffects()
|
|
}
|
|
}
|
|
|
|
// CleanupEntityEffects removes expired effects from an entity
|
|
func (m *Manager) CleanupEntityEffects(entity *Entity) {
|
|
if entity != nil {
|
|
entity.ProcessEffects() // This includes cleanup
|
|
}
|
|
}
|
|
|
|
// === Statistics and Monitoring ===
|
|
|
|
// GetStatistics returns comprehensive manager statistics
|
|
func (m *Manager) GetStatistics() map[string]interface{} {
|
|
m.mutex.RLock()
|
|
defer m.mutex.RUnlock()
|
|
|
|
stats := make(map[string]interface{})
|
|
|
|
// Entity stats (using atomic loads)
|
|
stats["entities_created"] = atomic.LoadInt64(&m.stats.EntitiesCreated)
|
|
stats["entities_destroyed"] = atomic.LoadInt64(&m.stats.EntitiesDestroyed)
|
|
stats["entities_updated"] = atomic.LoadInt64(&m.stats.EntitiesUpdated)
|
|
|
|
// Spell effect stats (using atomic loads)
|
|
stats["spell_effects_added"] = atomic.LoadInt64(&m.stats.SpellEffectsAdded)
|
|
stats["spell_effects_removed"] = atomic.LoadInt64(&m.stats.SpellEffectsRemoved)
|
|
stats["bonus_calculations"] = atomic.LoadInt64(&m.stats.BonusCalculations)
|
|
|
|
// Combat stats (using atomic loads)
|
|
stats["damage_calculations"] = atomic.LoadInt64(&m.stats.DamageCalculations)
|
|
stats["healing_calculations"] = atomic.LoadInt64(&m.stats.HealingCalculations)
|
|
stats["combat_actions"] = atomic.LoadInt64(&m.stats.CombatActions)
|
|
|
|
// Packet stats (using atomic loads)
|
|
stats["packets_sent"] = atomic.LoadInt64(&m.stats.PacketsSent)
|
|
stats["packet_errors"] = atomic.LoadInt64(&m.stats.PacketErrors)
|
|
stats["verb_requests"] = atomic.LoadInt64(&m.stats.VerbRequests)
|
|
|
|
// Cache stats (using atomic loads)
|
|
cacheHits := atomic.LoadInt64(&m.stats.CacheHits)
|
|
cacheMisses := atomic.LoadInt64(&m.stats.CacheMisses)
|
|
stats["cache_hits"] = cacheHits
|
|
stats["cache_misses"] = cacheMisses
|
|
|
|
if cacheHits+cacheMisses > 0 {
|
|
hitRate := float64(cacheHits) / float64(cacheHits+cacheMisses) * 100
|
|
stats["cache_hit_rate"] = fmt.Sprintf("%.2f%%", hitRate)
|
|
}
|
|
|
|
// Configuration
|
|
stats["config_statistics_enabled"] = m.config.EnableStatistics
|
|
stats["config_validation_enabled"] = m.config.EnableValidation
|
|
stats["config_combat_logging_enabled"] = m.config.EnableCombatLogging
|
|
stats["config_pet_management_enabled"] = m.config.EnablePetManagement
|
|
|
|
return stats
|
|
}
|
|
|
|
// ResetStatistics clears all performance counters
|
|
func (m *Manager) ResetStatistics() {
|
|
atomic.StoreInt64(&m.stats.EntitiesCreated, 0)
|
|
atomic.StoreInt64(&m.stats.EntitiesDestroyed, 0)
|
|
atomic.StoreInt64(&m.stats.EntitiesUpdated, 0)
|
|
atomic.StoreInt64(&m.stats.SpellEffectsAdded, 0)
|
|
atomic.StoreInt64(&m.stats.SpellEffectsRemoved, 0)
|
|
atomic.StoreInt64(&m.stats.BonusCalculations, 0)
|
|
atomic.StoreInt64(&m.stats.DamageCalculations, 0)
|
|
atomic.StoreInt64(&m.stats.HealingCalculations, 0)
|
|
atomic.StoreInt64(&m.stats.CombatActions, 0)
|
|
atomic.StoreInt64(&m.stats.PacketsSent, 0)
|
|
atomic.StoreInt64(&m.stats.PacketErrors, 0)
|
|
atomic.StoreInt64(&m.stats.VerbRequests, 0)
|
|
atomic.StoreInt64(&m.stats.CacheHits, 0)
|
|
atomic.StoreInt64(&m.stats.CacheMisses, 0)
|
|
}
|
|
|
|
// === Configuration Management ===
|
|
|
|
// SetConfiguration updates manager configuration
|
|
func (m *Manager) SetConfiguration(config map[string]interface{}) {
|
|
m.mutex.Lock()
|
|
defer m.mutex.Unlock()
|
|
|
|
if val, ok := config["enable_statistics"].(bool); ok {
|
|
m.config.EnableStatistics = val
|
|
}
|
|
if val, ok := config["enable_validation"].(bool); ok {
|
|
m.config.EnableValidation = val
|
|
}
|
|
if val, ok := config["enable_combat_logging"].(bool); ok {
|
|
m.config.EnableCombatLogging = val
|
|
}
|
|
if val, ok := config["max_entities_per_zone"].(int); ok {
|
|
m.config.MaxEntitiesPerZone = val
|
|
}
|
|
if val, ok := config["effect_cleanup_interval"].(time.Duration); ok {
|
|
m.config.EffectCleanupInterval = val
|
|
}
|
|
if val, ok := config["enable_pet_management"].(bool); ok {
|
|
m.config.EnablePetManagement = val
|
|
}
|
|
if val, ok := config["enable_spell_effect_caching"].(bool); ok {
|
|
m.config.EnableSpellEffectCaching = val
|
|
}
|
|
}
|
|
|
|
// GetConfiguration returns current manager configuration
|
|
func (m *Manager) GetConfiguration() map[string]interface{} {
|
|
m.mutex.RLock()
|
|
defer m.mutex.RUnlock()
|
|
|
|
return map[string]interface{}{
|
|
"enable_statistics": m.config.EnableStatistics,
|
|
"enable_validation": m.config.EnableValidation,
|
|
"enable_combat_logging": m.config.EnableCombatLogging,
|
|
"max_entities_per_zone": m.config.MaxEntitiesPerZone,
|
|
"effect_cleanup_interval": m.config.EffectCleanupInterval,
|
|
"bonus_calculation_interval": m.config.BonusCalculationInterval,
|
|
"packet_builder_timeout": m.config.PacketBuilderTimeout,
|
|
"enable_pet_management": m.config.EnablePetManagement,
|
|
"enable_spell_effect_caching": m.config.EnableSpellEffectCaching,
|
|
}
|
|
}
|
|
|
|
// === Validation and Health Checks ===
|
|
|
|
// ValidateEntity performs comprehensive entity validation
|
|
func (m *Manager) ValidateEntity(entity *Entity) []string {
|
|
var issues []string
|
|
|
|
if entity == nil {
|
|
return []string{"entity is nil"}
|
|
}
|
|
|
|
info := entity.GetInfoStruct()
|
|
if info == nil {
|
|
issues = append(issues, "entity info struct is nil")
|
|
return issues
|
|
}
|
|
|
|
if info.GetLevel() < 0 {
|
|
issues = append(issues, fmt.Sprintf("invalid level: %d", info.GetLevel()))
|
|
}
|
|
|
|
if info.GetName() == "" {
|
|
issues = append(issues, "entity name is empty")
|
|
}
|
|
|
|
if entity.GetTotalHP() < 0 {
|
|
issues = append(issues, fmt.Sprintf("invalid total HP: %d", entity.GetTotalHP()))
|
|
}
|
|
|
|
if entity.GetTotalPower() < 0 {
|
|
issues = append(issues, fmt.Sprintf("invalid total power: %d", entity.GetTotalPower()))
|
|
}
|
|
|
|
return issues
|
|
}
|
|
|
|
// IsHealthy returns true if the manager is in a healthy state
|
|
func (m *Manager) IsHealthy() bool {
|
|
m.mutex.RLock()
|
|
defer m.mutex.RUnlock()
|
|
|
|
// Manager is always considered healthy for entities
|
|
// as it's primarily a utility manager
|
|
return true
|
|
} |