package main import ( "sync" "time" ) type CachedUuid struct { CleanUuid string Uuid string PlayerName string TimeFetched time.Time } type UUIDCache struct { mu sync.RWMutex lifetimeLimit time.Duration uuidMap map[string]*CachedUuid cleanUuidMap map[string]*CachedUuid playerNameMap map[string]*CachedUuid } func NewUUIDCache(lifetime time.Duration) *UUIDCache { return &UUIDCache{ lifetimeLimit: lifetime, uuidMap: make(map[string]*CachedUuid), cleanUuidMap: make(map[string]*CachedUuid), playerNameMap: make(map[string]*CachedUuid), } } func (c *UUIDCache) Add(cachedUuid *CachedUuid) { c.mu.Lock() defer c.mu.Unlock() c.uuidMap[cachedUuid.Uuid] = cachedUuid c.cleanUuidMap[cachedUuid.CleanUuid] = cachedUuid c.playerNameMap[cachedUuid.PlayerName] = cachedUuid } func (c *UUIDCache) GetByUuid(uuid string) (*CachedUuid, bool) { c.mu.RLock() defer c.mu.RUnlock() val, ok := c.uuidMap[uuid] return val, ok } func (c *UUIDCache) GetByCleanUuid(cleanUuid string) (*CachedUuid, bool) { c.mu.RLock() defer c.mu.RUnlock() val, ok := c.cleanUuidMap[cleanUuid] return val, ok } func (c *UUIDCache) GetByPlayerName(playerName string) (*CachedUuid, bool) { c.mu.RLock() defer c.mu.RUnlock() val, ok := c.playerNameMap[playerName] return val, ok } func (c *UUIDCache) Get(id string) (*CachedUuid, bool) { val, ok := c.GetByPlayerName(id) if ok { return val, ok } val, ok = c.GetByUuid(id) if ok { return val, ok } val, ok = c.GetByCleanUuid(id) return val, ok } func (c *UUIDCache) Delete(uuid string) { c.mu.Lock() defer c.mu.Unlock() if cachedUuid, ok := c.uuidMap[uuid]; ok { delete(c.uuidMap, cachedUuid.Uuid) delete(c.cleanUuidMap, cachedUuid.CleanUuid) delete(c.playerNameMap, cachedUuid.PlayerName) } } func (c *UUIDCache) Clean() { c.mu.Lock() defer c.mu.Unlock() now := time.Now() for uuid, cachedUuid := range c.uuidMap { if now.Sub(cachedUuid.TimeFetched) > c.lifetimeLimit { delete(c.uuidMap, uuid) delete(c.cleanUuidMap, cachedUuid.CleanUuid) delete(c.playerNameMap, cachedUuid.PlayerName) } } }