Editor/Dock/AvatarCache.cs
using System;
using System.Collections.Generic;
using Editor;
using Sandbox;
using Sandbox.Internal;

namespace TeamCreate;

public static class AvatarCache
{
    private sealed class Entry
    {
        public Texture Texture;

        public Pixmap Pixmap;

        public bool Failed;

        public int Conversions;

        public long RequestedAt;
    }

    private const int TextureSize = 64;

    private const int MaxWaitFrames = 600;

    private static readonly int[] ConvertAt = new int[3] { 3, 75, 225 };

    private static readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>(StringComparer.Ordinal);

    private static readonly List<string> pending = new List<string>();

    private static long frame;

    private static int cursor;

    private static readonly TimeSpan BudgetWindow = TimeSpan.FromMilliseconds(4L);

    private static DateTime lastSpend = DateTime.MinValue;

    public static Pixmap Get(string steamId)
    {
        Entry entry = EntryFor(steamId);
        return (entry == null || entry.Failed) ? null : entry.Pixmap;
    }

    /// <summary>Set only by a solo test copy: the reserved test identity shows this real account's picture. Null everywhere else.</summary>
    public static string SyntheticAvatarAlias { get; set; }

    public static Texture GetTexture(string steamId)
    {
        Entry entry = EntryFor(steamId);
        return (entry == null || entry.Failed) ? null : entry.Texture;
    }

    private static Entry EntryFor(string steamId)
    {
        if (string.IsNullOrWhiteSpace(steamId))
        {
            return null;
        }
        string text = steamId.Trim();
        if (SyntheticAvatarAlias != null && TestHarnessRules.IsSyntheticIdentity(text))
        {
            text = SyntheticAvatarAlias;
        }
        if (!entries.TryGetValue(text, out var value))
        {
            value = new Entry
            {
                RequestedAt = frame
            };
            entries[text] = value;
            pending.Add(text);
        }
        return value;
    }

    public static void Poll()
    {
        DateTime utcNow = DateTime.UtcNow;
        if (utcNow - lastSpend < BudgetWindow)
        {
            return;
        }
        lastSpend = utcNow;
        frame++;
        int num = 2;
        while (num > 0 && pending.Count > 0)
        {
            if (cursor >= pending.Count)
            {
                cursor = 0;
            }
            num--;
            if (Advance(pending[cursor]))
            {
                pending.RemoveAt(cursor);
            }
            else
            {
                cursor++;
            }
        }
    }

    public static void Clear()
    {
        entries.Clear();
        pending.Clear();
        cursor = 0;
    }

    private static bool Advance(string key)
    {
        if (!entries.TryGetValue(key, out var value))
        {
            return true;
        }
        if (value.Failed)
        {
            return true;
        }
        long num = frame - value.RequestedAt;
        try
        {
            if (value.Texture == null)
            {
                if (!long.TryParse(key, out var result) || result <= 0)
                {
                    return Fail(value);
                }
                value.Texture = Texture.LoadAvatar(key, 64);
            }
            if (value.Conversions >= ConvertAt.Length)
            {
                return true;
            }
            if (num < ConvertAt[value.Conversions])
            {
                return false;
            }
            if (!value.Texture.IsLoaded)
            {
                return num > 600 && Fail(value, null, log: true);
            }
            Pixmap pixmap = Pixmap.FromTexture(value.Texture);
            if (pixmap == null || pixmap.Width <= 0 || pixmap.Height <= 0)
            {
                return num > 600 && Fail(value, null, log: true);
            }
            value.Pixmap = pixmap;
            value.Conversions++;
            return value.Conversions >= ConvertAt.Length;
        }
        catch (Exception ex)
        {
            return Fail(value, CollaborationDiagnostics.Bounded(ex.Message), log: true);
        }
    }

    private static bool Fail(Entry entry, string reason = null, bool log = false)
    {
        entry.Failed = true;
        entry.Pixmap = null;
        entry.Texture = null;
        if (log)
        {
            GlobalGameNamespace.Log.Error("Collaboration avatars: " + CollaborationDiagnostics.Bounded(reason ?? "The avatar texture could not be loaded."));
        }
        return true;
    }
}