func (a *AttributeList) RemoveMask(name string, mask int) {
	a.SetVar(name, a.VarInt(name, 0)^mask)
}
RemoveMask checks for an int attribute with the specified name, and if it exists, tries to unset mask from it.
If it doesn't exist, or is another type, it Will set it to 0.
NOTE: mask parameter should be the index of the bit from the right most bit that you want to deactivate.
package entity
import (
	"fmt"
	"strconv"
	"sync"
	"time"
	"github.com/spkaeros/rscgo/pkg/log"
)
type entry struct {
	key   string
	Value interface{}
}
func (e entry) String() string {
	return e.key
}
type AttributeList struct {
	set  map[string]interface{}
	lock sync.RWMutex
}
func NewAttributeList() *AttributeList {
	return &AttributeList{set: make(map[string]interface{})}
}
func (a *AttributeList) Keys() (keys []string) {
	a.RangeK(func(k string) {
		keys = append(keys, k)
	})
	return
}
func (a *AttributeList) Values() (values []interface{}) {
	a.RangeV(func(v interface{}) {
		values = append(values, v)
	})
	return
}
func (a *AttributeList) Entries() (entries EntrySet) {
	a.ForEach(func(k string, v interface{}) {
		entries = append(entries, entry{k, v})
	})
	return
}
type EntrySet []entry
func (e EntrySet) Size() int {
	return len(e) - 1
}
func (e EntrySet) String() string {
	s := "[\n"
	for _, v := range e {
		s += "name:" + v.String() + ",value:"
		switch v.Value.(type) {
		case string:
			s += v.Value.(string) + ";\n"
		case fmt.Stringer:
			s += v.Value.(fmt.Stringer).String() + ";\n"
		case int:
			s += strconv.Itoa(v.Value.(int)) + ";\n"
		case bool:
			s += strconv.FormatBool(v.Value.(bool)) + ";\n"
		case int64:
			s += strconv.FormatInt(v.Value.(int64), 10) + ";\n"
		case float64:
			s += strconv.FormatFloat(v.Value.(float64), 'E', -1, 64) + ";\n"
		}
	}
	s += "\n]\n"
	return s
}
func (a *AttributeList) String() string {
	return a.Entries().String()
}
func (a *AttributeList) Range(fn func(string, interface{}) bool) {
	a.lock.RLock()
	defer a.lock.RUnlock()
	for k, v := range a.set {
		if fn(k, v) {
			return
		}
	}
}
func (a *AttributeList) ForEach(fn func(string, interface{})) {
	a.Range(func(s string, v interface{}) bool {
		if v != nil {
			fn(s, v)
		}
		return false
	})
}
func (a *AttributeList) RangeV(fn func(interface{})) {
	a.ForEach(func(s string, v interface{}) {
		fn(v)
	})
}
func (a *AttributeList) RangeK(fn func(string)) {
	a.ForEach(func(s string, v interface{}) {
		fn(s)
	})
}
func (a *AttributeList) Contains(name string) (ok bool) {
	_, ok = a.Var(name)
	return
}
func (a *AttributeList) SetVar(name string, value interface{}) {
	a.lock.Lock()
	a.set[name] = value
	a.lock.Unlock()
}
func (a *AttributeList) Var(name string) (interface{}, bool) {
	a.lock.RLock()
	defer a.lock.RUnlock()
	val, ok := a.set[name]
	return val, ok
}
func (a *AttributeList) UnsetVar(name string) {
	a.lock.Lock()
	defer a.lock.Unlock()
	if _, ok := a.set[name]; ok {
		a.set[name] = nil
		delete(a.set, name)
	}
}
func (a *AttributeList) Inc(name string, delta int) {
	a.SetVar(name, a.VarInt(name, 0)+delta)
}
func (a *AttributeList) Dec(name string, delta int) {
	a.SetVar(name, a.VarInt(name, 0)-delta)
}
func (a *AttributeList) VarChecked(name string) interface{} {
	if v, ok := a.Var(name); ok && v != nil {
		return v
	}
	return nil
}
func (a *AttributeList) VarString(name string, zero string) string {
	if s, ok := a.VarChecked(name).(string); ok && len(s) > 0 {
		return "" + s
	} else if s, ok := a.VarChecked(name).(fmt.Stringer); ok && s != nil {
		return "" + s.String()
	} else {
		log.Error.Printf("AttributeList[Type Error]: Expected string, got %T\n", s)
	}
	return zero
}
func (a *AttributeList) VarInt(name string, zero int) int {
	if v, ok := a.Var(name); ok && v != nil {
		if i, ok := v.(int); ok {
			return i
		}
	} else if ok {
		log.Error.Printf("AttributeList[Type Error]: Expected int, got %T\n", v)
		return zero
	}
	return zero
}
func (a *AttributeList) StoreMask(name string, mask int) {
	a.SetVar(name, a.VarInt(name, 0)|mask)
}
func (a *AttributeList) HasMasks(name string, masks ...int) bool {
	for _, mask := range masks {
		if a.CheckMask(name, mask) {
			return true
		}
	}
	return false
}