AlexMog / Longship

Valheim Dedicated server Fixes, Optimizations and High-Level API
MIT License
29 stars 3 forks source link

[Optimization] Optimise GetClosestPlayer #6

Open AlexMog opened 3 years ago

AlexMog commented 3 years ago

The method GetClosestPlayer seems to be used on Update behaviours, and is a bruteforce way to check which player is the closest. Better ways should be used to avoid checking all players.

Decompiled code (Class: Player):

public static Player GetClosestPlayer(Vector3 point, float maxRange)
{
    Player result = null;
    float num = 999999f;
    foreach (Player player in m_players)
    {
        float num2 = Vector3.Distance(player.transform.position, point);
        if (num2 < num && num2 < maxRange)
        {
            num = num2;
            result = player;
        }
    }
    return result;
}
AlexMog commented 3 years ago

In same class:

public static void MessageAllInRange(Vector3 point, float range, MessageHud.MessageType type, string msg, Sprite icon = null)
    {
        foreach (Player player in m_players)
        {
            if (Vector3.Distance(player.transform.position, point) < range)
            {
                player.Message(type, msg, 0, icon);
            }
        }
    }
AlexMog commented 3 years ago

In same class:

public static int GetPlayersInRangeXZ(Vector3 point, float range)
    {
        int num = 0;
        foreach (Player player in m_players)
        {
            if (Utils.DistanceXZ(player.transform.position, point) < range)
            {
                num++;
            }
        }
        return num;
    }

    public static void GetPlayersInRange(Vector3 point, float range, List<Player> players)
    {
        foreach (Player player in m_players)
        {
            if (Vector3.Distance(player.transform.position, point) < range)
            {
                players.Add(player);
            }
        }
    }

    public static bool IsPlayerInRange(Vector3 point, float range)
    {
        foreach (Player player in m_players)
        {
            if (Vector3.Distance(player.transform.position, point) < range)
            {
                return true;
            }
        }
        return false;
    }

    public static bool IsPlayerInRange(Vector3 point, float range, float minNoise)
    {
        foreach (Player player in m_players)
        {
            if (Vector3.Distance(player.transform.position, point) < range)
            {
                float noiseRange = player.GetNoiseRange();
                if (range <= noiseRange && noiseRange >= minNoise)
                {
                    return true;
                }
            }
        }
        return false;
    }

    public static Player GetPlayerNoiseRange(Vector3 point, float noiseRangeScale = 1f)
    {
        foreach (Player player in m_players)
        {
            float num = Vector3.Distance(player.transform.position, point);
            float noiseRange = player.GetNoiseRange();
            if (num < noiseRange * noiseRangeScale)
            {
                return player;
            }
        }
        return null;
    }