C#:
// Reference: 0Harmony
using System;
using System.Collections.Generic;
using HarmonyLib;
using Network;
using Network.Visibility;
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("CircularNetworkDistance", "Whispers88", "1.0.6")]
public class CircularNetworkDistance : RustPlugin
{
#region Harmony
void Init()
{
ConVar.Net.visibilityRadiusFarOverride = 6;
ConVar.Net.visibilityRadiusNearOverride = 4;
}
#endregion
[HarmonyPatch(typeof(NetworkVisibilityGrid), "GetVisibleFrom"), AutoPatch]
public static class GetVisibleFromPatch
{
[HarmonyPrefix]
public static bool Prefix(NetworkVisibilityGrid __instance, Group group, ListHashSet<Group> groups, int radius)
{
return GetVisibleFromCircle(__instance, group, groups, radius);
}
}
// hardcoded values because this is probably fastest
private static readonly List<int> EightCircle = new List<int>() { 2, 4, 6, 6, 7, 7, 8, 8, 8, 8, 8, 7, 7, 6, 6, 4, 2 };
private static readonly List<int> SevenCircle = new List<int>() { 2, 4, 5, 6, 6, 7, 7, 7, 7, 7, 6, 6, 5, 4, 2 };
private static readonly List<int> SixCircle = new List<int>() { 2, 4, 5, 5, 6, 6, 6, 6, 6, 5, 5, 4, 2 };
private static readonly List<int> FiveCircle = new List<int>() { 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2 };
private static readonly List<int> FourCircle = new List<int>() { 2, 3, 4, 4, 4, 4, 4, 3, 2 };
private static readonly List<int> ThreeCircle = new List<int>() { 1, 2, 3, 3, 3, 2, 1 };
private static readonly List<int> TwoCircle = new List<int>() { 1, 2, 2, 2, 1 };
static List<int>? GetCircleSizeLookup(int radius)
{
switch (radius)
{
case 8: return EightCircle;
case 7: return SevenCircle;
case 6: return SixCircle;
case 5: return FiveCircle;
case 4: return FourCircle;
case 3: return ThreeCircle;
case 2: return TwoCircle;
default: return null;
}
}
static bool GetVisibleFromCircle(NetworkVisibilityGrid grid, Group group, ListHashSet<Group> groups, int radius)
{
List<int>? lookup = GetCircleSizeLookup(radius);
if (lookup == null)
return true;
// Global netgroup
//groups.Add(Net.sv.visibility.Get(0));
grid.GetGlobalNetworkGroups(group, groups);
if (group.restricted)
{
groups.Add(group);
return false;
}
int id = (int)group.ID;
if (id < grid.startID)
return false;
ValueTuple<int, int, int> valueTuple = DeconstructGroupId(grid, id);
int item1 = valueTuple.Item1;
int item2 = valueTuple.Item2;
int item3 = valueTuple.Item3;
for (int deltaY = -radius; deltaY <= radius; deltaY++)
{
int bounds = lookup[deltaY + radius];
for (int deltaX = -bounds; deltaX <= bounds; deltaX++)
{
AddLayers(grid, groups, item1 + deltaX, item2 + deltaY, item3);
}
}
return false;
}
private static ValueTuple<int, int, int> DeconstructGroupId(NetworkVisibilityGrid grid, int groupId)
{
int num;
int num1;
groupId -= grid.startID;
int num2 = Math.DivRem(groupId, grid.cellCount * grid.cellCount, out num);
return new ValueTuple<int, int, int>(Math.DivRem(num, grid.cellCount, out num1), num1, num2);
}
static void AddLayers(NetworkVisibilityGrid grid, ListHashSet<Group> groups, int groupX, int groupY, int groupLayer)
{
Add(grid, groups, groupX, groupY, groupLayer);
if (groupLayer == 0)
{
Add(grid, groups, groupX, groupY, 1);
}
else if (groupLayer == 1)
{
Add(grid, groups, groupX, groupY, 2);
Add(grid, groups, groupX, groupY, 0);
}
else if (groupLayer == 2)
{
Add(grid, groups, groupX, groupY, 1);
}
}
static void Add(NetworkVisibilityGrid grid, ListHashSet<Group> groups, int groupX, int groupY, int groupLayer) => groups.Add(Net.sv.visibility.Get(CoordToID(grid, groupX, groupY, groupLayer)));
static uint CoordToID(NetworkVisibilityGrid grid, int x, int y, int layer) => (uint)(layer * (grid.cellCount * grid.cellCount) + x * grid.cellCount + y + grid.startID);
}
}