eq2go/internal/skills/master_skill_list.go

203 lines
5.0 KiB
Go

package skills
import (
"sync"
)
// MasterSkillList manages the master list of all available skills
type MasterSkillList struct {
skills map[int32]*Skill // All skills by ID
populatePackets map[int16][]byte // Cached packets by version
mutex sync.RWMutex // Thread safety
}
// NewMasterSkillList creates a new master skill list
func NewMasterSkillList() *MasterSkillList {
return &MasterSkillList{
skills: make(map[int32]*Skill),
populatePackets: make(map[int16][]byte),
}
}
// AddSkill adds a skill to the master list
func (msl *MasterSkillList) AddSkill(skill *Skill) {
if skill == nil {
return
}
msl.mutex.Lock()
defer msl.mutex.Unlock()
msl.skills[skill.SkillID] = skill
// Clear cached packets when skills change
msl.populatePackets = make(map[int16][]byte)
}
// GetSkillCount returns the total number of skills
func (msl *MasterSkillList) GetSkillCount() int16 {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
return int16(len(msl.skills))
}
// GetAllSkills returns a copy of all skills
func (msl *MasterSkillList) GetAllSkills() map[int32]*Skill {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
// Return a copy to prevent external modification
skills := make(map[int32]*Skill)
for id, skill := range msl.skills {
skills[id] = skill
}
return skills
}
// GetSkill returns a skill by ID
func (msl *MasterSkillList) GetSkill(skillID int32) *Skill {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
if skill, exists := msl.skills[skillID]; exists {
return skill
}
return nil
}
// GetSkillByName returns a skill by name (case-insensitive)
func (msl *MasterSkillList) GetSkillByName(skillName string) *Skill {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
// Convert to lowercase for comparison
lowerName := toLower(skillName)
for _, skill := range msl.skills {
if toLower(skill.Name.Data) == lowerName {
return skill
}
}
return nil
}
// GetPopulateSkillsPacket builds a packet containing all skills for a client version
func (msl *MasterSkillList) GetPopulateSkillsPacket(version int16) ([]byte, error) {
msl.mutex.Lock()
defer msl.mutex.Unlock()
// Check if we have a cached packet for this version
if packet, exists := msl.populatePackets[version]; exists {
// Return a copy of the cached packet
result := make([]byte, len(packet))
copy(result, packet)
return result, nil
}
// Build the packet - this is a placeholder implementation
// In the full implementation, this would use the PacketStruct system
// to build a proper WS_SkillMap packet for the given version
packet := msl.buildSkillMapPacket(version)
// Cache the packet
msl.populatePackets[version] = packet
// Return a copy
result := make([]byte, len(packet))
copy(result, packet)
return result, nil
}
// buildSkillMapPacket builds a WS_SkillMap packet
func (msl *MasterSkillList) buildSkillMapPacket(version int16) []byte {
// This is a placeholder implementation
// In a real implementation, this would use the PacketStruct system:
// packet := configReader.getStruct("WS_SkillMap", version)
// packet.setArrayLengthByName("skill_count", len(msl.skills))
// for i, skill := range msl.skills {
// packet.setArrayDataByName("skill_id", skill.SkillID, i)
// packet.setArrayDataByName("short_name", &skill.ShortName, i)
// packet.setArrayDataByName("name", &skill.Name, i)
// packet.setArrayDataByName("description", &skill.Description, i)
// }
// return packet.serialize()
// For now, return an empty packet
return make([]byte, 0)
}
// RemoveSkill removes a skill from the master list
func (msl *MasterSkillList) RemoveSkill(skillID int32) {
msl.mutex.Lock()
defer msl.mutex.Unlock()
delete(msl.skills, skillID)
// Clear cached packets when skills change
msl.populatePackets = make(map[int16][]byte)
}
// ClearSkills removes all skills from the master list
func (msl *MasterSkillList) ClearSkills() {
msl.mutex.Lock()
defer msl.mutex.Unlock()
msl.skills = make(map[int32]*Skill)
msl.populatePackets = make(map[int16][]byte)
}
// GetSkillsByType returns all skills of a specific type
func (msl *MasterSkillList) GetSkillsByType(skillType int32) []*Skill {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
var skills []*Skill
for _, skill := range msl.skills {
if skill.SkillType == skillType {
skills = append(skills, skill)
}
}
return skills
}
// HasSkill checks if a skill exists in the master list
func (msl *MasterSkillList) HasSkill(skillID int32) bool {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
_, exists := msl.skills[skillID]
return exists
}
// GetSkillIDs returns all skill IDs
func (msl *MasterSkillList) GetSkillIDs() []int32 {
msl.mutex.RLock()
defer msl.mutex.RUnlock()
ids := make([]int32, 0, len(msl.skills))
for id := range msl.skills {
ids = append(ids, id)
}
return ids
}
// toLower converts a string to lowercase (simple implementation)
func toLower(s string) string {
result := make([]byte, len(s))
for i, c := range []byte(s) {
if c >= 'A' && c <= 'Z' {
result[i] = c + 32
} else {
result[i] = c
}
}
return string(result)
}