Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ===== Guardian 1.7.10 PASTEBIN PART 2 of 2 =====
- // Continues from part 1 at #region _map_. Append this file under part 1.
- // Delete these header lines, then concatenate. Result must match Guardian.cs 1.7.10.
- #region _map_
- private class Map
- {
- public class Building
- {
- public static bool HasPrivilege(DecayEntity entity) =>
- entity.GetBuildingPrivilege() != null;
- public static bool InFoundation(Vector3 position)
- {
- try
- {
- RaycastHit hit;
- Physics.queriesHitBackfaces = true;
- if(Physics.Raycast(position, Vector3.up, out hit, 4.5f, Layers.Mask.Construction, QueryTriggerInteraction.Ignore))
- {
- var block = hit.GetEntity() as BuildingBlock;
- if((block != null) && Hit.IsFoundation(hit))
- {
- switch(block.grade)
- {
- case BuildingGrade.Enum.Stone:
- case BuildingGrade.Enum.Metal:
- case BuildingGrade.Enum.TopTier:
- return true;
- }
- }
- }
- }
- finally
- {
- Physics.queriesHitBackfaces = false;
- }
- return false;
- }
- public static bool IsNearby(Vector3 position, bool check_privilege = true)
- {
- // Facepunch removed Pool.GetList<T>() (CS0117). Use Pool.Get<List<T>>() instead.
- var blocks = Pool.Get<List<BuildingBlock>>();
- Vis.Entities(position, 16.0f, blocks, Layers.Mask.Construction, QueryTriggerInteraction.Ignore);
- bool nearby = false;
- foreach(var block in blocks)
- {
- if(check_privilege)
- {
- if(HasPrivilege(block))
- {
- nearby = true; break;
- }
- }
- else
- {
- nearby = true; break;
- }
- }
- Pool.FreeUnmanaged<BuildingBlock>(ref blocks);
- return nearby;
- }
- }
- public class Cave
- {
- public static bool IsInside(Vector3 position)
- {
- foreach(var hit in Physics.RaycastAll(position, Vector3.up, 125f, Layers.Mask.World))
- {
- if(Hit.IsCave(hit) || Hit.IsRock(hit))
- {
- return true;
- }
- }
- foreach(var hit in Physics.RaycastAll(position, Vector3.down, 125f, Layers.Mask.World))
- {
- if(Hit.IsCave(hit))
- {
- return true;
- }
- }
- return false;
- }
- }
- public class Collider
- {
- public static string Info(Vector3 position)
- {
- var colliders = new List<string>();
- foreach(var hit in Physics.RaycastAll(position, Vector3.up, 50.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- colliders.Add($"{hit.collider.name} ({hit.distance}m)");
- }
- try
- {
- RaycastHit hit;
- Physics.queriesHitBackfaces = true;
- if(Physics.Raycast(new Vector3(position.x, position.y + 0.1f, position.z), Vector3.up, out hit, 4.5f, Layers.Mask.Construction, QueryTriggerInteraction.Ignore))
- {
- if(Hit.IsFoundation(hit))
- {
- colliders.Add($"foundation ({hit.distance}m)");
- }
- }
- }
- finally
- {
- Physics.queriesHitBackfaces = false;
- }
- var up = colliders.Count > 0 ? $"\nUp: {string.Join(", ", colliders)}" : string.Empty;
- colliders.Clear();
- foreach(var hit in Physics.RaycastAll(position, Vector3.down, 50.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- colliders.Add($"{hit.collider.name} ({hit.distance}m)");
- }
- var dn = colliders.Count > 0 ? $"\nDn: {string.Join(", ", colliders)}" : string.Empty;
- return $"{up}{dn}";
- }
- }
- public class Entities
- {
- public static bool InRange(Vector3 position, float radius = 3.0f)
- {
- // Facepunch removed Pool.GetList<T>() / Pool.FreeList (CS0117).
- var entities = Pool.Get<List<DecayEntity>>();
- Vis.Entities(position, radius, entities);
- bool nearby = entities.Count > 0;
- Pool.FreeUnmanaged<DecayEntity>(ref entities);
- return nearby;
- }
- }
- public static string Grid(Vector3 position)
- {
- const double scale = 1.0 / 146.304;
- float normal = World.Size >> 1;
- if((Math.Abs(position.x) > normal) || (Math.Abs(position.z) > normal))
- {
- return string.Empty;
- }
- int x = (int)((normal + position.x) * scale);
- int y = (int)((normal - position.z) * scale);
- int r, q = Math.DivRem(x, 26, out r);
- if(q > 0)
- {
- return $"{Convert.ToChar(64 + q)}{Convert.ToChar(65 + r)}{y}";
- }
- else
- {
- return $"{Convert.ToChar(65 + r)}{y}";
- }
- }
- private class Hit
- {
- private static string Collider(RaycastHit hit) =>
- hit.collider?.name.ToLower() ?? string.Empty;
- public static bool IsBunker(RaycastHit hit) =>
- IsBunker(Collider(hit));
- public static bool IsBunker(string collider) =>
- collider.Contains("bunker.");
- public static bool IsCave(RaycastHit hit) =>
- IsCave(Collider(hit));
- public static bool IsCave(string collider) =>
- collider.Contains("cave_");
- public static bool IsCorridor(RaycastHit hit) =>
- IsCorridor(Collider(hit));
- public static bool IsCorridor(string collider) =>
- collider.Contains("corridor_");
- public static bool IsDuct(RaycastHit hit) =>
- IsDuct(Collider(hit));
- public static bool IsDuct(string collider) =>
- collider.Contains("duct_");
- public static bool IsFoundation(RaycastHit hit) =>
- IsFoundation(Collider(hit));
- public static bool IsFoundation(string collider) =>
- collider.Contains("foundation.");
- public static bool IsMine(RaycastHit hit) =>
- IsMine(Collider(hit));
- public static bool IsMine(string collider) =>
- collider.Contains("mine_tnl_");
- public static bool IsRoad(RaycastHit hit) =>
- IsRoad(Collider(hit));
- public static bool IsRoad(string collider) =>
- collider.Contains("road");
- public static bool IsRock(RaycastHit hit) =>
- IsRock(Collider(hit));
- public static bool IsRock(string collider) =>
- collider.Contains("rock_");
- public static bool IsStairwell(RaycastHit hit) =>
- IsStairwell(Collider(hit));
- public static bool IsStairwell(string collider) =>
- collider.Contains("stairwell_");
- public static bool IsTunnel(RaycastHit hit) =>
- IsTunnel(Collider(hit));
- public static bool IsTunnel(string collider) =>
- collider.Contains("tunnel");
- public static bool IsUnderground(RaycastHit hit) =>
- IsUnderground(Collider(hit));
- public static bool IsUnderground(string collider)
- {
- foreach(var partition in collider.Split('_', '.'))
- {
- switch(partition)
- {
- case "bunker":
- case "corridor":
- case "duct":
- case "mine":
- case "stairwell":
- case "tunnel":
- return true;
- }
- }
- return false;
- }
- }
- public static bool InRange(Vector3 a, Vector3 b, float distance) =>
- (a - b).sqrMagnitude <= distance * distance;
- public static bool InRange2D(Vector3 a, Vector3 b, float distance) =>
- InRange(new Vector3(a.x, 0f, a.z), new Vector3(b.x, 0f, b.z), distance);
- public static void Load()
- {
- _instance.timer.In(0.1f, () => Monument.Load());
- }
- public class Monument
- {
- private static SparseMap global = new SparseMap(4.0f);
- private static SparseMap tunnel = new SparseMap(4.0f);
- public static bool IsNearby(Vector3 position) =>
- global.Test(position);
- public static bool IsTunnel(Vector3 position) =>
- tunnel.Test(position);
- public static void Load()
- {
- foreach(var monument in TerrainMeta.Path.Monuments)
- {
- var center = monument.transform.position;
- var radius = Range(monument);
- global.Set(center, radius);
- if(monument.name.Contains("entrance"))
- {
- tunnel.Set(center, radius);
- }
- }
- }
- private static float Range(MonumentInfo monument)
- {
- var separator = monument.name.LastIndexOf('/');
- switch((separator > 0) ? monument.name.Substring(separator + 1).Replace(".prefab", "") : monument.name)
- {
- case "airfield_1": return 255f;
- case "bandit_town": return 105f;
- case "cave_large_hard":
- case "cave_large_medium":
- case "cave_large_sewers_hard":
- case "cave_medium_easy":
- case "cave_medium_hard":
- case "cave_medium_medium":
- case "cave_small_easy":
- case "cave_small_hard":
- case "cave_small_medium": return 75f;
- case "compound": return 255f;
- case "entrance": return 20f;
- case "excavator_1": return 150f;
- case "fishing_village_a":
- case "fishing_village_b":
- case "fishing_village_c": return 55f;
- case "gas_station_1": return 60f;
- case "harbor_1":
- case "harbor_2": return 135f;
- case "junkyard_1": return 105f;
- case "launch_site_1": return 245f;
- case "lighthouse": return 50f;
- case "military_tunnel_1": return 105f;
- case "mining_quarry_a":
- case "mining_quarry_b":
- case "mining_quarry_c": return 30f;
- case "OilrigAI": return 100f;
- case "OilrigAI2": return 200f;
- case "power_sub_big_1":
- case "power_sub_big_2": return 30f;
- case "power_sub_small_1":
- case "power_sub_small_2": return 25f;
- case "powerplant_1": return 145f;
- case "radtown_small_3": return 95f;
- case "satellite_dish": return 85f;
- case "sphere_tank": return 75f;
- case "stables_a":
- case "stables_b": return 80f;
- case "supermarket_1": return 60f;
- case "swamp_a":
- case "swamp_b": return 30f;
- case "swamp_c": return 55f;
- case "trainyard_1": return 145f;
- case "warehouse": return 50f;
- case "water_treatment_plant_1": return 175f;
- case "water_well_a":
- case "water_well_b":
- case "water_well_c":
- case "water_well_d":
- case "water_well_e": return 30f;
- }
- return 50.0f;
- }
- public static void Unload()
- {
- global.Clear();
- tunnel.Clear();
- }
- }
- public class Position
- {
- [Flags]
- public enum Check : ulong
- {
- None = 0ul,
- Building = 1ul,
- Entities = 1ul << 1,
- Monument = 1ul << 2,
- Road = 1ul << 3,
- Terrain = 1ul << 4,
- Water = 1ul << 5,
- All = ~0ul
- }
- private static bool HasCheck(Check checks, Check check) =>
- (checks & check) == check;
- public static Vector3 Random(Check checks = Check.All)
- {
- var max = (float)(World.Size >> 1);
- var min = -max;
- Vector3 position;
- do
- {
- position = Surface(Random(min, max, min, max));
- if(HasCheck(checks, Check.Terrain))
- {
- if(!Terrain.IsSurface(position))
- {
- continue;
- }
- }
- else if(HasCheck(checks, Check.Water) && !Water.IsSurface(position))
- {
- continue;
- }
- if(HasCheck(checks, Check.Monument) && Monument.IsNearby(position))
- {
- continue;
- }
- if(HasCheck(checks, Check.Road) && Road.IsNearby(position))
- {
- continue;
- }
- if(HasCheck(checks, Check.Building) && Building.IsNearby(position))
- {
- continue;
- }
- if(HasCheck(checks, Check.Entities) && Entities.InRange(position))
- {
- continue;
- }
- }
- while(Rock.IsInside(position));
- return position;
- }
- private static Vector3 Random(float min_x, float max_x, float min_z, float max_z) =>
- new Vector3(Core.Random.Range(min_x, max_x), 0.0f, Core.Random.Range(min_z, max_z));
- }
- public class Road
- {
- public static bool IsNearby(Vector3 position)
- {
- position = Terrain.Level(position, 0.5f);
- foreach(var hit in Physics.RaycastAll(position, Vector3.down, 25.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- if(Hit.IsRoad(hit))
- {
- return true;
- }
- }
- return false;
- }
- }
- public class Rock
- {
- public static bool IsInside(Vector3 position, bool check_cave = true)
- {
- if(check_cave && Cave.IsInside(position))
- {
- return false;
- }
- try
- {
- RaycastHit hit;
- Physics.queriesHitBackfaces = true;
- if(Physics.Raycast(position, Vector3.up, out hit, 25.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- return Hit.IsRock(hit);
- }
- }
- finally
- {
- Physics.queriesHitBackfaces = false;
- }
- return false;
- }
- }
- public static Vector3 Surface(Vector3 position, float offset = 0.0f) =>
- Terrain.IsSurface(position) ? Terrain.Level(position, offset) : Water.Level(position, offset);
- public class Terrain
- {
- public static float Height(Vector3 position) =>
- TerrainMeta.HeightMap.GetHeight(position);
- public static bool IsInside(Vector3 position, bool check_cave = true)
- {
- var elevation = Height(position);
- if((elevation - 1.0f) > position.y)
- {
- float c_x = position.x + 1.0f, f_x = position.x - 1.0f;
- float c_z = position.z + 1.0f, f_z = position.z - 1.0f;
- elevation = Math.Min(elevation, Height(new Vector3(c_x, 0, c_z)));
- elevation = Math.Min(elevation, Height(new Vector3(c_x, 0, f_z)));
- elevation = Math.Min(elevation, Height(new Vector3(f_x, 0, c_z)));
- elevation = Math.Min(elevation, Height(new Vector3(f_x, 0, f_z)));
- if((elevation - 1.0f) > position.y)
- {
- if(check_cave && Cave.IsInside(position))
- {
- return false;
- }
- else if(Underground.IsInside(position))
- {
- return false;
- }
- else if(Monument.IsNearby(position))
- {
- return (elevation - 51.0f) > position.y;
- }
- return true;
- }
- }
- return false;
- }
- public static bool IsSurface(Vector3 position) =>
- Height(position) > Water.Height(position);
- public static Vector3 Level(Vector3 position, float offset = 0.0f) =>
- new Vector3(position.x, Height(position) + offset, position.z);
- }
- public class Underground
- {
- public static bool IsInside(Vector3 position)
- {
- if(Monument.IsTunnel(position))
- {
- return true;
- }
- foreach(var hit in Physics.RaycastAll(position, Vector3.up, 25.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- if(Hit.IsUnderground(hit))
- {
- return true;
- }
- }
- foreach(var hit in Physics.RaycastAll(position, Vector3.down, 25.0f, Layers.Mask.World, QueryTriggerInteraction.Ignore))
- {
- if(Hit.IsUnderground(hit))
- {
- return true;
- }
- }
- return false;
- }
- }
- public static void Unload() => Monument.Unload();
- public class Water
- {
- public static float Height(Vector3 position) =>
- TerrainMeta.WaterMap.GetHeight(position);
- public static bool IsSurface(Vector3 position) =>
- Height(position) > Terrain.Height(position);
- public static Vector3 Level(Vector3 position, float offset = 0.0f) =>
- new Vector3(position.x, Height(position) + offset, position.z);
- }
- }
- #endregion _map_
- #region _permissions_
- private class Permissions
- {
- private static string PERMISSION_ADMIN;
- private static string PERMISSION_ALL;
- private static string PERMISSION_IGNORE;
- private static string PERMISSION_PREFIX;
- private static readonly HashSet<ulong> all = new HashSet<ulong>();
- private static readonly HashSet<ulong> admin = new HashSet<ulong>();
- private static readonly HashSet<ulong> ignore = new HashSet<ulong>();
- public static bool Admin(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_ADMIN) : admin.Contains(userid)) || All(userid, forced);
- public static bool All(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_ALL) : all.Contains(userid));
- public class Bypass
- {
- private static string PERMISSION_PREFIX;
- private static string PERMISSION_STEAM;
- private static string PERMISSION_VPN;
- private static readonly HashSet<ulong> steam = new HashSet<ulong>();
- private static readonly HashSet<ulong> vpn = new HashSet<ulong>();
- public class AntiCheat
- {
- private static readonly HashSet<ulong> aim = new HashSet<ulong>();
- private static readonly HashSet<ulong> firerate = new HashSet<ulong>();
- private static readonly HashSet<ulong> gravity = new HashSet<ulong>();
- private static readonly HashSet<ulong> meleerate = new HashSet<ulong>();
- private static readonly HashSet<ulong> recoil = new HashSet<ulong>();
- private static readonly HashSet<ulong> server = new HashSet<ulong>();
- private static readonly HashSet<ulong> stash = new HashSet<ulong>();
- private static readonly HashSet<ulong> trajectory = new HashSet<ulong>();
- private static readonly HashSet<ulong> wallhack = new HashSet<ulong>();
- private static string PERMISSION_AIM;
- private static string PERMISSION_FIRERATE;
- private static string PERMISSION_GRAVITY;
- private static string PERMISSION_MELEERATE;
- private static string PERMISSION_PREFIX;
- private static string PERMISSION_RECOIL;
- private static string PERMISSION_SERVER;
- private static string PERMISSION_STASH;
- private static string PERMISSION_TRAJECTORY;
- private static string PERMISSION_WALLHACK;
- public static void Load()
- {
- PERMISSION_PREFIX = Bypass.PERMISSION_PREFIX + "anticheat.";
- PERMISSION_AIM = PERMISSION_PREFIX + "aim";
- PERMISSION_FIRERATE = PERMISSION_PREFIX + "firerate";
- PERMISSION_GRAVITY = PERMISSION_PREFIX + "gravity";
- PERMISSION_MELEERATE = PERMISSION_PREFIX + "meleerate";
- PERMISSION_RECOIL = PERMISSION_PREFIX + "recoil";
- PERMISSION_SERVER = PERMISSION_PREFIX + "server";
- PERMISSION_STASH = PERMISSION_PREFIX + "stash";
- PERMISSION_TRAJECTORY = PERMISSION_PREFIX + "trajectory";
- PERMISSION_WALLHACK = PERMISSION_PREFIX + "wallhack";
- _instance.permission.RegisterPermission(PERMISSION_AIM, _instance);
- _instance.permission.RegisterPermission(PERMISSION_FIRERATE, _instance);
- _instance.permission.RegisterPermission(PERMISSION_GRAVITY, _instance);
- _instance.permission.RegisterPermission(PERMISSION_MELEERATE, _instance);
- _instance.permission.RegisterPermission(PERMISSION_RECOIL, _instance);
- _instance.permission.RegisterPermission(PERMISSION_SERVER, _instance);
- _instance.permission.RegisterPermission(PERMISSION_STASH, _instance);
- _instance.permission.RegisterPermission(PERMISSION_TRAJECTORY, _instance);
- _instance.permission.RegisterPermission(PERMISSION_WALLHACK, _instance);
- }
- public static bool Aim(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_AIM) : aim.Contains(userid)) || All(userid, forced);
- public static bool FireRate(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_FIRERATE) : firerate.Contains(userid)) || All(userid, forced);
- public static bool Gravity(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_GRAVITY) : gravity.Contains(userid)) || All(userid, forced);
- public static bool MeleeRate(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_MELEERATE) : meleerate.Contains(userid)) || All(userid, forced);
- public static bool Recoil(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_RECOIL) : recoil.Contains(userid)) || All(userid, forced);
- public static void Reset(ulong userid)
- {
- aim.Remove(userid);
- firerate.Remove(userid);
- gravity.Remove(userid);
- meleerate.Remove(userid);
- recoil.Remove(userid);
- server.Remove(userid);
- stash.Remove(userid);
- trajectory.Remove(userid);
- wallhack.Remove(userid);
- }
- public static bool Server(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_SERVER) : server.Contains(userid)) || All(userid, forced);
- public static bool Stash(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_STASH) : stash.Contains(userid)) || All(userid, forced);
- public static bool Trajectory(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_TRAJECTORY) : trajectory.Contains(userid)) || All(userid, forced);
- public static void Unload()
- {
- PERMISSION_AIM = null;
- PERMISSION_FIRERATE = null;
- PERMISSION_GRAVITY = null;
- PERMISSION_MELEERATE = null;
- PERMISSION_PREFIX = null;
- PERMISSION_RECOIL = null;
- PERMISSION_SERVER = null;
- PERMISSION_STASH = null;
- PERMISSION_TRAJECTORY = null;
- PERMISSION_WALLHACK = null;
- aim.Clear();
- firerate.Clear();
- gravity.Clear();
- meleerate.Clear();
- recoil.Clear();
- server.Clear();
- stash.Clear();
- trajectory.Clear();
- wallhack.Clear();
- }
- public static void Update(ulong userid)
- {
- if(!userid.IsSteamId())
- {
- return;
- }
- Permissions.Update(userid, PERMISSION_AIM, aim);
- Permissions.Update(userid, PERMISSION_FIRERATE, firerate);
- Permissions.Update(userid, PERMISSION_GRAVITY, gravity);
- Permissions.Update(userid, PERMISSION_MELEERATE, meleerate);
- Permissions.Update(userid, PERMISSION_RECOIL, recoil);
- Permissions.Update(userid, PERMISSION_SERVER, server);
- Permissions.Update(userid, PERMISSION_STASH, stash);
- Permissions.Update(userid, PERMISSION_TRAJECTORY, trajectory);
- Permissions.Update(userid, PERMISSION_WALLHACK, wallhack);
- }
- public static bool WallHack(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_WALLHACK) : wallhack.Contains(userid)) || All(userid, forced);
- }
- public static void Load()
- {
- PERMISSION_PREFIX = Permissions.PERMISSION_PREFIX + "bypass.";
- PERMISSION_STEAM = PERMISSION_PREFIX + "steam";
- PERMISSION_VPN = PERMISSION_PREFIX + "vpn";
- _instance.permission.RegisterPermission(PERMISSION_STEAM, _instance);
- _instance.permission.RegisterPermission(PERMISSION_VPN, _instance);
- AntiCheat.Load();
- }
- public static void Reset(ulong userid)
- {
- steam.Remove(userid);
- vpn.Remove(userid);
- AntiCheat.Reset(userid);
- }
- public static bool Steam(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_STEAM) : steam.Contains(userid)) || All(userid, forced);
- public static void Unload()
- {
- PERMISSION_PREFIX = null;
- PERMISSION_STEAM = null;
- PERMISSION_VPN = null;
- steam.Clear();
- vpn.Clear();
- AntiCheat.Unload();
- }
- public static void Update(ulong userid)
- {
- Permissions.Update(userid, PERMISSION_STEAM, vpn);
- Permissions.Update(userid, PERMISSION_VPN, vpn);
- AntiCheat.Update(userid);
- }
- public static bool Vpn(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_VPN) : vpn.Contains(userid)) || All(userid, forced);
- }
- public class Command
- {
- private static readonly HashSet<ulong> config = new HashSet<ulong>();
- private static readonly HashSet<ulong> ip = new HashSet<ulong>();
- private static readonly HashSet<ulong> server = new HashSet<ulong>();
- private static readonly HashSet<ulong> tp = new HashSet<ulong>();
- private static readonly HashSet<ulong> vpn = new HashSet<ulong>();
- private static string PERMISSION_CONFIG;
- private static string PERMISSION_IP;
- private static string PERMISSION_PREFIX;
- private static string PERMISSION_SERVER;
- private static string PERMISSION_TP;
- private static string PERMISSION_VPN;
- public static void Load()
- {
- PERMISSION_PREFIX = Permissions.PERMISSION_PREFIX + "command.";
- PERMISSION_CONFIG = PERMISSION_PREFIX + "config";
- PERMISSION_IP = PERMISSION_PREFIX + "ip";
- PERMISSION_SERVER = PERMISSION_PREFIX + "server";
- PERMISSION_TP = PERMISSION_PREFIX + "teleport";
- PERMISSION_VPN = PERMISSION_PREFIX + "vpn";
- _instance.permission.RegisterPermission(PERMISSION_CONFIG, _instance);
- _instance.permission.RegisterPermission(PERMISSION_IP, _instance);
- _instance.permission.RegisterPermission(PERMISSION_SERVER, _instance);
- _instance.permission.RegisterPermission(PERMISSION_TP, _instance);
- _instance.permission.RegisterPermission(PERMISSION_VPN, _instance);
- }
- public static bool Config(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_CONFIG) : config.Contains(userid)) || All(userid, forced);
- public static bool Ip(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_IP) : ip.Contains(userid)) || All(userid, forced);
- public static void Reset(ulong userid)
- {
- config.Remove(userid);
- ip.Remove(userid);
- server.Remove(userid);
- tp.Remove(userid);
- vpn.Remove(userid);
- }
- public static bool Server(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_SERVER) : server.Contains(userid)) || All(userid, forced);
- public static bool Tp(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_SERVER) : server.Contains(userid)) || All(userid, forced);
- public static void Unload()
- {
- PERMISSION_CONFIG = null;
- PERMISSION_IP = null;
- PERMISSION_PREFIX = null;
- PERMISSION_SERVER = null;
- PERMISSION_TP = null;
- PERMISSION_VPN = null;
- config.Clear();
- ip.Clear();
- server.Clear();
- tp.Clear();
- vpn.Clear();
- }
- public static void Update(ulong userid)
- {
- Permissions.Update(userid, PERMISSION_CONFIG, config);
- Permissions.Update(userid, PERMISSION_IP, ip);
- Permissions.Update(userid, PERMISSION_SERVER, server);
- Permissions.Update(userid, PERMISSION_TP, tp);
- Permissions.Update(userid, PERMISSION_VPN, vpn);
- }
- public static bool Vpn(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_VPN) : vpn.Contains(userid)) || All(userid, forced);
- }
- public static string[] Groups(ulong userid) =>
- _instance.permission.GetUserGroups(userid.ToString());
- private static bool HasPermission(ulong userid, string permission) =>
- _instance.permission.UserHasPermission(userid.ToString(), permission);
- public static bool HasPrefix(string permission) =>
- permission.StartsWith(PERMISSION_PREFIX);
- public static bool Ignore(ulong userid, bool forced = false) =>
- (forced ? HasPermission(userid, PERMISSION_IGNORE) : ignore.Contains(userid)) || All(userid, forced);
- public static void Load()
- {
- PERMISSION_PREFIX = _instance.Name.ToLower() + ".";
- PERMISSION_ALL = PERMISSION_PREFIX + "all";
- PERMISSION_ADMIN = PERMISSION_PREFIX + "admin";
- PERMISSION_IGNORE = PERMISSION_PREFIX + "ignore";
- _instance.permission.RegisterPermission(PERMISSION_ALL, _instance);
- _instance.permission.RegisterPermission(PERMISSION_ADMIN, _instance);
- _instance.permission.RegisterPermission(PERMISSION_IGNORE, _instance);
- Bypass.Load();
- Command.Load();
- }
- public static void Reset(ulong userid)
- {
- all.Remove(userid);
- admin.Remove(userid);
- ignore.Remove(userid);
- Bypass.Reset(userid);
- Command.Reset(userid);
- }
- public static void Unload()
- {
- PERMISSION_ALL = null;
- PERMISSION_ADMIN = null;
- PERMISSION_IGNORE = null;
- PERMISSION_PREFIX = null;
- all.Clear();
- admin.Clear();
- ignore.Clear();
- Bypass.Unload();
- Command.Unload();
- }
- public static void Update(ulong userid)
- {
- if(!userid.IsSteamId())
- {
- return;
- }
- Update(userid, PERMISSION_ALL, all);
- Update(userid, PERMISSION_ADMIN, admin);
- Update(userid, PERMISSION_IGNORE, ignore);
- Bypass.Update(userid);
- Command.Update(userid);
- }
- private static bool Update(ulong userid, string permission, HashSet<ulong> cache) =>
- HasPermission(userid, permission) ? cache.Add(userid) : cache.Remove(userid);
- }
- #endregion _permissions_
- #region _projectile_
- private class Projectile
- {
- public class Log
- {
- private static readonly Queue<Entry> expired = new Queue<Entry>();
- private static readonly Dictionary<ulong, Queue<Entry>> history = new Dictionary<ulong, Queue<Entry>>();
- private static readonly Dictionary<ulong, Dictionary<int, Entry>> pending = new Dictionary<ulong, Dictionary<int, Entry>>();
- private static readonly Queue<Request> request = new Queue<Request>();
- private static readonly Queue<Entry> reserve = new Queue<Entry>();
- static readonly StringBuilder buffer = new StringBuilder();
- private class Entry
- {
- public float aim_angle;
- public float aim_pvp;
- public float aim_range;
- public ulong aim_violations;
- public string attacker;
- public ulong attacker_id;
- public ulong firerate_violations;
- public float hit_distance;
- public HitArea hit_location;
- public bool pvp;
- public float recoil_pitch;
- public ulong recoil_repeats;
- public float recoil_swing;
- public ulong recoil_violations;
- public float recoil_yaw;
- public bool ricochet;
- public float speed;
- public DateTime timestamp;
- public float trajectory;
- public ulong trajectory_violations;
- public string victim;
- public bool violations;
- public ulong wallhack_violations;
- public string weapon;
- private static readonly Queue<Entry> pool = new Queue<Entry>();
- private Entry(DateTime timestamp)
- {
- Default().Set(timestamp);
- }
- private Entry Default()
- {
- aim_angle = 1;
- aim_pvp = 1;
- aim_range = 1;
- aim_violations = 0;
- attacker = null;
- attacker_id = 0;
- firerate_violations = 0;
- hit_distance = 0;
- hit_location = 0;
- pvp = false;
- recoil_pitch = 1;
- recoil_repeats = 0;
- recoil_swing = 0;
- recoil_violations = 0;
- recoil_yaw = 1;
- speed = 0;
- trajectory = 1;
- trajectory_violations = 0;
- victim = null;
- violations = false;
- wallhack_violations = 0;
- weapon = null;
- return this;
- }
- public string Format(bool collapse, bool id, bool time)
- {
- buffer.Clear();
- if(time)
- {
- var delta = DateTime.UtcNow.Subtract(timestamp);
- buffer.Append(((int)delta.TotalSeconds).ToString("D5")).Append('.').Append((delta.Milliseconds / 10).ToString("D2")).Append("s ");
- }
- buffer.Append("Recoil[").Append(recoil_repeats.ToString("D2"));
- buffer.Append("](x=").Append(recoil_yaw.ToString("F6"));
- buffer.Append(", y=").Append(recoil_pitch.ToString("F6"));
- buffer.Append(", a=").Append(recoil_swing.ToString("F1"));
- buffer.Append(')');
- if(!(collapse && string.IsNullOrEmpty(victim)))
- {
- buffer.Append(" Trajectory(").Append(trajectory.ToString("F6")).Append(')');
- buffer.Append(" Aim(a=").Append(aim_angle.ToString("F6")).Append(", p=").Append(aim_pvp.ToString("F6")).Append(", r=").Append(aim_range.ToString("F6")).Append(')');
- }
- if(id)
- {
- buffer.Append(' ').Append(attacker).Append('[').Append(attacker_id.ToString()).Append(']');
- }
- buffer.Append(" (").Append(speed.ToString("F1")).Append("m/s, ").Append(weapon).Append(')');
- if(victim != null)
- {
- buffer.Append(": ").Append(victim).Append('[').Append(Text.BodyPart(hit_location)).Append(", ").Append(hit_distance.ToString("F1")).Append("m]");
- }
- if(violations)
- {
- buffer.Append(' ');
- if( aim_violations > 0) buffer.Append("[A]");
- if( firerate_violations > 0) buffer.Append("[F]");
- if( recoil_violations > 0) buffer.Append("[R]");
- if(trajectory_violations > 0) buffer.Append("[T]");
- if( wallhack_violations > 0) buffer.Append("[W]");
- }
- return buffer.ToString();
- }
- public static Entry Get(DateTime timestamp) => (pool.Count > 0) ? pool.Dequeue().Set(timestamp) : new Entry(timestamp);
- public void Release() => pool.Enqueue(Default());
- private Entry Set(DateTime timestamp)
- {
- this.timestamp = timestamp;
- return this;
- }
- public static void Unload() => pool.Clear();
- }
- private class Request
- {
- public IPlayer actor;
- public int lines;
- public ulong userid;
- }
- public static void Add(Weapon weapon)
- {
- Dictionary<int, Entry> _pending;
- if(!pending.TryGetValue(weapon.Player.userID, out _pending))
- {
- pending.Add(weapon.Player.userID, _pending = new Dictionary<int, Entry>());
- }
- foreach(var projectileid in weapon.Projectiles)
- {
- try
- {
- _pending.Add(projectileid, Entry.Get(weapon.Fired));
- }
- catch(Exception e)
- {
- Guardian.Log.Warning($"Projectile.Log.Add({projectileid}): {weapon.Name}({e.Message})");
- }
- }
- }
- public static void Expire(Weapon weapon)
- {
- Dictionary<int, Entry> _pending;
- if(pending.TryGetValue(weapon.Player.userID, out _pending))
- {
- foreach(var projectileid in weapon.Projectiles)
- {
- Entry entry;
- if(_pending.TryGetValue(projectileid, out entry))
- {
- _pending.Remove(projectileid);
- if(config.Log.Projectile.Verbose || entry.violations || (entry.victim != null) || (weapon.Projectiles.Count == 1))
- {
- reserve.Enqueue(entry);
- }
- else
- {
- expired.Enqueue(entry);
- }
- }
- }
- while(expired.Count > 0)
- {
- expired.Dequeue().Release();
- }
- Queue<Entry> _history;
- if(!history.TryGetValue(weapon.Player.userID, out _history))
- {
- history.Add(weapon.Player.userID, _history = new Queue<Entry>());
- }
- while(reserve.Count > 0)
- {
- if(_history.Count > 64)
- {
- _history.Dequeue().Release();
- }
- _history.Enqueue(reserve.Dequeue());
- }
- }
- }
- public static void Get(IPlayer actor, ulong userid, int lines)
- {
- request.Enqueue(new Request { actor = actor, lines = lines, userid = userid });
- }
- public static float GetAimAngle(ulong userid, int id)
- {
- var aim_angle = 0.0f;
- TrySetEntry(userid, id, entry =>
- {
- aim_angle = entry.aim_angle;
- });
- return aim_angle;
- }
- public static bool GetAimPvp(ulong userid, int id)
- {
- var pvp = false;
- TrySetEntry(userid, id, entry =>
- {
- pvp = entry.pvp;
- });
- return pvp;
- }
- public static float GetHitDistance(ulong userid, int id)
- {
- var hit_distance = 0.0f;
- TrySetEntry(userid, id, entry =>
- {
- hit_distance = entry.hit_distance;
- });
- return hit_distance;
- }
- public static HitArea GetHitLocation(ulong userid, int id)
- {
- var hit_location = (HitArea)0;
- TrySetEntry(userid, id, entry =>
- {
- hit_location = entry.hit_location;
- });
- return hit_location;
- }
- public static bool GetRicochet(ulong userid, int id)
- {
- var ricochet = false;
- TrySetEntry(userid, id, entry =>
- {
- ricochet = entry.ricochet;
- });
- return ricochet;
- }
- public static string GetVictim(ulong userid, int id)
- {
- var victim = string.Empty;
- TrySetEntry(userid, id, entry =>
- {
- victim = entry.victim;
- });
- return victim;
- }
- public static void Send()
- {
- if(request.Count == 0)
- {
- return;
- }
- var send = request.Dequeue();
- Queue<Entry> _history;
- if(!history.TryGetValue(send.userid, out _history) || (_history.Count == 0))
- {
- Chat.Reply(send.actor, Key.CommandLogNoEntries, new Dictionary<string, string>
- {
- { "playerid", send.userid.ToString() },
- { "playername", Text.Sanitize(User.Name(send.userid)) }
- });
- return;
- }
- if(send.actor.LastCommand == CommandType.Chat)
- {
- Chat.Reply(send.actor, Key.CommandLogSeeConsole);
- send.actor.LastCommand = CommandType.Console;
- }
- Chat.Reply(send.actor, Key.CommandLogHeading, new Dictionary<string, string>
- {
- { "playerid", send.userid.ToString() },
- { "playername", Text.Sanitize(User.Name(send.userid)) }
- });
- var skip = (_history.Count > send.lines) ? (_history.Count - send.lines) : 0;
- foreach(var entry in _history)
- {
- if(skip > 0)
- {
- --skip; continue;
- }
- Chat.Reply(send.actor, Key.CommandLogLine, new Dictionary<string, string>
- {
- { "info", entry.Format(config.Log.Projectile.Collapse, false, true) }
- });
- }
- }
- public static void SetAim(ulong userid, int id, float aim_angle, float aim_pvp, float aim_range, bool pvp, bool ricochet)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.aim_angle = aim_angle;
- entry.aim_pvp = aim_pvp;
- entry.aim_range = aim_range;
- entry.pvp = pvp;
- entry.ricochet = ricochet;
- });
- }
- public static void SetAimViolations(ulong userid, int id, ulong aim_violations, bool add = false)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.aim_violations = add ? (aim_violations += aim_violations) : aim_violations;
- entry.violations = entry.violations || (entry.aim_violations > 0);
- });
- }
- public static void SetAttacker(ulong userid, int id, string attacker, ulong attaker_id)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.attacker = attacker;
- entry.attacker_id = attaker_id;
- });
- }
- public static void SetFireRateViolations(ulong userid, int id, ulong firerate_violations)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.violations = entry.violations || ((entry.firerate_violations = firerate_violations) > 0);
- });
- }
- public static void SetHit(ulong userid, int id, float hit_distance, HitArea hit_location)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.hit_distance = hit_distance;
- entry.hit_location = hit_location;
- });
- }
- public static void SetRecoil(ulong userid, int id, float recoil_pitch, ulong recoil_repeats, float recoil_yaw, float recoil_swing)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.recoil_pitch = recoil_pitch;
- entry.recoil_repeats = recoil_repeats;
- entry.recoil_swing = recoil_swing;
- entry.recoil_yaw = recoil_yaw;
- });
- }
- public static void SetRecoilViolations(ulong userid, int id, ulong recoil_violations)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.violations = entry.violations || ((entry.recoil_violations = recoil_violations) > 0);
- });
- }
- public static void SetTrajectory(ulong userid, int id, float trajectory)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.trajectory = trajectory;
- });
- }
- public static void SetTrajectoryViolations(ulong userid, int id, ulong trajectory_violations)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.violations = entry.violations || ((entry.trajectory_violations = trajectory_violations) > 0);
- });
- }
- public static void SetVictim(ulong userid, int id, string victim)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.victim = victim;
- });
- }
- public static void SetWallHackViolations(ulong userid, int id, ulong wallhack_violations)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.violations = entry.violations || ((entry.wallhack_violations = wallhack_violations) > 0);
- });
- }
- public static void SetWeapon(ulong userid, int id, float speed, string weapon)
- {
- TrySetEntry(userid, id, entry =>
- {
- entry.speed = speed;
- entry.weapon = weapon;
- });
- }
- private static void TrySetEntry(ulong userid, int id, Action<Entry> set)
- {
- Dictionary<int, Entry> _pending;
- if(pending.TryGetValue(userid, out _pending))
- {
- Entry entry;
- if(_pending.TryGetValue(id, out entry))
- {
- set(entry);
- }
- }
- }
- public static void Unload()
- {
- buffer.Clear();
- expired.Clear();
- history.Clear();
- pending.Clear();
- request.Clear();
- reserve.Clear();
- Entry.Unload();
- }
- }
- private static readonly List<Weapon> expired = new List<Weapon>();
- private static readonly Dictionary<ulong, Dictionary<int, Weapon>> reverse = new Dictionary<ulong, Dictionary<int, Weapon>>();
- private static readonly Dictionary<ulong, Queue<Weapon>> weapons = new Dictionary<ulong, Queue<Weapon>>();
- public static void Add(Weapon weapon)
- {
- Queue<Weapon> _weapons;
- if(!weapons.TryGetValue(weapon.Player.userID, out _weapons))
- {
- weapons.Add(weapon.Player.userID, _weapons = new Queue<Weapon>());
- }
- _weapons.Enqueue(weapon);
- Dictionary<int, Weapon> _reverse;
- if(!reverse.TryGetValue(weapon.Player.userID, out _reverse))
- {
- reverse.Add(weapon.Player.userID, _reverse = new Dictionary<int, Weapon>());
- }
- foreach(var projectileid in weapon.Projectiles)
- {
- _reverse[projectileid] = weapon;
- }
- Log.Add(weapon);
- }
- public static void Load()
- {
- Timers.Add(0.1f, () =>
- {
- var time = DateTime.UtcNow;
- foreach(var user in weapons)
- {
- var _weapons = user.Value;
- while(_weapons.Count > 0)
- {
- if(time.Subtract(_weapons.Peek().Fired).TotalSeconds > 9.0)
- {
- expired.Add(_weapons.Dequeue());
- }
- else
- {
- break;
- }
- }
- }
- expired.Sort((x, y) => DateTime.Compare(x.Fired, y.Fired));
- foreach(var weapon in expired)
- {
- AntiCheat.Aim.Update(weapon);
- Dictionary<int, Weapon> _reverse;
- if(reverse.TryGetValue(weapon.Player.userID, out _reverse))
- {
- foreach(var projectileid in weapon.Projectiles)
- {
- _reverse.Remove(projectileid);
- }
- Log.Expire(weapon);
- weapon.Release();
- }
- }
- expired.Clear();
- Log.Send();
- });
- }
- public static void Unload()
- {
- expired.Clear();
- reverse.Clear();
- weapons.Clear();
- Log.Unload();
- }
- public static Weapon Weapon(ulong userid, int projectileid)
- {
- Dictionary<int, Weapon> _reverse;
- if(reverse.TryGetValue(userid, out _reverse))
- {
- Weapon weapon;
- if(_reverse.TryGetValue(projectileid, out weapon))
- {
- return weapon;
- }
- }
- return null;
- }
- }
- #endregion _projectile_
- #region _sparse_map_
- private class SparseMap
- {
- private Dictionary<Texel, Cell> map;
- private float map_scale;
- private struct Cell
- {
- private ulong pixels;
- public bool IsEmpty() =>
- pixels == 0;
- private static ulong Mask(Delta delta) =>
- 1ul << (((delta.Y + 4) << 3) + delta.X + 4);
- public Cell Reset(Delta delta) =>
- new Cell { pixels = pixels & ~Mask(delta) };
- public Cell Set(Delta delta) =>
- new Cell { pixels = pixels | Mask(delta) };
- public bool Test(Delta delta) =>
- (pixels & Mask(delta)) != 0;
- }
- private struct Delta
- {
- public int X { get; private set; }
- public int Y { get; private set; }
- public Delta(Texel texel, Pixel pixel)
- {
- X = pixel.X - texel.X;
- Y = pixel.Y - texel.Y;
- }
- }
- private struct Pixel
- {
- public int X { get; private set; }
- public int Y { get; private set; }
- public Pixel(int x, int y)
- {
- X = x;
- Y = y;
- }
- public Pixel(Vector3 position, SparseMap map)
- {
- X = map.Scale(position.x);
- Y = map.Scale(position.z);
- }
- }
- private struct Texel
- {
- public int X { get; private set; }
- public int Y { get; private set; }
- public Texel(Pixel pixel)
- {
- X = pixel.X & ~7;
- Y = pixel.Y & ~7;
- }
- public override bool Equals(object o) =>
- (o is Texel) ? (this == (Texel)o) : false;
- public static bool operator ==(Texel a, Texel b) =>
- (a.X == b.X) && (a.Y == b.Y);
- public static bool operator !=(Texel a, Texel b) =>
- (a.X != b.X) || (a.Y != b.Y);
- public override int GetHashCode() =>
- (((X * 1664525 + 1013904223) & 0x3fffffff) >> 3) ^ ((Y * 1103515245 + 12345) << 2);
- }
- public SparseMap(float scale)
- {
- map = new Dictionary<Texel, Cell>();
- SetScale(scale);
- }
- public void Clear() => map.Clear();
- public int Count() => map.Count;
- public void Reset(float scale = 0.0f)
- {
- Clear();
- if(scale != 0.0f)
- {
- SetScale(scale);
- }
- }
- private void Reset(Pixel pixel)
- {
- var texel = new Texel(pixel);
- Cell value;
- if(!map.TryGetValue(texel, out value))
- {
- return;
- }
- value = value.Reset(new Delta(texel, pixel));
- if(value.IsEmpty())
- {
- map.Remove(texel);
- }
- else
- {
- map[texel] = value;
- }
- }
- public void Reset(Vector3 position) =>
- Reset(new Pixel(position, this));
- public float Scale() => map_scale;
- private int Scale(float n) =>
- (int)(n * map_scale);
- private void Set(Pixel pixel)
- {
- var texel = new Texel(pixel);
- Cell value;
- if(!map.TryGetValue(texel, out value))
- {
- value = new Cell();
- }
- map[texel] = value.Set(new Delta(texel, pixel));
- }
- public void Set(Vector3 position) =>
- Set(new Pixel(position, this));
- public int Set(Vector3 origin, float range)
- {
- var pixels = 0;
- var center = new Pixel(origin, this);
- var r = Scale(range);
- if(r < 0)
- {
- return pixels;
- }
- var r_squared = r * r;
- if(r_squared == 0)
- {
- if(range >= 0.25f)
- {
- Set(center); ++pixels;
- }
- return pixels;
- }
- for(int delta_x = -r; delta_x < r; ++delta_x)
- {
- int delta_y = (int)Math.Sqrt(r_squared - delta_x * delta_x);
- int x = center.X + delta_x, limit_y = center.Y + delta_y;
- for(int y = center.Y - delta_y; y < limit_y; ++y)
- {
- Set(new Pixel(x, y)); ++pixels;
- }
- }
- return pixels;
- }
- private void SetScale(float scale)
- {
- scale = Math.Abs(scale);
- scale = (scale < 0.125f) ? 0.125f : scale;
- map_scale = 1.0f / scale;
- }
- private bool Test(Pixel pixel)
- {
- var texel = new Texel(pixel);
- Cell value;
- if(map.TryGetValue(texel, out value))
- {
- return value.Test(new Delta(texel, pixel));
- }
- return false;
- }
- public bool Test(Vector3 position) =>
- Test(new Pixel(position, this));
- }
- #endregion _sparse_map_
- #region _steam_
- private class Steam
- {
- public class Settings
- {
- public API.Settings API;
- public SteamBan Ban;
- public SteamGame Game;
- public SteamProfile Profile;
- public SteamShare Share;
- public SteamViolation Violation;
- public Settings()
- {
- API = new API.Settings();
- Ban = new SteamBan();
- Game = new SteamGame();
- Profile = new SteamProfile();
- Share = new SteamShare();
- Violation = new SteamViolation();
- }
- public class SteamBan
- {
- public bool Active;
- public bool Community;
- public ulong Days;
- public bool Economy;
- public ulong Game;
- public ulong VAC;
- }
- public class SteamGame
- {
- public ulong Count;
- public ulong Hours;
- }
- public class SteamProfile
- {
- public bool Invalid;
- public bool Limited;
- public bool Private;
- }
- public class SteamShare
- {
- public bool Family;
- }
- public class SteamViolation
- {
- public bool Ban;
- public bool Enabled;
- public bool Warn;
- public SteamViolation()
- {
- Ban = false;
- Enabled = true;
- Warn = false;
- }
- }
- public void Validate()
- {
- Configuration.Validate(ref API, () => new API.Settings(), () => API.Validate());
- Configuration.Validate(ref Ban, () => new SteamBan());
- Configuration.Validate(ref Game, () => new SteamGame());
- Configuration.Validate(ref Profile, () => new SteamProfile());
- Configuration.Validate(ref Share, () => new SteamShare());
- Configuration.Validate(ref Violation, () => new SteamViolation());
- }
- }
- private static uint appid;
- private static ActionQueue checks;
- private static readonly Violation violation = new Violation(Key.Steam);
- public static void Check(ulong userid)
- {
- if(!config.Steam.API.Enabled || Permissions.Bypass.Steam(userid))
- {
- return;
- }
- if(string.IsNullOrEmpty(config.Steam.API.ApiKey))
- {
- Log.Console(Key.LogSteamConfig, new Dictionary<string, string>
- {
- { "api", "API" },
- { "link", $"https://steamcommunity.com/dev/apikey" }
- });
- return;
- }
- if(Ban.check)
- {
- checks.Enqueue(() => Ban.Check(userid));
- }
- }
- public static void Configure()
- {
- violation.Configure(new Violation.Settings(true, 3600, 0.5f, config.Steam.Violation.Warn), 1, 1, 1);
- Game.check = Share.check = Profile.check = Summaries.check = Ban.check = false;
- if(config.Steam.API.Enabled)
- {
- Game.check =
- config.Steam.Game.Count > 0 ||
- config.Steam.Game.Hours > 0;
- Share.check =
- Game.check ||
- config.Steam.Share.Family;
- Profile.check =
- Share.check ||
- config.Steam.Profile.Invalid ||
- config.Steam.Profile.Limited;
- Summaries.check =
- Profile.check ||
- config.Steam.Profile.Private;
- Ban.check =
- Summaries.check ||
- config.Steam.Ban.Active ||
- config.Steam.Ban.Community ||
- config.Steam.Ban.Days > 0 ||
- config.Steam.Ban.Economy ||
- config.Steam.Ban.Game > 0 ||
- config.Steam.Ban.VAC > 0;
- }
- }
- public static void Load()
- {
- appid = _instance.covalence.ClientAppId;
- Configure();
- checks = new ActionQueue(1.0f);
- }
- public static void Unload()
- {
- checks.Clear();
- checks = null;
- violation.Clear();
- }
- private static void Violation(ulong userid, Key type, string details, bool ban = false)
- {
- if(config.Steam.Violation.Enabled)
- {
- ulong violations = (config.Steam.Violation.Ban || ban) ? ulong.MaxValue : 1ul;
- violation.Trigger(userid, type, details, violations, true);
- }
- else
- {
- if(User.IsConnected(userid))
- {
- User.Kick(userid, $"Steam: {type}");
- }
- }
- }
- private class Ban
- {
- [JsonProperty("players")]
- public Player[] Players;
- public class Player
- {
- [JsonProperty("CommunityBanned")]
- public bool CommunityBanned;
- [JsonProperty("VACBanned")]
- public bool VacBanned;
- [JsonProperty("NumberOfVACBans")]
- public ulong NumberOfVacBans;
- [JsonProperty("DaysSinceLastBan")]
- public ulong DaysSinceLastBan;
- [JsonProperty("NumberOfGameBans")]
- public ulong NumberOfGameBans;
- [JsonProperty("EconomyBan")]
- public string EconomyBan;
- }
- [JsonIgnore]
- private static readonly string api = nameof(Ban);
- [JsonIgnore]
- public static bool check = false;
- public static void Check(ulong userid)
- {
- var url = $"https://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key={config.Steam.API.ApiKey}&steamids={userid}";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<Ban>(reply).Players[0];
- var has_bans = (response.NumberOfGameBans + response.NumberOfVacBans) > 0;
- if(config.Steam.Ban.Active && response.VacBanned)
- {
- Violation(userid, Key.SteamBanActive, $"{true}");
- }
- else if(config.Steam.Ban.Community && response.CommunityBanned)
- {
- Violation(userid, Key.SteamBanCommunity, $"{true}");
- }
- else if((config.Steam.Ban.Days > 0) && (config.Steam.Ban.Days > response.DaysSinceLastBan) && has_bans)
- {
- Violation(userid, Key.SteamBanDays, $"{response.DaysSinceLastBan}");
- }
- else if(config.Steam.Ban.Economy && (response.EconomyBan == "banned"))
- {
- Violation(userid, Key.SteamBanEconomy, $"{true}");
- }
- else if((config.Steam.Ban.Game > 0) && (config.Steam.Ban.Game <= response.NumberOfGameBans))
- {
- Violation(userid, Key.SteamBanGame, $"{response.NumberOfGameBans}", true);
- }
- else if((config.Steam.Ban.VAC > 0) && (config.Steam.Ban.VAC <= response.NumberOfVacBans))
- {
- Violation(userid, Key.SteamBanVAC, $"{response.NumberOfVacBans}", true);
- }
- else if(Summaries.check)
- {
- Summaries.Check(userid);
- }
- }
- catch
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", reply },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- private class Game
- {
- [JsonProperty("response")]
- public Content Response;
- public class Content
- {
- [JsonProperty("game_count")]
- public ulong GameCount;
- [JsonProperty("games")]
- public Game[] Games;
- public class Game
- {
- [JsonProperty("appid")]
- public uint AppId;
- [JsonProperty("playtime_forever")]
- public ulong PlaytimeForever;
- }
- }
- [JsonIgnore]
- private static readonly string api = nameof(Game);
- [JsonIgnore]
- public static bool check = false;
- public static void Check(ulong userid, bool private_profile, bool is_sharing)
- {
- if(private_profile || is_sharing)
- {
- if(config.Steam.Game.Count > 0)
- {
- Violation(userid, Key.SteamGameCount, "(null)");
- }
- else if(config.Steam.Game.Hours > 0)
- {
- Violation(userid, Key.SteamGameHours, "(null)");
- }
- return;
- }
- var url = $"https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key={config.Steam.API.ApiKey}&steamid={userid}";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<Game>(reply).Response;
- if((config.Steam.Game.Count > 0) && (config.Steam.Game.Count > response.GameCount))
- {
- Violation(userid, Key.SteamGameCount, $"{response.GameCount}");
- }
- else if(config.Steam.Game.Hours > 0)
- {
- foreach(var game in response.Games)
- {
- if(game.AppId == appid)
- {
- var hours_played = game.PlaytimeForever / 60ul;
- if(config.Steam.Game.Hours > hours_played)
- {
- Violation(userid, Key.SteamGameHours, $"{hours_played}");
- break;
- }
- }
- }
- }
- }
- catch
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", reply },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- private class Profile
- {
- private static readonly string api = nameof(Profile);
- public static bool check = false;
- public static void Check(ulong userid, bool private_profile)
- {
- var url = $"https://steamcommunity.com/profiles/{userid}/?xml=1";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "HTTP" }
- });
- return;
- }
- var response = reply.ToLower();
- var has_profile = !response.Contains("this user has not yet set up their steam community profile");
- if(config.Steam.Profile.Invalid && !has_profile)
- {
- Violation(userid, Key.SteamProfileInvalid, $"{true}");
- }
- else if(config.Steam.Profile.Limited && has_profile && response.Contains("<islimitedaccount>1</islimitedaccount>"))
- {
- Violation(userid, Key.SteamProfileLimited, $"{true}");
- }
- else if(Share.check)
- {
- Share.Check(userid, private_profile);
- }
- }, _instance);
- }
- }
- private class Share
- {
- [JsonProperty("response")]
- public Content Response;
- public class Content
- {
- [JsonProperty("lender_steamid")]
- public ulong LenderSteamId;
- }
- [JsonIgnore]
- private static readonly string api = nameof(Share);
- [JsonIgnore]
- public static bool check = false;
- public static void Check(ulong userid, bool private_profile)
- {
- var url = $"https://api.steampowered.com/IPlayerService/IsPlayingSharedGame/v0001/?key={config.Steam.API.ApiKey}&steamid={userid}&appid_playing={appid}";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<Share>(reply).Response;
- var is_sharing = (response.LenderSteamId > 0);
- if(config.Steam.Share.Family && is_sharing)
- {
- Violation(userid, Key.SteamShareFamily, $"{true}");
- }
- else if(Game.check)
- {
- Game.Check(userid, private_profile, is_sharing);
- }
- }
- catch
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", reply },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- private class Summaries
- {
- [JsonProperty("response")]
- public Content Response;
- public class Content
- {
- [JsonProperty("players")]
- public Player[] Players;
- public class Player
- {
- [JsonProperty("communityvisibilitystate")]
- public int CommunityVisibilityState;
- }
- }
- [JsonIgnore]
- private static readonly string api = nameof(Summaries);
- [JsonIgnore]
- public static bool check = false;
- public static void Check(ulong userid)
- {
- var url = $"https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={config.Steam.API.ApiKey}&steamids={userid}";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<Summaries>(reply).Response.Players[0];
- var private_profile = (response.CommunityVisibilityState < 3);
- if(config.Steam.Profile.Private && private_profile)
- {
- Violation(userid, Key.SteamProfilePrivate, $"{true}");
- }
- else if(Profile.check)
- {
- Profile.Check(userid, private_profile);
- }
- }
- catch
- {
- Log.Console(Key.LogSteam, new Dictionary<string, string>
- {
- { "api", api },
- { "info", reply },
- { "playerid", userid.ToString() },
- { "playername", Text.Sanitize(User.Name(userid)) },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- }
- #endregion _steam_
- #region _text_
- private enum Key
- {
- add,
- Added,
- Address,
- ago,
- Allowed,
- AllUsers,
- and,
- AntiCheat,
- AntiCheatAim,
- AntiCheatFireRate,
- AntiCheatGravity,
- AntiCheatMeleeRate,
- AntiCheatRecoil,
- AntiCheatStash,
- AntiCheatTrajectory,
- AntiCheatWallHack,
- AntiFlood,
- AntiFloodChat,
- AntiFloodCommand,
- AntiFloodItemDrop,
- BanCount,
- BanInherited,
- Banned,
- banned,
- BanReason,
- BanReset,
- Blocked,
- BodyPart,
- BodyPartArm,
- BodyPartChest,
- BodyPartFoot,
- BodyPartHand,
- BodyPartHead,
- BodyPartLeg,
- BodyPartStomach,
- Bypassed,
- Changed,
- Chat,
- Command,
- CommandConfig,
- CommandConfigAdminSyntax,
- CommandConfigAntiCheatAimSyntax,
- CommandConfigAntiCheatFireRateSyntax,
- CommandConfigAntiCheatGravitySyntax,
- CommandConfigAntiCheatMeleeRateSyntax,
- CommandConfigAntiCheatRecoilSyntax,
- CommandConfigAntiCheatServerSyntax,
- CommandConfigAntiCheatStashSyntax,
- CommandConfigAntiCheatSyntax,
- CommandConfigAntiCheatTrajectorySyntax,
- CommandConfigAntiCheatWallHackSyntax,
- CommandConfigAntiFloodChatSyntax,
- CommandConfigAntiFloodCommandSyntax,
- CommandConfigAntiFloodItemDropSyntax,
- CommandConfigAntiFloodSyntax,
- CommandConfigBanSyntax,
- CommandConfigCrippleSyntax,
- CommandConfigDiscordSyntax,
- CommandConfigEntitySyntax,
- CommandConfigIpSyntax,
- CommandConfigLogSyntax,
- CommandConfigSaveSyntax,
- CommandConfigSteamSyntax,
- CommandConfigSyntax,
- CommandConfigTitle,
- CommandConfigUserSyntax,
- CommandConfigViolationSyntax,
- CommandConfigVpnSyntax,
- CommandHelp,
- CommandHelpEntry,
- CommandHelpTitle,
- CommandIp,
- CommandIpEntry,
- CommandIpEntryFailed,
- CommandIpList,
- CommandIpSyntax,
- CommandIpTitle,
- CommandLogHeading,
- CommandLogLine,
- CommandLogNoEntries,
- CommandLogSeeConsole,
- CommandLogSyntax,
- CommandLogTitle,
- CommandNoPermission,
- CommandServerSyntax,
- CommandServerTitle,
- CommandTeleport,
- CommandTeleportSyntax,
- CommandTeleportTitle,
- CommandTeleportViolation,
- CommandUnknown,
- CommandUser,
- CommandUserAction,
- CommandUserInfo,
- CommandUserKick,
- CommandUserNotFound,
- CommandUserSyntax,
- CommandUserTeam,
- CommandUserTitle,
- CommandUserTooMany,
- CommandVpn,
- CommandVpnSyntax,
- CommandVpnTitle,
- connected,
- CONSOLE,
- Cooldown,
- Crafting,
- CrippleCount,
- Crippled,
- crippled,
- CrippleReason,
- CrippleReset,
- Current,
- data,
- Denied,
- Detected,
- DurationDay,
- DurationDays,
- DurationHour,
- DurationHours,
- DurationMinute,
- DurationMinutes,
- DurationSecond,
- DurationSeconds,
- DurationSecondsUnit,
- empty,
- Entity,
- EntityAnimal,
- EntityAutoTurret,
- EntityBear,
- EntityBoar,
- EntityBradley,
- EntityBuilding,
- EntityChicken,
- EntityFlameTurret,
- EntityGunTrap,
- EntityHelicopter,
- EntityMurderer,
- EntityNPC,
- EntityPlayer,
- EntitySAMSite,
- EntityScientist,
- EntityStag,
- EntityTC,
- EntityTrap,
- file,
- For,
- idle,
- InvalidSteamId,
- IP,
- IpBlocked,
- IpCooldown,
- Kicked,
- LogAntiCheatAim,
- LogAntiCheatGravity,
- LogAntiCheatMeleeRate,
- LogAntiCheatRecoil,
- LogAntiCheatServer,
- LogAntiCheatStash,
- LogAntiCheatTrajectory,
- LogAntiSpamItemDrop,
- LogConnect,
- LogDiscordConfig,
- LogDiscordMessage,
- LogIpFilter,
- LogSteam,
- LogSteamConfig,
- LogUserBypass,
- LogVpnCheck,
- LogVpnCheckConfig,
- LogVpnCheckError,
- LogWebHook,
- Name,
- never,
- NoReasonGiven,
- NULL,
- offline,
- OnAntiCheatTriggered,
- online,
- OxideGroups,
- Pardoned,
- permanently,
- Played,
- remove,
- Removed,
- Saved,
- Server,
- SERVER,
- Status,
- Steam,
- SteamBanActive,
- SteamBanCommunity,
- SteamBanDays,
- SteamBanEconomy,
- SteamBanGame,
- SteamBanVAC,
- SteamGameCount,
- SteamGameHours,
- SteamID,
- SteamProfileInvalid,
- SteamProfileLimited,
- SteamProfilePrivate,
- SteamShareFamily,
- True,
- Unbanned,
- Unblocked,
- Uncrippled,
- unknown,
- UnknownKey,
- UserAction,
- UserBanTeleport,
- UserBanTeleported,
- UserConnectBanInherit,
- UserConnectIpBlocked,
- UserConnectSteamIdInvalid,
- UserInfoText,
- UserInfoTextBullet,
- UserInfoTextLabel,
- UserPardonProgress,
- Violation,
- ViolationAim,
- ViolationFireRate,
- ViolationGravity,
- ViolationMeleeRate,
- ViolationRecoil,
- ViolationStash,
- ViolationTrajectory,
- ViolationWallHack,
- VPN,
- VpnCache,
- VpnDetected,
- Warning
- }
- private class Text
- {
- private static readonly Dictionary<string, Dictionary<Key, string>> decorated = new Dictionary<string, Dictionary<Key, string>>();
- private static readonly Dictionary<string, Dictionary<Key, string>> unadorned = new Dictionary<string, Dictionary<Key, string>>();
- private static string server_language;
- private class RegEx
- {
- public static Regex clean1;
- public static Regex clean2;
- public static Regex clean3;
- public static Regex markup;
- public static Regex spaces;
- public static void Load()
- {
- clean1 = new Regex(@"\p{Cc}+|\p{Cs}+", RegexOptions.Compiled);
- clean2 = new Regex(@"\{+|\}+", RegexOptions.Compiled);
- markup = new Regex(@"<[^>]+>", RegexOptions.Compiled);
- spaces = new Regex(@"\s{2,}", RegexOptions.Compiled);
- }
- public static void Unload()
- {
- clean1 = clean2 = clean3 = markup = spaces = null;
- }
- }
- public static string Actor(IPlayer actor) =>
- Actor(actor, server_language);
- public static string Actor(IPlayer actor, BasePlayer player) =>
- Actor(actor, Language(player.UserIDString));
- public static string Actor(IPlayer actor, IPlayer iplayer) =>
- Actor(actor, iplayer.IsServer ? server_language : Language(iplayer.Id));
- public static string Actor(IPlayer actor, ulong userid) =>
- Actor(actor, Language(userid.ToString()));
- public static string Actor(IPlayer actor, string language)
- {
- if(actor == null)
- {
- return GetPlain(Key.SERVER, language);
- }
- else if(actor.IsServer)
- {
- return GetPlain(Key.CONSOLE, language);
- }
- else
- {
- return Sanitize(actor.Name);
- }
- }
- public static string BodyPart(HitArea area) =>
- BodyPart(area, server_language);
- public static string BodyPart(HitArea area, BasePlayer player) =>
- BodyPart(area, Language(player.UserIDString));
- public static string BodyPart(HitArea area, IPlayer iplayer) =>
- BodyPart(area, iplayer.IsServer ? server_language : Language(iplayer.Id));
- public static string BodyPart(HitArea area, ulong userid) =>
- BodyPart(area, Language(userid.ToString()));
- public static string BodyPart(HitArea area, string language)
- {
- switch(area)
- {
- case HitArea.Head: return GetPlain(Key.BodyPartHead);
- case HitArea.Chest: return GetPlain(Key.BodyPartChest);
- case HitArea.Stomach: return GetPlain(Key.BodyPartStomach);
- case HitArea.Arm: return GetPlain(Key.BodyPartArm);
- case HitArea.Hand: return GetPlain(Key.BodyPartHand);
- case HitArea.Leg: return GetPlain(Key.BodyPartLeg);
- case HitArea.Foot: return GetPlain(Key.BodyPartFoot);
- }
- return GetPlain(Key.BodyPart, language);
- }
- public class Duration
- {
- public static string Hours(TimeSpan time) =>
- Hours(time, server_language);
- public static string Hours(TimeSpan time, BasePlayer player) =>
- Hours(time, Language(player.UserIDString));
- public static string Hours(TimeSpan time, IPlayer iplayer) =>
- Hours(time, iplayer.IsServer ? server_language : Language(iplayer.Id));
- public static string Hours(TimeSpan time, ulong userid) =>
- Hours(time, Language(userid.ToString()));
- public static string Hours(TimeSpan time, string language) =>
- $"{time.Duration().TotalHours:0.00} {GetPlain(Key.DurationHours, language)}";
- public static string Short(TimeSpan time) =>
- Short(time, server_language);
- public static string Short(TimeSpan time, BasePlayer player) =>
- Short(time, Language(player.UserIDString));
- public static string Short(TimeSpan time, IPlayer iplayer) =>
- Short(time, iplayer.IsServer ? server_language : Language(iplayer.Id));
- public static string Short(TimeSpan time, ulong userid) =>
- Short(time, Language(userid.ToString()));
- public static string Short(TimeSpan time, string language)
- {
- var duration = time.Duration();
- if(duration.Days != 0)
- {
- return $"{duration.TotalDays:0.00} {GetPlain(Key.DurationDays, language)}";
- }
- else if(duration.Hours != 0)
- {
- return $"{duration.TotalHours:0.00} {GetPlain(Key.DurationHours, language)}";
- }
- else if(duration.Minutes != 0)
- {
- return $"{duration.TotalMinutes:0.00} {GetPlain(Key.DurationMinutes, language)}";
- }
- else
- {
- return $"{duration.TotalSeconds:0.00} {GetPlain(Key.DurationSeconds, language)}";
- }
- }
- }
- public static string Get(Key key, Dictionary<string, string> parameters = null) =>
- Get(key, server_language, parameters);
- public static string Get(Key key, BasePlayer player, Dictionary<string, string> parameters = null) =>
- Get(key, Language(player.UserIDString), parameters);
- public static string Get(Key key, IPlayer iplayer, Dictionary<string, string> parameters = null)
- {
- if(iplayer.LastCommand == CommandType.Console)
- {
- return GetPlain(key, iplayer.IsServer ? server_language : Language(iplayer.Id), parameters);
- }
- else
- {
- return Get(key, iplayer.IsServer ? server_language : Language(iplayer.Id), parameters);
- }
- }
- public static string Get(Key key, ulong userid, Dictionary<string, string> parameters = null) =>
- Get(key, Language(userid.ToString()), parameters);
- public static string Get(Key key, string language, Dictionary<string, string> parameters = null) =>
- Get(key, Messages(decorated, language), parameters);
- private static string Get(Key key, Dictionary<Key, string> cache, Dictionary<string, string> parameters)
- {
- string message = null;
- if(cache?.TryGetValue(key, out message) ?? false)
- {
- return Replace(message, parameters);
- }
- return Enum.GetName(typeof(Key), key);
- }
- public static string GetPlain(Key key, Dictionary<string, string> parameters = null) =>
- GetPlain(key, server_language, parameters);
- public static string GetPlain(Key key, BasePlayer player, Dictionary<string, string> parameters = null) =>
- GetPlain(key, Language(player.UserIDString), parameters);
- public static string GetPlain(Key key, IPlayer iplayer, Dictionary<string, string> parameters = null) =>
- GetPlain(key, iplayer.IsServer ? server_language : Language(iplayer.Id), parameters);
- public static string GetPlain(Key key, ulong userid, Dictionary<string, string> parameters = null) =>
- GetPlain(key, Language(userid.ToString()), parameters);
- public static string GetPlain(Key key, string language, Dictionary<string, string> parameters = null) =>
- Get(key, Messages(unadorned, language), parameters);
- public static string Language(string userid = null)
- {
- if(string.IsNullOrEmpty(userid))
- {
- return server_language;
- }
- var language = _instance.lang.GetLanguage(userid) ?? server_language;
- return decorated.ContainsKey(language) ? language : server_language;
- }
- public static void Load()
- {
- var languages = _instance.lang.GetLanguages(_instance);
- if((languages.Length == 0) || Configuration.Upgraded())
- {
- RegisterMessages();
- languages = _instance.lang.GetLanguages(_instance);
- }
- var requested = _instance.lang.GetServerLanguage();
- if(!string.IsNullOrEmpty(requested) && languages.Contains(requested))
- {
- server_language = requested;
- }
- else
- {
- server_language = "en";
- }
- RegEx.Load();
- foreach(var language in languages)
- {
- var m_decorated = decorated[language] = new Dictionary<Key, string>();
- var m_unadorned = unadorned[language] = new Dictionary<Key, string>();
- foreach(var entry in _instance.lang.GetMessages(language, _instance))
- {
- if(string.IsNullOrEmpty(entry.Key))
- {
- continue;
- }
- Key key;
- if(Enum.TryParse(entry.Key, out key))
- {
- m_decorated.Add(key, entry.Value);
- m_unadorned.Add(key, Strip(entry.Value));
- }
- else
- {
- Log.Console(Key.UnknownKey, new Dictionary<string, string>
- {
- { "key", entry.Key },
- { "language", language }
- });
- }
- }
- }
- }
- private static Dictionary<Key, string> Messages(Dictionary<string, Dictionary<Key, string>> cache, string language)
- {
- Dictionary<Key, string> messages;
- if(!cache.TryGetValue(language, out messages))
- {
- if(!cache.TryGetValue(server_language, out messages))
- {
- return null;
- }
- }
- return messages;
- }
- public static bool ParseTime(string message, out ulong seconds)
- {
- seconds = 0;
- if(string.IsNullOrEmpty(message))
- {
- return false;
- }
- ulong amount = 0; char units = 's';
- for(int i = 0; i < message.Length; ++i)
- {
- var current = message[i];
- if(char.IsDigit(current))
- {
- amount *= 10;
- amount += (ulong)(current - '0');
- }
- else
- {
- if((i + 1) != message.Length)
- {
- return false;
- }
- units = char.ToLower(current);
- }
- }
- switch(units)
- {
- case 'd': seconds = amount * 86400ul; return true;
- case 'h': seconds = amount * 3600ul; return true;
- case 'm': seconds = amount * 60ul; return true;
- case 's': seconds = amount; return true;
- }
- return false;
- }
- private static void RegisterMessages()
- {
- _instance.lang.RegisterMessages(new Dictionary<string, string>(), _instance, "en");
- _instance.lang.RegisterMessages(new Dictionary<string, string>
- {
- { nameof(Key.add), "add" },
- { nameof(Key.Added), "Added" },
- { nameof(Key.Address), "Address" },
- { nameof(Key.ago), "ago" },
- { nameof(Key.Allowed), "Allowed" },
- { nameof(Key.AllUsers), "All Users" },
- { nameof(Key.and), "and" },
- { nameof(Key.AntiCheat), "AntiCheat" },
- { nameof(Key.AntiCheatAim), "Aim" },
- { nameof(Key.AntiCheatFireRate), "Fire Rate" },
- { nameof(Key.AntiCheatGravity), "Gravity" },
- { nameof(Key.AntiCheatMeleeRate), "Melee Rate" },
- { nameof(Key.AntiCheatRecoil), "Recoil" },
- { nameof(Key.AntiCheatStash), "Stash" },
- { nameof(Key.AntiCheatTrajectory), "Trajectory" },
- { nameof(Key.AntiCheatWallHack), "Wall Hack" },
- { nameof(Key.AntiFlood), "AntiFlood" },
- { nameof(Key.AntiFloodChat), "Chat" },
- { nameof(Key.AntiFloodCommand), "Command" },
- { nameof(Key.AntiFloodItemDrop), "Dropped Items" },
- { nameof(Key.BanCount), "Ban Count" },
- { nameof(Key.BanInherited), "Ban inherited" },
- { nameof(Key.Banned), "Banned" },
- { nameof(Key.banned), "banned" },
- { nameof(Key.BanReason), "Ban Reason" },
- { nameof(Key.BanReset), "Reset ban data for" },
- { nameof(Key.Blocked), "Blocked" },
- { nameof(Key.BodyPart), "Body" },
- { nameof(Key.BodyPartArm), "Arm" },
- { nameof(Key.BodyPartChest), "Chest" },
- { nameof(Key.BodyPartFoot), "Foot" },
- { nameof(Key.BodyPartHand), "Hand" },
- { nameof(Key.BodyPartHead), "Head" },
- { nameof(Key.BodyPartLeg), "Leg" },
- { nameof(Key.BodyPartStomach), "Stomach" },
- { nameof(Key.Bypassed), "Bypassed" },
- { nameof(Key.Changed), "Changed" },
- { nameof(Key.Chat), "Chat" },
- { nameof(Key.Command), "Command" },
- { nameof(Key.CommandConfig), "<size=12><color=#c0ffc0>{action} configuration: </color><color=#c0c0ff>{info}</color></size>" },
- { nameof(Key.CommandConfigAdminSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} admin.broadcast [true|false]\n {command} admin.bypass [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatAimSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.aim.ban [true|false]\n {command} anticheat.aim.cooldown [SECONDS]\n {command} anticheat.aim.enabled [true|false]\n {command} anticheat.aim.sensitivity [0.0-1.0]\n {command} anticheat.aim.trigger.animal [true|false]\n {command} anticheat.aim.trigger.bradley [true|false]\n {command} anticheat.aim.trigger.helicopter [true|false]\n {command} anticheat.aim.trigger.npc [true|false]\n {command} anticheat.aim.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatFireRateSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.firerate.ban [true|false]\n {command} anticheat.firerate.cooldown [SECONDS]\n {command} anticheat.firerate.enabled [true|false]\n {command} anticheat.firerate.sensitivity [0.0-1.0]\n {command} anticheat.firerate.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatGravitySyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.gravity.ban [true|false]\n {command} anticheat.gravity.cooldown [SECONDS]\n {command} anticheat.gravity.enabled [true|false]\n {command} anticheat.gravity.sensitivity [0.0-1.0]\n {command} anticheat.gravity.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatMeleeRateSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.meleerate.ban [true|false]\n {command} anticheat.meleerate.cooldown [SECONDS]\n {command} anticheat.meleerate.enabled [true|false]\n {command} anticheat.meleerate.sensitivity [0.0-1.0]\n {command} anticheat.meleerate.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatRecoilSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.recoil.ban [true|false]\n {command} anticheat.recoil.cooldown [SECONDS]\n {command} anticheat.recoil.enabled [true|false]\n {command} anticheat.recoil.sensitivity [0.0-1.0]\n {command} anticheat.recoil.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatServerSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.server.ban [true|false]\n {command} anticheat.server.cooldown [SECONDS]\n {command} anticheat.server.enabled [true|false]\n {command} anticheat.server.sensitivity [0.0-1.0]\n {command} anticheat.server.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatStashSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.stash.ban [true|false]\n {command} anticheat.stash.cooldown [SECONDS]\n {command} anticheat.stash.enabled [true|false]\n {command} anticheat.stash.sensitivity [0.0-1.0]\n {command} anticheat.stash.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatSyntax), "<size=12><color=#ffc0c0>Syntax:</color><color=#c0c0ff>\n {command} anticheat.aim\n {command} anticheat.firerate\n {command} anticheat.gravity\n {command} anticheat.meleerate\n {command} anticheat.recoil\n {command} anticheat.server\n {command} anticheat.stash\n {command} anticheat.trajetory\n {command} anticheat.wallhack</color></size>" },
- { nameof(Key.CommandConfigAntiCheatTrajectorySyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.trajectory.ban [true|false]\n {command} anticheat.trajectory.cooldown [SECONDS]\n {command} anticheat.trajectory.enabled [true|false]\n {command} anticheat.trajectory.sensitivity [0.0-1.0]\n {command} anticheat.trajectory.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiCheatWallHackSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} anticheat.wallhack.ban [true|false]\n {command} anticheat.wallhack.cooldown [SECONDS]\n {command} anticheat.wallhack.enabled [true|false]\n {command} anticheat.wallhack.sensitivity [0.0-1.0]\n {command} anticheat.wallhack.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiFloodChatSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} antiflood.chat.ban [true|false]\n {command} antiflood.chat.cooldown [SECONDS]\n {command} antiflood.chat.enabled [true|false]\n {command} antiflood.chat.sensitivity [0.0-1.0]\n {command} antiflood.chat.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiFloodCommandSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} antiflood.command.ban [true|false]\n {command} antiflood.command.cooldown [SECONDS]\n {command} antiflood.command.enabled [true|false]\n {command} antiflood.command.sensitivity [0.0-1.0]\n {command} antiflood.command.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiFloodItemDropSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} antiflood.itemdrop.ban [true|false]\n {command} antiflood.itemdrop.cooldown [SECONDS]\n {command} antiflood.itemdrop.enabled [true|false]\n {command} antiflood.itemdrop.sensitivity [0.0-1.0]\n {command} antiflood.itemdrop.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigAntiFloodSyntax), "<size=12><color=#ffc0c0>Syntax:</color><color=#c0c0ff>\n {command} antiflood.chat\n {command} antiflood.command\n {command} antiflood.itemdrop</color></size>" },
- { nameof(Key.CommandConfigBanSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} ban.inherit [true|false]\n {command} ban.teleport [true|false]\n {command} ban.time.enforce [true|false]\n {command} ban.time.multiply [true|false]\n {command} ban.time.seconds [AMOUNT[d|h|m|s]]</color></size>" },
- { nameof(Key.CommandConfigCrippleSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} cripple.heal [true|false]\n {command} cripple.inherit [true|false]</color></size>" },
- { nameof(Key.CommandConfigDiscordSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} discord.enabled [true|false]\n {command} discord.webhook [URL]\n {command} discord.filters.anticheat.enabled [true|false]\n {command} discord.filters.anticheat.webhook [URL]\n {command} discord.filters.antiflood.enabled [true|false]\n {command} discord.filters.antiflood.webhook [URL]\n {command} discord.filters.ip.enabled [true|false]\n {command} discord.filters.ip.webhook [URL]\n {command} discord.filters.steam.enabled [true|false]\n {command} discord.filters.steam.webhook [URL]\n {command} discord.filters.vpn.enabled [true|false]\n {command} discord.filters.vpn.webhook [URL]</color></size>" },
- { nameof(Key.CommandConfigEntitySyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} entity.damage.animal [0.0-100.0]\n {command} entity.damage.bradley [0.0-100.0]\n {command} entity.damage.building [0.0-100.0]\n {command} entity.damage.entity [0.0-100.0]\n {command} entity.damage.friend [0.0-100.0]\n {command} entity.damage.helicopter [0.0-100.0]\n {command} entity.damage.npc [0.0-100.0]\n {command} entity.damage.player [0.0-100.0]\n {command} entity.damage.team [0.0-100.0]\n {command} entity.damage.trap [0.0-100.0]</color></size>" },
- { nameof(Key.CommandConfigIpSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} ip.filter.cooldown [SECONDS]\n {command} ip.violation.ban [true|false]\n {command} ip.violation.enabled [true|false]</color></size>" },
- { nameof(Key.CommandConfigLogSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} log.anticheat.gravity [true|false]\n {command} log.anticheat.meleerate [true|false]\n {command} log.anticheat.projectile [true|false]\n {command} log.anticheat.server [true|false]\n {command} log.anticheat.stash [true|false]\n {command} log.antiflood.itemdrop [true|false]\n {command} log.ip.filter [true|false]\n {command} log.projectile.collapse [true|false]\n {command} log.projectile.verbose [true|false]\n {command} log.user.connect [true|false]\n {command} log.vpn.bypass [true|false]\n {command} log.vpn.check [true|false]</color></size>" },
- { nameof(Key.CommandConfigSaveSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} save</color></size>" },
- { nameof(Key.CommandConfigSteamSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} steam.api.apikey [\"API-KEY\"]\n {command} steam.api.enabled [true|false]\n {command} steam.ban.active [true|false]\n {command} steam.ban.community [true|false]\n {command} steam.ban.days [DAYS]\n {command} steam.ban.economy [true|false]\n {command} steam.ban.game [NUMBER]\n {command} steam.ban.vac [NUMBER]\n {command} steam.game.count [NUMBER]\n {command} steam.game.hours [HOURS]\n {command} steam.profile.invalid [true|false]\n {command} steam.profile.limited [true|false]\n {command} steam.profile.private [true|false]\n {command} steam.share.family [true|false]\n {command} steam.violation.ban [true|false]\n {command} steam.violation.enabled [true|false]\n {command} steam.violation.warn [true|false]</color></size>" },
- { nameof(Key.CommandConfigSyntax), "<size=12><color=#ffc0c0>Syntax:</color><color=#c0c0ff>\n {command} admin\n {command} anticheat\n {command} antiflood\n {command} ban\n {command} cripple\n {command} discord\n {command} entity\n {command} ip\n {command} log\n {command} save\n {command} steam\n {command} user\n {command} violation\n {command} vpn</color></size>" },
- { nameof(Key.CommandConfigTitle), "Configuration Settings" },
- { nameof(Key.CommandConfigUserSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} user.bypass.dayssincelastban [DAYS]\n {command} user.bypass.enabled [true|false]\n {command} user.bypass.multiply [true|false]\n {command} user.bypass.hoursplayed [HOURS]</color></size>" },
- { nameof(Key.CommandConfigViolationSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} violation.ban [true|false]\n {command} violation.cooldown [SECONDS]\n {command} violation.enabled [true|false]\n {command} violation.sensitivity [0.0-1.0]</size>" },
- { nameof(Key.CommandConfigVpnSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} vpn.api.getipintel.apikey [\"API-KEY\"]\n {command} vpn.api.getipintel.enabled [true|false]\n {command} vpn.api.ipapi.enabled [true|false]\n {command} vpn.api.iphub.apikey [\"API-KEY\"]\n {command} vpn.api.iphub.enabled [true|false]\n {command} vpn.api.ipqualityscore.apikey [\"API-KEY\"]\n {command} vpn.api.ipqualityscore.enabled [true|false]\n {command} vpn.cache.hours [HOURS]\n {command} vpn.check.enabled [true|false]\n {command} vpn.check.strict [true|false]\n {command} vpn.violation.ban [true|false]\n {command} vpn.violation.enabled [true|false]\n {command} vpn.violation.warn [true|false]</color></size>" },
- { nameof(Key.CommandHelp), "<size=12><color=#ffffc0>{name} v{version} - Help</color>{entries}</size>" },
- { nameof(Key.CommandHelpEntry), "<color=#c0ffc0>\n{title}:</color><color=#c0c0ff>{aliases}</color>" },
- { nameof(Key.CommandHelpTitle), "Help Information" },
- { nameof(Key.CommandIp), "<size=12><color=#c0ffc0>{action} IP: </color><color=#c0c0ff>{info}</color></size>" },
- { nameof(Key.CommandIpEntry), "<size=12><color=#c0ffc0>{action} IP entry: </color><color=#c0c0ff>{entry}</color></size>" },
- { nameof(Key.CommandIpEntryFailed), "<size=12><color=#ffc0c0>Failed to {action} IP entry: </color><color=#c0c0ff>{entry}</color></size>" },
- { nameof(Key.CommandIpList), "<size=12><color=#c0ffc0>{type} IP entries: </color><color=#c0c0ff>{addresses}</color></size>" },
- { nameof(Key.CommandIpSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} allow\n {command} allow IP[/BITS]\n {command} allow add IP[/BITS]\n {command} allow remove IP[/BITS]\n {command} block IP\n {command} bypass IP\n {command} deny\n {command} deny IP[/BITS]\n {command} deny add IP[/BITS]\n {command} deny remove IP[/BITS]\n {command} save\n {command} unblock IP</color></size>" },
- { nameof(Key.CommandIpTitle), "IP Filtering" },
- { nameof(Key.CommandLogHeading), "<size=12><color=#c0ffc0>Projectile Log for {playername}[{playerid}]:</color></size>" },
- { nameof(Key.CommandLogLine), "<size=12><color=#c0c0c0>{info}</color></size>" },
- { nameof(Key.CommandLogNoEntries), "<size=12><color=#ffffc0>No log data available for {playername}[{playerid}].</color></size>" },
- { nameof(Key.CommandLogSeeConsole), "<size=12><color=#c0ffc0>Check the console (F1) for results.</color></size>" },
- { nameof(Key.CommandLogSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} IP|NAME|STEAMID [LINES]</color></size>" },
- { nameof(Key.CommandLogTitle), "Projectile Log" },
- { nameof(Key.CommandNoPermission), "<color=#ffc0c0><size=12>You do not have permission to use this command.</size></color>" },
- { nameof(Key.CommandServerSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} pardon\n {command} unban\n {command} uncripple</color></size>" },
- { nameof(Key.CommandServerTitle), "Server Administration" },
- { nameof(Key.CommandTeleport), "<size=12><color=#c0ffc0>Last seen location: </color><color=#c0c0ff>{position}</color></size>" },
- { nameof(Key.CommandTeleportSyntax), "<size=12><color=#ffc0c0>Syntax:</color><color=#c0c0ff>\n {command} IP|NAME|STEAMID</color></size>" },
- { nameof(Key.CommandTeleportTitle), "Teleportation" },
- { nameof(Key.CommandTeleportViolation), "<size=12><color=#c0ffc0>Violation location: </color><color=#c0c0ff>{position}</color></size>" },
- { nameof(Key.CommandUnknown), "<size=12><color=#ffc0c0>Command unknown: </color><color=#c0c0ff>{command}</color></size>" },
- { nameof(Key.CommandUser), "<size=12><color=#c0ffc0>{action} {playername}[{playerid}] {duration}: </color><color=#c0c0ff>{reason}</color></size>" },
- { nameof(Key.CommandUserAction), "<size=12><color=#c0ffc0>{action} {playername}[{playerid}]</color></size>" },
- { nameof(Key.CommandUserInfo), "<size=12><color=#c0ffc0>User information:</color><color=#c0c0ff>{info}</color></size>" },
- { nameof(Key.CommandUserKick), "<size=12><color=#c0ffc0>{action} {playername}[{playerid}]: </color><color=#c0c0ff>{reason}</color></size>" },
- { nameof(Key.CommandUserNotFound), "<size=12><color=#ffc0c0>User not found.</color></size>" },
- { nameof(Key.CommandUserSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} IP|NAME|STEAMID [team]\n {command} IP|NAME|STEAMID [team.]ban [\"REASON\"] [TIME[d|h|m|s]]\n {command} IP|NAME|STEAMID [team.]ban.reset\n {command} IP|NAME|STEAMID [team.]cripple [\"REASON\"] [TIME[d|h|m|s]]\n {command} IP|NAME|STEAMID [team.]cripple.reset\n {command} IP|NAME|STEAMID [team.]kick [\"REASON\"]\n {command} IP|NAME|STEAMID [team.]pardon\n {command} IP|NAME|STEAMID [team.]unban\n {command} IP|NAME|STEAMID [team.]uncripple</color></size>" },
- { nameof(Key.CommandUserTeam), "<size=12><color=#c0ffc0>Team members:</color><color=#c0c0ff>{users}</color></size>" },
- { nameof(Key.CommandUserTitle), "User Administration" },
- { nameof(Key.CommandUserTooMany), "<size=12><color=#ffc0c0>Found multiple users:</color><color=#c0c0ff>{users}</color></size>" },
- { nameof(Key.CommandVpn), "<size=12><color=#c0ffc0>{action} VPN check: </color><color=#c0c0ff>{info}</color></size>" },
- { nameof(Key.CommandVpnSyntax), "<size=12><color=#ffc0c0>Syntax [optional]:</color><color=#c0c0ff>\n {command} bypass IP\n {command} status IP\n {command} unblock IP</color></size>" },
- { nameof(Key.CommandVpnTitle), "VPN Detection" },
- { nameof(Key.connected), "connected" },
- { nameof(Key.CONSOLE), "CONSOLE" },
- { nameof(Key.Cooldown), "<color=#ffc0c0><size=12>{type} cooldown: {cooldown}s</size></color>" },
- { nameof(Key.Crafting), "Crafting" },
- { nameof(Key.CrippleCount), "Cripple Count" },
- { nameof(Key.Crippled), "Crippled" },
- { nameof(Key.crippled), "crippled" },
- { nameof(Key.CrippleReason), "Cripple Reason" },
- { nameof(Key.CrippleReset), "Reset cripple data for" },
- { nameof(Key.Current), "Current" },
- { nameof(Key.data), "data" },
- { nameof(Key.Denied), "Denied" },
- { nameof(Key.Detected), "Detected" },
- { nameof(Key.DurationDay), "day" },
- { nameof(Key.DurationDays), "days" },
- { nameof(Key.DurationHour), "hour" },
- { nameof(Key.DurationHours), "hours" },
- { nameof(Key.DurationMinute), "minute" },
- { nameof(Key.DurationMinutes), "minutes" },
- { nameof(Key.DurationSecond), "second" },
- { nameof(Key.DurationSeconds), "seconds" },
- { nameof(Key.DurationSecondsUnit), "s" },
- { nameof(Key.empty), "empty" },
- { nameof(Key.Entity), "Entity" },
- { nameof(Key.EntityAnimal), "Animal" },
- { nameof(Key.EntityAutoTurret), "Auto Turret" },
- { nameof(Key.EntityBear), "Bear" },
- { nameof(Key.EntityBoar), "Boar" },
- { nameof(Key.EntityBradley), "Bradley APC" },
- { nameof(Key.EntityBuilding), "Building" },
- { nameof(Key.EntityChicken), "Chicken" },
- { nameof(Key.EntityFlameTurret), "Flame Turret" },
- { nameof(Key.EntityGunTrap), "Shotgun Trap" },
- { nameof(Key.EntityHelicopter), "Helicopter" },
- { nameof(Key.EntityMurderer), "Murderer" },
- { nameof(Key.EntityNPC), "NPC" },
- { nameof(Key.EntityPlayer), "Player" },
- { nameof(Key.EntitySAMSite), "SAM Site" },
- { nameof(Key.EntityScientist), "Scientist" },
- { nameof(Key.EntityStag), "Stag" },
- { nameof(Key.EntityTC), "Tool Cupboard" },
- { nameof(Key.EntityTrap), "Trap" },
- { nameof(Key.file), "file" },
- { nameof(Key.For), "for" },
- { nameof(Key.idle), "idle" },
- { nameof(Key.InvalidSteamId), "Invalid SteamID" },
- { nameof(Key.IP), "IP" },
- { nameof(Key.IpBlocked), "<color=#ffc000><size=12>IP: Blocked</size></color>" },
- { nameof(Key.IpCooldown), "<color=#ffc000><size=12>IP: Cooldown</size></color>" },
- { nameof(Key.Kicked), "Kicked" },
- { nameof(Key.LogAntiCheatAim), "<color=#ffc000><size=12>Hit info for {playername}[{playerid}]: {target} ({bodypart}; {distance}m; r={range_variance}; a={angle_variance}; p={pvp_variance}; {speed}m/s) {weapon}</size></color>" },
- { nameof(Key.LogAntiCheatGravity), "<color=#ffc000><size=12>Gravity info for {playername}[{playerid}]: {amount} {position}</size></color>" },
- { nameof(Key.LogAntiCheatMeleeRate), "<color=#ffc000><size=12>Melee info for {playername}[{playerid}]: {weapon} ({delay}) - {target}</size></color>" },
- { nameof(Key.LogAntiCheatRecoil), "<color=#ffc000><size=12>Recoil [y: {yaw}({count_x})][p: {pitch}({count_y})][a: {swing}] {playername}[{playerid}] - {weapon}</size></color>" },
- { nameof(Key.LogAntiCheatServer), "<color=#ffc000><size=12>Server AntiHack violation for {playername}[{playerid}]: {type}({amount}) {position}{colliders}</size></color>" },
- { nameof(Key.LogAntiCheatStash), "<color=#ffc000><size=12>Stash discovery info for {playername}[{playerid}]: at {grid}{position} - owner={ownerid}</size></color>" },
- { nameof(Key.LogAntiCheatTrajectory), "<color=#ffc000><size=12>Trajectory [t: {trajectory}] {playername}[{playerid}]: {weapon}({distance}m - {reported}m)</size></color>" },
- { nameof(Key.LogAntiSpamItemDrop), "<color=#ffc000><size=12>Item drop by player {playername}[{playerid}] - {itemname}[{itemid}]</size></color>" },
- { nameof(Key.LogConnect), "<color=#ffc000><size=12>{action} connection for {playername}[{playerid}]: {type}({reason})</size></color>" },
- { nameof(Key.LogDiscordConfig), "<color=#ffc0c0><size=12>Discord: WebHook URL is not configured!</size></color>" },
- { nameof(Key.LogDiscordMessage), "<color=#ffc0c0><size=12>Discord: Message requires at least one \'content\' or one \'embed\' field!</size></color>" },
- { nameof(Key.LogIpFilter), "<color=#ffc000><size=12>IP Filter: {action} connection from {address}</size></color>" },
- { nameof(Key.LogSteam), "<color=#ffc0c0><size=12>Steam Check[{api}]: {type} error for {playername}[{playerid}] - {info}</size></color>" },
- { nameof(Key.LogSteamConfig), "<color=#ffc0c0><size=12>Steam Check[{api}]: APIKEY missing! Get one from here: {link}</size></color>" },
- { nameof(Key.LogUserBypass), "<color=#ffc000><size=12>User Bypass: {playername}[{playerid}](address={address}; banned {bantime}; played {playtime}) - {status}</size></color>" },
- { nameof(Key.LogVpnCheck), "<color=#ffc000><size=12>VPN Check[{api}]: {address}({info})</size></color>" },
- { nameof(Key.LogVpnCheckConfig), "<color=#ffc0c0><size=12>VPN Check[{api}]: APIKEY missing! Get one from here: {link}</size></color>" },
- { nameof(Key.LogVpnCheckError), "<color=#ffc0c0><size=12>VPN Check[{api}]: {type} error for {address} - {info}</size></color>" },
- { nameof(Key.LogWebHook), "<color=#ffc0c0><size=12>WebHook({category}): {type} error - {info}</size></color>" },
- { nameof(Key.Name), "Name" },
- { nameof(Key.never), "never" },
- { nameof(Key.NoReasonGiven), "no reason given" },
- { nameof(Key.NULL), "null" },
- { nameof(Key.offline), "offline" },
- { nameof(Key.OnAntiCheatTriggered), "{action} for {category} - {type}" },
- { nameof(Key.online), "online" },
- { nameof(Key.OxideGroups), "Oxide Groups" },
- { nameof(Key.Pardoned), "Pardoned" },
- { nameof(Key.permanently), "permanently" },
- { nameof(Key.Played), "Played" },
- { nameof(Key.remove), "remove" },
- { nameof(Key.Removed), "Removed" },
- { nameof(Key.Saved), "Saved" },
- { nameof(Key.Server), "Server" },
- { nameof(Key.SERVER), "SERVER" },
- { nameof(Key.Status), "Status" },
- { nameof(Key.Steam), "Steam" },
- { nameof(Key.SteamBanActive), "VAC Banned" },
- { nameof(Key.SteamBanCommunity), "Community Banned" },
- { nameof(Key.SteamBanDays), "Days Since Ban" },
- { nameof(Key.SteamBanEconomy), "Economy Banned" },
- { nameof(Key.SteamBanGame), "Game Bans" },
- { nameof(Key.SteamBanVAC), "VAC Bans" },
- { nameof(Key.SteamGameCount), "Game Count" },
- { nameof(Key.SteamGameHours), "Hours Played" },
- { nameof(Key.SteamID), "SteamID" },
- { nameof(Key.SteamProfileInvalid), "Invalid Profile" },
- { nameof(Key.SteamProfileLimited), "Limited Profile" },
- { nameof(Key.SteamProfilePrivate), "Private Profile" },
- { nameof(Key.SteamShareFamily), "Family Share" },
- { nameof(Key.True), "True" },
- { nameof(Key.Unbanned), "Unbanned" },
- { nameof(Key.Unblocked), "Unblocked" },
- { nameof(Key.Uncrippled), "Uncrippled" },
- { nameof(Key.unknown), "unknown" },
- { nameof(Key.UnknownKey), "<color=#ffc0c0><size=12>Text error: language={language}]; key={key}</size></color>" },
- { nameof(Key.UserAction), "<color=#ffc000><size=12>{actor}: {action} {playername}[{playerid}]</size></color>" },
- { nameof(Key.UserBanTeleport), "<color=#c0ffc0><size=12>A banned player was teleported to your location!</size></color>" },
- { nameof(Key.UserBanTeleported), "<color=#c0ffc0><size=12>Teleported {playername}[{playerid}] to {victim}.</size></color>" },
- { nameof(Key.UserConnectBanInherit), "<color=#ffff00><size=12>You are banned from this server (Inherited: {reason})</size></color>" },
- { nameof(Key.UserConnectSteamIdInvalid), "<color=#ffff00><size=12>Connection denied (SteamID: Invalid)</size></color>" },
- { nameof(Key.UserConnectIpBlocked), "<color=#ffff00><size=12>Connection denied (IP: Blocked)</size></color>" },
- { nameof(Key.UserInfoText), "<color=#c0c0ff><size=12>{info}</size></color>" },
- { nameof(Key.UserInfoTextBullet), "<color=#c0c0ff><size=12>\n - {info}</size></color>" },
- { nameof(Key.UserInfoTextLabel), "<color=#c0c0ff><size=12>\n {label}: {info}</size></color>" },
- { nameof(Key.UserPardonProgress), "<size=12><color=#ffc000>Pardoned users: </color><color=#ffffc0>{count}/{total}</color></size>" },
- { nameof(Key.Violation), "<color=#ffffc0><size=12>{action} {playername}[{playerid}] for {category}({type}): {details}</size></color>" },
- { nameof(Key.ViolationAim), "<color=#ffffc0><size=12>{target}, {weapon}, {bodypart}, {distance}m, {angle}deg</size></color>" },
- { nameof(Key.ViolationFireRate), "<color=#ffffc0><size=12>{weapon}, {delay}s</size></color>" },
- { nameof(Key.ViolationGravity), "<color=#ffffc0><size=12>{amount}m</size></color>" },
- { nameof(Key.ViolationMeleeRate), "<color=#ffffc0><size=12>{weapon}, {delay}s, {target}</size></color>" },
- { nameof(Key.ViolationRecoil), "<color=#ffffc0><size=12>{weapon}, yaw={yaw}, pitch={pitch}</size></color>" },
- { nameof(Key.ViolationStash), "<color=#ffffc0><size=12>{grid}{position}</size></color>" },
- { nameof(Key.ViolationTrajectory), "<color=#ffffc0><size=12>{weapon}, {distance}m, {reported}m</size></color>" },
- { nameof(Key.ViolationWallHack), "<color=#ffffc0><size=12>{weapon}, {target}</size></color>" },
- { nameof(Key.VPN), "VPN" },
- { nameof(Key.VpnCache), "VPN Cache" },
- { nameof(Key.VpnDetected), "<color=#ffc000><size=12>VPN: Detected</size></color>" },
- { nameof(Key.Warning), "Warning" }
- }, _instance, "en");
- }
- private static string Replace(string message, Dictionary<string, string> parameters = null)
- {
- if((message != null) && (parameters != null))
- {
- foreach(var entry in parameters)
- {
- message = message.Replace('{' + entry.Key + '}', entry.Value);
- }
- }
- return message;
- }
- private static string Strip(string message)
- {
- if(string.IsNullOrEmpty(message))
- {
- return string.Empty;
- }
- return RegEx.markup.Replace(message, (match) =>
- {
- var tag = match.Value.ToLower();
- switch(tag)
- {
- case "<b>":
- case "<i>":
- case "</b>":
- case "</color>":
- case "</i>":
- case "</size>":
- return string.Empty;
- }
- if(tag.StartsWith("<color=") || tag.StartsWith("<size="))
- {
- return string.Empty;
- }
- return match.Value;
- });
- }
- public static string Sanitize(string message)
- {
- if(string.IsNullOrEmpty(message))
- {
- return string.Empty;
- }
- message = RegEx.clean1.Replace(message, " ");
- message = RegEx.clean2.Replace(message, " ");
- return Trim(message);
- }
- private static string Trim(string message)
- {
- if(string.IsNullOrEmpty(message))
- {
- return string.Empty;
- }
- return RegEx.spaces.Replace(message, " ").Trim();
- }
- public static void Unload()
- {
- RegEx.Unload();
- foreach(var language in decorated)
- {
- language.Value.Clear();
- }
- decorated.Clear();
- foreach(var language in unadorned)
- {
- language.Value.Clear();
- }
- unadorned.Clear();
- server_language = null;
- }
- }
- #endregion _text_
- #region _timers_
- private class Timers
- {
- private static readonly List<Timer> timers = new List<Timer>();
- public static void Add(float interval, Action callback)
- {
- timers.Add(_instance.timer.Every(interval, callback));
- }
- public static void Destroy()
- {
- foreach(var timer in timers)
- {
- timer.Destroy();
- }
- timers.Clear();
- }
- }
- #endregion _timers_
- #region _user_
- private class User
- {
- public class Settings
- {
- public UserBypass Bypass;
- public UserFriend Friend;
- public UserTeam Team;
- public Settings()
- {
- Bypass = new UserBypass();
- Friend = new UserFriend();
- Team = new UserTeam();
- }
- public class UserBypass
- {
- public ulong DaysSinceBan;
- public bool Enabled;
- public ulong HoursPlayed;
- public bool Multiply;
- public UserBypass()
- {
- DaysSinceBan = 10ul;
- HoursPlayed = 6ul;
- }
- public void Validate()
- {
- Configuration.Clamp(ref DaysSinceBan, 1ul, 365ul);
- Configuration.Clamp(ref HoursPlayed, 1ul, 8760ul);
- }
- }
- public class UserFriend
- {
- public bool Damage;
- }
- public class UserTeam
- {
- public bool Damage;
- }
- public void Validate()
- {
- Configuration.Validate(ref Bypass, () => new UserBypass(), () => Bypass.Validate());
- Configuration.Validate(ref Friend, () => new UserFriend());
- Configuration.Validate(ref Team, () => new UserTeam());
- }
- }
- private class Info
- {
- public ulong userid;
- public string name;
- public HashSet<string> names;
- public string address;
- public HashSet<string> addresses;
- public DateTime time_connected;
- public DateTime time_disconnected;
- public TimeSpan time_played;
- public ulong ban_count;
- public string ban_reason;
- public DateTime ban_time;
- public DateTime ban_timer;
- public bool is_banned;
- public ulong cripple_count;
- public string cripple_reason;
- public DateTime cripple_time;
- public DateTime cripple_timer;
- public bool is_crippled;
- public Vector3 l_position;
- public Vector3 v_position;
- [JsonIgnore] public DateTime access_time;
- [JsonIgnore] public ulong attacked;
- [JsonIgnore] public ulong attacker;
- [JsonIgnore] public bool dirty;
- [JsonIgnore] public BasePlayer player;
- [JsonIgnore] public Stack<ulong> teleport;
- [JsonIgnore] public List<ulong> victims;
- public Info()
- {
- userid = 0;
- name = string.Empty;
- names = new HashSet<string>();
- address = string.Empty;
- addresses = new HashSet<string>();
- time_connected = DateTime.MaxValue;
- time_disconnected = DateTime.MinValue;
- time_played = TimeSpan.Zero;
- ban_count = 0;
- ban_reason = string.Empty;
- ban_time = DateTime.MaxValue;
- ban_timer = DateTime.MinValue;
- is_banned = false;
- cripple_count = 0;
- cripple_reason = string.Empty;
- cripple_time = DateTime.MaxValue;
- cripple_timer = DateTime.MinValue;
- is_crippled = false;
- l_position = Vector3.zero;
- v_position = Vector3.zero;
- attacked = 0;
- attacker = 0;
- victims = new List<ulong>();
- dirty = true;
- }
- }
- private static readonly DataFile<string, HashSet<ulong>> names = new DataFile<string, HashSet<ulong>>("user_names");
- private static ActionQueue teleport;
- private static readonly Dictionary<ulong, Info> users = new Dictionary<ulong, Info>();
- private static void Action(IPlayer actor, Key action, Info user = null)
- {
- var parameters = new Dictionary<string, string>
- {
- { "action", Text.GetPlain(action) },
- { "actor", Text.Actor(actor) },
- { "playerid", user?.userid.ToString() ?? "*" },
- { "playername", Text.Sanitize(user?.name ?? Text.GetPlain(Key.AllUsers)) }
- };
- Log.Console(Key.UserAction, parameters);
- if(config.Admin.Broadcast)
- {
- foreach(var player in BasePlayer.activePlayerList)
- {
- if(Permissions.Admin(player.userID))
- {
- parameters["action"] = Text.GetPlain(action, player);
- parameters["actor"] = Text.Actor(actor, player);
- parameters["playername"] = Text.Sanitize(user?.name ?? Text.GetPlain(Key.AllUsers, player));
- Chat.Send(player, Key.UserAction, parameters);
- }
- }
- }
- }
- public static string Address(ulong userid)
- {
- return Load(userid).address;
- }
- public static void AssignAttacker(BasePlayer attacker, BasePlayer victim)
- {
- if((attacker == null) || attacker.IsAdmin || victim.IsAdmin || !victim.IsConnected)
- {
- return;
- }
- if((attacker == victim) || (victim.lastDamage == DamageType.Bleeding))
- {
- return;
- }
- if(IsTeamMate(attacker, victim) || IsFriend(attacker, victim.userID))
- {
- return;
- }
- Load(attacker.userID).attacked = victim.userID;
- Load(victim.userID).attacker = attacker.userID;
- }
- public static void AssignVictim(BasePlayer victim)
- {
- var user = Load(victim.userID);
- if(victim.IsConnected && (user.attacker != 0))
- {
- var attacker = Load(user.attacker);
- attacker.victims.Remove(victim.userID);
- attacker.victims.Add(victim.userID);
- }
- user.attacker = 0;
- }
- private static void AssignVictims(Info user)
- {
- user.teleport = new Stack<ulong>();
- if((user.attacked != 0) && !user.victims.Contains(user.attacked))
- {
- user.teleport.Push(user.attacked);
- user.attacked = 0;
- }
- foreach(var victim in user.victims)
- {
- user.teleport.Push(victim);
- }
- user.victims.Clear();
- }
- public static void Ban(ulong userid, string reason = null, ulong seconds = 0, IPlayer actor = null)
- {
- var user = Load(userid);
- if(user.is_banned)
- {
- if(actor == null)
- {
- return;
- }
- user.is_banned = false;
- _instance.server.Command("unban", user.userid.ToString());
- }
- else
- {
- user.ban_count++;
- }
- _instance.NextTick(() =>
- {
- user.ban_reason = string.IsNullOrEmpty(reason) ? Text.GetPlain(Key.NoReasonGiven) : reason;
- user.ban_time = DateTime.UtcNow;
- user.ban_timer = (seconds == 0) ? DateTime.MaxValue : user.ban_time.AddSeconds(seconds);
- user.is_banned = true;
- user.dirty = true;
- Action(actor, Key.Banned, user);
- _instance.server.Command("banid", user.userid.ToString(), user.name, user.ban_reason);
- });
- }
- public static ulong BanCount(ulong userid)
- {
- return Load(userid).ban_count;
- }
- private static void BanInherit(ulong userid, string name, string address, Info copy)
- {
- var user = Load(userid);
- Update(user, name, address);
- user.ban_count = copy.ban_count;
- user.ban_reason = copy.ban_reason;
- user.ban_time = copy.ban_time;
- user.ban_timer = copy.ban_timer;
- user.is_banned = copy.is_banned;
- user.time_connected = DateTime.UtcNow;
- user.time_disconnected = user.time_connected;
- user.dirty = true;
- Action(null, Key.Banned, user);
- _instance.server.Command("banid", user.userid.ToString(), user.name, user.ban_reason);
- }
- public static void BanReset(ulong userid, IPlayer actor = null)
- {
- var user = Load(userid);
- var was_banned = user.is_banned;
- user.ban_count = 0;
- user.ban_reason = string.Empty;
- user.ban_time = DateTime.MaxValue;
- user.ban_timer = DateTime.MinValue;
- user.is_banned = false;
- user.dirty = true;
- Action(actor, Key.BanReset, user);
- if(was_banned)
- {
- _instance.server.Command("unban", user.userid.ToString());
- }
- }
- private static void BanTeleport(Info user, ulong count = 0)
- {
- Info victim = null;
- while((victim == null) && (user.teleport.Count > 0))
- {
- victim = Load(user.teleport.Peek());
- if(!(victim.player?.IsConnected ?? false))
- {
- count = 0; victim = null;
- user.teleport.Pop();
- }
- }
- if(victim == null)
- {
- return;
- }
- user.access_time = DateTime.UtcNow;
- if(victim.player.IsSleeping() || victim.player.IsDead() || victim.player.HasParent())
- {
- if(count < 10)
- {
- teleport.Enqueue(() => BanTeleport(user, count + 1));
- }
- else
- {
- user.teleport.Pop();
- if(user.teleport.Count > 0)
- {
- teleport.Enqueue(() => BanTeleport(user));
- }
- }
- return;
- }
- var attacker = BasePlayer.FindAwakeOrSleeping(user.userid.ToString());
- if(attacker == null)
- {
- return;
- }
- var position = attacker.transform.position; position.y += 0.1f;
- RaycastHit hit;
- if(Physics.Raycast(position, Vector3.down, out hit))
- {
- position.y -= hit.distance;
- }
- attacker.MovePosition(position);
- // Facepunch removed BasePlayer.ClientRPCPlayer (CS1061). Current RPC path is
- // ClientRPC(RpcTarget.Player(rpcName, connectionPlayer), args...). Matches
- // vanilla VehicleSpawner.NudgePlayersInRadius ForcePositionTo usage.
- // Old: attacker.ClientRPCPlayer(null, attacker, "ForcePositionTo", position);
- attacker.ClientRPC(RpcTarget.Player("ForcePositionTo", attacker), position);
- attacker.SendNetworkUpdateImmediate();
- Chat.Admin(Key.UserBanTeleported, new Dictionary<string, string>
- {
- { "playerid", user.userid.ToString() },
- { "playername", Text.Sanitize(user.name) },
- { "victim", Text.Sanitize(victim.name) }
- });
- Chat.Send(victim.player, Key.UserBanTeleport);
- }
- public static DateTime BanTime(ulong userid)
- {
- return Load(userid).ban_time;
- }
- private static void BanTimeEnforce(Info user)
- {
- if(!config.Ban.Time.Enforce)
- {
- return;
- }
- var seconds = 0ul;
- if(config.Ban.Time.Seconds > 0)
- {
- seconds = config.Ban.Time.Seconds;
- if(config.Ban.Time.Multiply)
- {
- seconds *= user.ban_count;
- }
- }
- if(seconds == 0)
- {
- user.ban_timer = DateTime.MaxValue;
- }
- else
- {
- user.ban_timer = user.ban_time.AddSeconds(seconds);
- }
- user.dirty = true;
- }
- private static bool CanBypass(Info user)
- {
- if(Permissions.Ignore(user.userid) || (config.Admin.Bypass && Permissions.Admin(user.userid)))
- {
- return true;
- }
- else if(!config.User.Bypass.Enabled)
- {
- return false;
- }
- bool never_banned = true;
- var days_since_banned = 0.0;
- var date_current = DateTime.UtcNow;
- var time_banned = TimeSpan.MaxValue;
- if(user.ban_time < date_current)
- {
- time_banned = date_current.Subtract(user.ban_time);
- days_since_banned = time_banned.TotalDays;
- never_banned = false;
- }
- var time_played = TimePlayed(user);
- var hours_played = time_played.TotalHours;
- bool bypass = false;
- var days_banned_minimum = config.User.Bypass.DaysSinceBan;
- var hours_played_minimum = config.User.Bypass.HoursPlayed;
- if(config.User.Bypass.Multiply)
- {
- var multiplier = user.ban_count + 1;
- days_banned_minimum *= multiplier;
- hours_played_minimum *= multiplier;
- }
- if(hours_played >= hours_played_minimum)
- {
- bypass = never_banned || (days_since_banned >= days_banned_minimum);
- }
- if(config.Log.User.Bypass)
- {
- Log.Console(Key.LogUserBypass, new Dictionary<string, string>
- {
- { "address", user.address },
- { "bantime", never_banned ? Text.Get(Key.never) : $"{Text.Duration.Short(time_banned)} {Text.Get(Key.ago)}" },
- { "playerid", user.userid.ToString() },
- { "playername", Text.Sanitize(user.name) },
- { "playtime", Text.Duration.Hours(time_played) },
- { "status", bypass ? Text.Get(Key.Allowed) : Text.Get(Key.Denied) }
- });
- }
- return bypass;
- }
- public static object CanConnect(string name, string id, string address)
- {
- if(IP.Cooldown(address))
- {
- return Text.GetPlain(Key.IpCooldown);
- }
- ulong userid;
- if(!id.StartsWith("7656119") || !ulong.TryParse(id, out userid))
- {
- if(config.Log.User.Connect)
- {
- Log.Console(Key.LogConnect, new Dictionary<string, string>
- {
- { "action", Text.GetPlain(Key.Denied) },
- { "playerid", id },
- { "playername", Text.Sanitize(name) },
- { "reason", address },
- { "type", Text.GetPlain(Key.InvalidSteamId) }
- });
- }
- return Text.GetPlain(Key.UserConnectSteamIdInvalid, Text.Language(id));
- }
- if(Permissions.Ignore(userid, true))
- {
- return null;
- }
- else if(Permissions.Admin(userid, true) && config.Admin.Bypass)
- {
- return null;
- }
- if(!IP.Filter(address, userid))
- {
- if(config.Log.User.Connect)
- {
- Log.Console(Key.LogConnect, new Dictionary<string, string>
- {
- { "action", Text.GetPlain(Key.Denied) },
- { "playerid", id },
- { "playername", Text.Sanitize(name) },
- { "reason", address },
- { "type", Text.GetPlain(Key.Blocked) }
- });
- }
- return Text.GetPlain(Key.UserConnectIpBlocked, userid);
- }
- var cripple_inherit = config.Cripple.Inherit && !IsCrippled(userid);
- if(config.Ban.Inherit || cripple_inherit)
- {
- var userids = IP.Find(address);
- if(cripple_inherit)
- {
- foreach(var entry in userids)
- {
- var user = Load(entry);
- if(user.is_crippled)
- {
- _instance.NextTick(() => CrippleInherit(userid, name, address, user));
- break;
- }
- }
- }
- if(config.Ban.Inherit)
- {
- foreach(var entry in userids)
- {
- var user = Load(entry);
- if(user.is_banned)
- {
- if(config.Log.User.Connect)
- {
- Log.Console(Key.LogConnect, new Dictionary<string, string>
- {
- { "action", Text.GetPlain(Key.Denied) },
- { "playerid", id },
- { "playername", Text.Sanitize(name) },
- { "reason", user.ban_reason },
- { "type", Text.GetPlain(Key.BanInherited) }
- });
- }
- _instance.NextTick(() => BanInherit(userid, name, address, user));
- return Text.GetPlain(Key.UserConnectBanInherit, userid, new Dictionary<string, string>
- {
- { "reason", user.ban_reason }
- });
- }
- }
- }
- }
- return null;
- }
- public static bool CanFly(BasePlayer player) =>
- HasAuthLevel(player) || HasAdminFlag(player) || HasDeveloperFlag(player);
- private static bool CanLoot(ulong userid, ulong targetid)
- {
- if(userid == targetid)
- {
- return true;
- }
- if(IsCrippled(userid))
- {
- if(Permissions.Ignore(userid) || Permissions.Admin(userid))
- {
- return true;
- }
- return false;
- }
- return true;
- }
- public static object CanLoot(BasePlayer player, ulong targetid)
- {
- if(ShouldIgnore(player) || CanLoot(player.userID, targetid))
- {
- return null;
- }
- return false;
- }
- public static void Cripple(ulong userid, string reason = null, ulong seconds = 0, IPlayer actor = null)
- {
- var user = Load(userid);
- if(!user.is_crippled)
- {
- user.cripple_count++;
- }
- user.cripple_reason = string.IsNullOrEmpty(reason) ? Text.GetPlain(Key.NoReasonGiven) : reason;
- user.cripple_time = DateTime.UtcNow;
- user.cripple_timer = (seconds == 0) ? DateTime.MaxValue : user.cripple_time.AddSeconds(seconds);
- user.is_crippled = true;
- user.dirty = true;
- Action(actor, Key.Crippled, user);
- }
- private static void CrippleInherit(ulong userid, string name, string address, Info copy)
- {
- var user = Load(userid);
- Update(user, name, address);
- user.cripple_count = copy.cripple_count;
- user.cripple_reason = copy.cripple_reason;
- user.cripple_time = copy.cripple_time;
- user.cripple_timer = copy.cripple_timer;
- user.is_crippled = copy.is_crippled;
- user.dirty = true;
- Action(null, Key.Crippled, user);
- }
- public static void CrippleReset(ulong userid, IPlayer actor = null)
- {
- var user = Load(userid);
- user.cripple_count = 0;
- user.cripple_reason = string.Empty;
- user.cripple_time = DateTime.MaxValue;
- user.cripple_timer = DateTime.MinValue;
- user.is_crippled = false;
- user.dirty = true;
- Action(actor, Key.CrippleReset, user);
- }
- public static bool Exists(ulong userid) =>
- users.ContainsKey(userid) || Data.Exists($"Users/{userid}");
- public static HashSet<ulong> Find(string text)
- {
- var found = new HashSet<ulong>();
- if(IP.IsValid(text))
- {
- foreach(var userid in IP.Find(text))
- {
- found.Add(userid);
- }
- }
- else if(text.IsSteamId())
- {
- ulong userid;
- if(ulong.TryParse(text, out userid) && Exists(userid))
- {
- found.Add(userid);
- }
- }
- else
- {
- var key = text.Sanitize();
- if(names.Contains(key))
- {
- foreach(var userid in names[key])
- {
- found.Add(userid);
- }
- }
- else
- {
- var search = key.ToLower();
- names.ForEach((name, userids) =>
- {
- if(name.ToLower().Contains(search))
- {
- foreach(var userid in userids)
- {
- found.Add(userid);
- }
- }
- });
- }
- }
- return found;
- }
- public static Vector3 GetLastSeenPosition(ulong userid)
- {
- var player = BasePlayer.FindAwakeOrSleeping(userid.ToString());
- if(player != null)
- {
- return player.transform.position;
- }
- return Load(userid).l_position;
- }
- public static Vector3 GetViolationPosition(ulong userid) =>
- Load(userid).v_position;
- public static bool HasAuthLevel(BasePlayer player) =>
- (player?.net?.connection?.authLevel ?? 0) > 0;
- public static bool HasAdminFlag(BasePlayer player) =>
- player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin);
- private static bool HasConnected(Info user) =>
- user.time_connected != DateTime.MaxValue;
- public static bool HasDeveloperFlag(BasePlayer player) =>
- player.HasPlayerFlag(BasePlayer.PlayerFlags.IsDeveloper);
- public static bool HasParent<T>(BasePlayer player) =>
- player.GetParentEntity() is T;
- public static string InfoText(ulong userid) =>
- InfoText(userid, Text.Language());
- public static string InfoText(ulong userid, BasePlayer player) =>
- InfoText(userid, Text.Language(player.UserIDString));
- public static string InfoText(ulong userid, IPlayer iplayer) =>
- InfoText(userid, Text.Language(iplayer.IsServer ? null : iplayer.Id));
- public static string InfoText(ulong userid, ulong playerid) =>
- InfoText(userid, Text.Language(playerid.ToString()));
- public static string InfoText(ulong userid, string language)
- {
- if(!Exists(userid))
- {
- return Text.GetPlain(Key.unknown, language);
- }
- var user = Load(userid);
- var info = new StringBuilder();
- var parameters = new Dictionary<string, string>();
- parameters["label"] = Text.GetPlain(Key.SteamID, language);
- parameters["info"] = user.userid.ToString();
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- parameters["label"] = Text.GetPlain(Key.Name, language);
- parameters["info"] = Text.Sanitize(user.name);
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- if(user.names.Count > 1)
- {
- foreach(var name in user.names)
- {
- if(name != user.name)
- {
- parameters["info"] = Text.Sanitize(name);
- info.Append(Text.GetPlain(Key.UserInfoTextBullet, language, parameters));
- }
- }
- }
- parameters["label"] = Text.GetPlain(Key.Played, language);
- parameters["info"] = Text.Duration.Hours(TimePlayed(user), language);
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- parameters["label"] = Text.GetPlain(Key.Status, language);
- parameters["info"] = StatusText(user, language);
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- if(user.ban_count > 0)
- {
- parameters["label"] = Text.GetPlain(Key.BanCount, language);
- parameters["info"] = user.ban_count.ToString();
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- if(user.is_banned)
- {
- parameters["label"] = Text.GetPlain(Key.BanReason, language);
- parameters["info"] = user.ban_reason;
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- }
- }
- if(user.cripple_count > 0)
- {
- parameters["label"] = Text.GetPlain(Key.CrippleCount, language);
- parameters["info"] = user.cripple_count.ToString();
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- if(user.is_crippled)
- {
- parameters["label"] = Text.GetPlain(Key.CrippleReason, language);
- parameters["info"] = user.cripple_reason;
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- }
- }
- parameters["label"] = Text.GetPlain(Key.Address, language);
- parameters["info"] = user.address;
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- if(user.addresses.Count > 1)
- {
- foreach(var address in user.addresses)
- {
- if(address != user.address)
- {
- parameters["info"] = address;
- info.Append(Text.GetPlain(Key.UserInfoTextBullet, language, parameters));
- }
- }
- }
- parameters["label"] = Text.GetPlain(Key.OxideGroups, language);
- parameters["info"] = string.Join(", ", Permissions.Groups(user.userid));
- info.Append(Text.GetPlain(Key.UserInfoTextLabel, language, parameters));
- parameters["info"] = info.ToString();
- return Text.GetPlain(Key.UserInfoText, language, parameters);
- }
- public static bool IsBanned(ulong userid) =>
- Load(userid).is_banned;
- private static bool IsConnected(Info user) =>
- user.player?.IsConnected ?? false;
- public static bool IsConnected(ulong userid)
- {
- Info user;
- if(users.TryGetValue(userid, out user))
- {
- return IsConnected(user);
- }
- return false;
- }
- public static bool IsCrippled(ulong userid) =>
- Load(userid).is_crippled;
- public static bool IsFriend(BasePlayer a, BasePlayer b) =>
- IsFriend(a, b.userID);
- public static bool IsFriend(BasePlayer player, ulong userid) =>
- (_instance?.Friends?.Call<bool>("IsFriend", player.userID, userid) ?? false);
- public static bool IsInactive(BasePlayer player) =>
- player.IsDead() || player.IsSleeping() || !player.IsConnected;
- private static bool IsStale(Info user) =>
- !(HasConnected(user) && (user.time_connected > SaveRestore.SaveCreatedTime.ToUniversalTime()));
- public static bool IsTeamMate(BasePlayer a, BasePlayer b)
- => (a.currentTeam != 0) && (a.currentTeam == b.currentTeam);
- public static bool IsTeamMate(BasePlayer player, ulong userid)
- {
- var team = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
- return team?.members?.Contains(userid) ?? false;
- }
- public static void Kick(ulong userid, string reason = null, IPlayer actor = null)
- {
- var user = Load(userid);
- if(IsConnected(user))
- {
- reason = string.IsNullOrEmpty(reason) ? Text.GetPlain(Key.NoReasonGiven) : reason;
- if(actor != null)
- {
- Action(actor, Key.Kicked, user);
- }
- _instance.server.Command("kick", user.userid.ToString(), reason);
- }
- }
- public static void Load()
- {
- names.Load();
- teleport = new ActionQueue(6.0f);
- Timers.Add(6.0f, () => Scan());
- }
- private static Info Load(ulong userid)
- {
- Info user;
- if(!userid.IsSteamId())
- {
- throw new ArgumentException("Parameter must be a valid Steam ID", nameof(userid));
- }
- else if(users.ContainsKey(userid))
- {
- user = users[userid];
- }
- else
- {
- try
- {
- user = Data.ReadObject<Info>($"Users/{userid}");
- if((user?.userid ?? 0) == 0)
- {
- throw new Exception();
- }
- }
- catch
- {
- user = new Info
- {
- dirty = true,
- userid = userid
- };
- }
- if(user.name == null)
- {
- user.dirty = true; user.name = string.Empty;
- }
- if(user.names == null)
- {
- user.dirty = true; user.names = new HashSet<string>();
- }
- if(user.address == null)
- {
- user.dirty = true; user.address = string.Empty;
- }
- if(user.addresses == null)
- {
- user.dirty = true; user.addresses = new HashSet<string>();
- }
- if(user.ban_reason == null)
- {
- user.dirty = true; user.ban_reason = string.Empty;
- }
- if(user.cripple_reason == null)
- {
- user.dirty = true; user.cripple_reason = string.Empty;
- }
- if(IsStale(user))
- {
- SetLastSeenPosition(user, Vector3.zero);
- SetViolationPosition(user, Vector3.zero);
- }
- users.Add(userid, user);
- Save(user);
- }
- user.access_time = DateTime.UtcNow;
- return user;
- }
- public static string Name(ulong userid) =>
- Load(userid).name;
- public static void OnBanned(ulong userid, bool banned)
- {
- var user = Load(userid);
- if(banned)
- {
- if(!user.is_banned)
- {
- var serveruser = ServerUsers.Get(userid);
- user.ban_count++;
- user.ban_reason = string.IsNullOrEmpty(serveruser.notes) ? Text.GetPlain(Key.NoReasonGiven) : serveruser.notes;
- user.ban_time = DateTime.UtcNow;
- user.is_banned = true;
- if(serveruser.expiry < 0)
- {
- user.ban_timer = DateTime.MaxValue;
- }
- else
- {
- user.ban_timer = user.ban_time.AddSeconds(serveruser.expiry - Epoch.Current);
- }
- user.dirty = true;
- }
- BanTimeEnforce(user);
- if(config.Ban.Teleport)
- {
- AssignVictims(user);
- if(user.teleport.Count > 0)
- {
- _instance.timer.In(6.0f, () => BanTeleport(user));
- }
- }
- }
- else
- {
- if(user.is_banned && config.Ban.Time.Enforce)
- {
- if((user.ban_timer != DateTime.MaxValue) && (user.ban_timer > DateTime.UtcNow))
- {
- _instance.server.Command("banid", user.userid.ToString(), user.name, user.ban_reason);
- return;
- }
- }
- if(user.ban_count == 0)
- {
- user.ban_time = DateTime.MaxValue;
- }
- user.ban_reason = string.Empty;
- user.ban_timer = DateTime.MinValue;
- user.is_banned = false;
- user.dirty = true;
- }
- }
- public static void OnConnected(BasePlayer player)
- {
- var user = Load(player.userID);
- var connected = TimeSpan.FromSeconds(user.player?.net?.connection?.GetSecondsConnected() ?? 0.0f);
- user.time_connected = DateTime.UtcNow.Subtract(connected);
- if(user.is_banned)
- {
- user.is_banned = false;
- user.ban_reason = string.Empty;
- user.ban_timer = DateTime.MinValue;
- }
- if(_instance.PlaytimeTracker)
- {
- var result = _instance.PlaytimeTracker.Call("GetPlayTime", player.UserIDString);
- if(result != null)
- {
- var time_played = TimeSpan.FromSeconds(Convert.ToDouble(result));
- if(time_played > user.time_played)
- {
- user.time_played = time_played;
- }
- }
- }
- user.player = player;
- Update(user, player.displayName, IP.Parse(player?.Connection?.ipaddress));
- user.dirty = true;
- Permissions.Update(user.userid);
- if(!CanBypass(user))
- {
- Steam.Check(user.userid);
- VPN.Check(user.address, user.userid);
- }
- }
- public static void OnDisconnected(BasePlayer player)
- {
- var user = Load(player.userID);
- user.time_disconnected = DateTime.UtcNow;
- if(user.time_disconnected > user.time_connected)
- {
- user.time_played += user.time_disconnected.Subtract(user.time_connected);
- }
- user.player = null;
- SetLastSeenPosition(user, player.transform.position);
- user.dirty = true;
- Permissions.Reset(user.userid);
- }
- public static void OnLoot(BasePlayer player, ulong targetid)
- {
- if(ShouldIgnore(player))
- {
- return;
- }
- if(!CanLoot(player.userID, targetid))
- {
- _instance.NextFrame(() => player.EndLooting());
- }
- }
- public static void Pardon(ulong userid, IPlayer actor = null) =>
- Pardon(Load(userid), actor);
- public static void Pardon(IPlayer actor)
- {
- var found = new HashSet<ulong>();
- names.ForEach((name, userids) =>
- {
- found.UnionWith(userids);
- });
- var userid = new Queue<ulong>(found);
- Pardon(userid, actor);
- }
- private static void Pardon(Queue<ulong> userid, IPlayer actor, int total = 0)
- {
- if(total == 0)
- {
- total = userid.Count;
- }
- if(userid.Count > 0)
- {
- var user = Load(userid.Dequeue());
- Pardon(user, actor, false);
- Save(user);
- var count = total - userid.Count;
- if((count % ((total <= 100) ? 10 : 100)) == 0)
- {
- Chat.Reply(actor, Key.UserPardonProgress, new Dictionary<string, string>
- {
- { "count", count.ToString() },
- { "total", total.ToString() }
- });
- }
- _instance.NextTick(() => Pardon(userid, actor, total));
- }
- else
- {
- if(total > 0)
- {
- Chat.Reply(actor, Key.UserPardonProgress, new Dictionary<string, string>
- {
- { "count", total.ToString() },
- { "total", total.ToString() }
- });
- }
- Action(actor, Key.Pardoned);
- }
- }
- private static void Pardon(Info user, IPlayer actor, bool broadcast = true)
- {
- if(user.is_banned)
- {
- if(user.ban_count > 1)
- {
- user.dirty = true; user.ban_count = 1;
- BanTimeEnforce(user);
- }
- }
- else
- {
- if(user.ban_count != 0)
- {
- user.dirty = true; user.ban_count = 0;
- }
- if(user.ban_time != DateTime.MaxValue)
- {
- user.dirty = true; user.ban_time = DateTime.MaxValue;
- }
- if(user.ban_timer != DateTime.MinValue)
- {
- user.dirty = true; user.ban_timer = DateTime.MinValue;
- }
- }
- if(user.is_crippled)
- {
- if(user.cripple_count > 1)
- {
- user.dirty = true; user.cripple_count = 1;
- }
- }
- else
- {
- if(user.cripple_count != 0)
- {
- user.dirty = true; user.cripple_count = 0;
- }
- if(user.cripple_time != DateTime.MaxValue)
- {
- user.dirty = true; user.cripple_time = DateTime.MaxValue;
- }
- if(user.cripple_timer != DateTime.MinValue)
- {
- user.dirty = true; user.cripple_timer = DateTime.MinValue;
- }
- }
- if(broadcast)
- {
- Action(actor, Key.Pardoned, user);
- }
- }
- public static void Save()
- {
- var current = DateTime.UtcNow;
- var expired = TimeSpan.FromMinutes(30.0);
- var remove = new List<ulong>();
- foreach(var entry in users)
- {
- Save(entry.Value);
- if(current.Subtract(entry.Value.access_time) >= expired)
- {
- remove.Add(entry.Key);
- }
- }
- foreach(var entry in remove)
- {
- users.Remove(entry);
- }
- names.Save();
- }
- private static void Save(Info user)
- {
- if(user.dirty)
- {
- user.dirty = false;
- Data.WriteObject($"Users/{user.userid}", user);
- }
- }
- private static void Scan()
- {
- var current = DateTime.UtcNow;
- foreach(var entry in users)
- {
- var user = entry.Value;
- if(user.is_banned && (user.ban_timer != DateTime.MaxValue))
- {
- if(user.ban_timer > current)
- {
- user.access_time = current;
- }
- else
- {
- Unban(user.userid);
- }
- }
- else if(user.is_crippled && (user.cripple_timer != DateTime.MaxValue))
- {
- if(user.cripple_timer > current)
- {
- user.access_time = current;
- }
- else
- {
- Uncripple(user.userid);
- }
- }
- }
- }
- private static void SetLastSeenPosition(Info user, Vector3 position)
- {
- if(user.l_position != position)
- {
- user.l_position = position;
- user.dirty = true;
- }
- }
- private static void SetViolationPosition(Info user, Vector3 position)
- {
- if(user.v_position != position)
- {
- user.v_position = position;
- user.dirty = true;
- }
- }
- public static void SetViolationPosition(ulong userid)
- {
- Info user;
- if(users.TryGetValue(userid, out user))
- {
- if(user.player != null)
- {
- SetViolationPosition(user, user.player.transform.position);
- }
- }
- }
- public static bool ShouldIgnore(BasePlayer player) =>
- (player == null) || !player.userID.IsSteamId() || Permissions.Ignore(player.userID);
- public static string StatusText(ulong userid) =>
- StatusText(userid, Text.Language());
- public static string StatusText(ulong userid, BasePlayer player) =>
- StatusText(userid, Text.Language(player.UserIDString));
- public static string StatusText(ulong userid, IPlayer iplayer) =>
- StatusText(userid, Text.Language(iplayer.IsServer ? null : iplayer.Id));
- public static string StatusText(ulong userid, ulong playerid) =>
- StatusText(userid, Text.Language(playerid.ToString()));
- public static string StatusText(ulong userid, string language) =>
- Exists(userid) ? StatusText(Load(userid), language) : Text.GetPlain(Key.unknown, language);
- private static string StatusText(Info user, string language)
- {
- StringBuilder status = new StringBuilder();
- TimeSpan duration;
- if(user.is_banned)
- {
- status.Append(Text.GetPlain(Key.banned, language));
- status.Append(' ');
- if(TimeSpan.MaxValue == (duration = TimeBanned(user)))
- {
- status.Append(Text.GetPlain(Key.permanently, language));
- }
- else
- {
- status.Append(Text.Duration.Short(duration, language));
- }
- }
- else if(user.is_crippled)
- {
- status.Append(Text.GetPlain(Key.crippled, language));
- status.Append(' ');
- if(TimeSpan.MaxValue == (duration = TimeCrippled(user)))
- {
- status.Append(Text.GetPlain(Key.permanently, language));
- }
- else
- {
- status.Append(Text.Duration.Short(duration, language));
- }
- }
- else if(user.player?.IsConnected ?? false)
- {
- status.Append(Text.GetPlain(Key.online, language));
- status.Append(' ');
- if(TimeSpan.MaxValue == (duration = TimeOnline(user)))
- {
- status.Append(Text.GetPlain(Key.never, language));
- }
- else
- {
- status.Append(Text.Duration.Short(duration, language));
- }
- }
- else
- {
- status.Append(Text.GetPlain(Key.offline, language));
- status.Append(' ');
- if(TimeSpan.MaxValue == (duration = TimeOffline(user)))
- {
- status.Append(Text.GetPlain(Key.never, language));
- }
- else
- {
- status.Append(Text.Duration.Short(duration, language));
- }
- }
- return status.ToString();
- }
- public static List<ulong> Team(ulong userid)
- {
- ulong teamid = 0;
- var player = Load(userid).player;
- if(player != null)
- {
- teamid = player.currentTeam;
- }
- else
- {
- foreach(var team in RelationshipManager.ServerInstance.teams)
- {
- if(team.Value.members.Contains(userid))
- {
- teamid = team.Key;
- break;
- }
- }
- }
- if(teamid != 0)
- {
- return new List<ulong>(RelationshipManager.ServerInstance.teams[teamid].members);
- }
- return new List<ulong> { userid };
- }
- public static TimeSpan TimeBanned(ulong userid) =>
- TimeRemaining(Load(userid).ban_timer);
- private static TimeSpan TimeBanned(Info user) =>
- TimeRemaining(user.ban_timer);
- public static TimeSpan TimeCrippled(ulong userid) =>
- TimeRemaining(Load(userid).cripple_timer);
- private static TimeSpan TimeCrippled(Info user) =>
- TimeRemaining(user.cripple_timer);
- private static TimeSpan TimeRemaining(DateTime time)
- {
- if(time == DateTime.MaxValue)
- {
- return TimeSpan.MaxValue;
- }
- var current = DateTime.UtcNow;
- if(time > current)
- {
- return time.Subtract(current);
- }
- return TimeSpan.Zero;
- }
- public static TimeSpan TimeOffline(ulong userid) =>
- TimeSpent(Load(userid).time_disconnected);
- private static TimeSpan TimeOffline(Info user) =>
- TimeSpent(user.time_disconnected);
- public static TimeSpan TimeOnline(ulong userid) =>
- TimeSpent(Load(userid).time_connected);
- private static TimeSpan TimeOnline(Info user) =>
- TimeSpent(user.time_connected);
- private static TimeSpan TimeSpent(DateTime time)
- {
- if((time == DateTime.MaxValue) || (time == DateTime.MinValue))
- {
- return TimeSpan.MaxValue;
- }
- var current = DateTime.UtcNow;
- if(time < current)
- {
- return current.Subtract(time);
- }
- return TimeSpan.Zero;
- }
- public static TimeSpan TimePlayed(ulong userid) =>
- TimePlayed(Load(userid));
- private static TimeSpan TimePlayed(Info user)
- {
- var time_played = user.time_played;
- if(user.time_disconnected > user.time_connected)
- {
- time_played += user.time_disconnected.Subtract(user.time_connected);
- }
- else if(user.player?.IsConnected ?? false)
- {
- time_played += DateTime.UtcNow.Subtract(user.time_connected);
- }
- return time_played;
- }
- public static void Unban(ulong userid, bool manual = false, IPlayer actor = null) =>
- Unban(Load(userid), manual, actor);
- public static void Unban(IPlayer actor)
- {
- foreach(var entry in users)
- {
- var user = entry.Value;
- if(user.is_banned)
- {
- Unban(user, false, actor, false);
- }
- }
- Action(actor, Key.Unbanned);
- }
- private static void Unban(Info user, bool manual, IPlayer actor, bool broadcast = true)
- {
- if(user.is_banned)
- {
- if(manual)
- {
- user.ban_count -= (user.ban_count > 0) ? 1ul : 0ul;
- }
- user.is_banned = false;
- user.dirty = true;
- if(broadcast)
- {
- Action(actor, Key.Unbanned, user);
- }
- _instance.server.Command("unban", user.userid.ToString());
- }
- }
- public static void Uncripple(ulong userid, bool manual = false, IPlayer actor = null) =>
- Uncripple(Load(userid), manual, actor);
- public static void Uncripple(IPlayer actor)
- {
- foreach(var entry in users)
- {
- var user = entry.Value;
- if(user.is_crippled)
- {
- Uncripple(user, false, actor, false);
- }
- }
- Action(actor, Key.Uncrippled);
- }
- private static void Uncripple(Info user, bool manual, IPlayer actor, bool broadcast = true)
- {
- if(user.is_crippled)
- {
- if(manual)
- {
- user.cripple_count -= (user.cripple_count > 0) ? 1ul : 0ul;
- }
- user.cripple_reason = string.Empty;
- user.cripple_timer = DateTime.MinValue;
- user.is_crippled = false;
- user.dirty = true;
- if(broadcast)
- {
- Action(actor, Key.Uncrippled, user);
- }
- }
- }
- public static void Unload()
- {
- foreach(var player in BasePlayer.activePlayerList)
- {
- if(player.IsConnected)
- {
- OnDisconnected(player);
- }
- }
- foreach(var player in BasePlayer.sleepingPlayerList)
- {
- if(player.IsConnected)
- {
- OnDisconnected(player);
- }
- }
- Save();
- names.Unload();
- users.Clear();
- teleport.Clear();
- teleport = null;
- }
- public static void Update()
- {
- _instance.NextTick(() =>
- {
- foreach(var player in BasePlayer.activePlayerList)
- {
- if(player.IsConnected)
- {
- OnConnected(player);
- }
- }
- foreach(var player in BasePlayer.sleepingPlayerList)
- {
- if(player.IsConnected)
- {
- OnConnected(player);
- }
- }
- foreach(var serveruser in ServerUsers.GetAll(ServerUsers.UserGroup.Banned))
- {
- OnBanned(serveruser.steamid, true);
- }
- });
- }
- private static void Update(Info user, string name, string address)
- {
- if(user.name != name)
- {
- user.dirty = true; user.name = name;
- }
- if(user.names.Add(name))
- {
- user.dirty = true;
- }
- if(!names.Contains(name))
- {
- names.Add(name, new HashSet<ulong>());
- }
- if(names[name].Add(user.userid))
- {
- names.SetDirty();
- }
- if(!string.IsNullOrEmpty(address = address ?? user.address))
- {
- if(user.address != address)
- {
- user.dirty = true; user.address = address;
- }
- if(user.addresses.Add(address))
- {
- user.dirty = true;
- }
- IP.Update(address, user.userid);
- }
- }
- }
- #endregion _user_
- #region _version_
- private new class Version
- {
- public class Settings
- {
- public int Major;
- public int Minor;
- public int Patch;
- public Settings()
- {
- Major = Minor = Patch = 0;
- }
- public int Compare(int major, int minor, int patch)
- {
- return
- (Major != major) ? (Major - major) :
- (Minor != minor) ? (Minor - minor) :
- (Patch != patch) ? (Patch - patch) : 0;
- }
- public void Validate()
- {
- var current = (_instance as CovalencePlugin).Version;
- if(Compare(current.Major, current.Minor, current.Patch) < 0)
- {
- Configuration.SetDirty();
- Major = current.Major;
- Minor = current.Minor;
- Patch = current.Patch;
- Configuration.SetUpgrade();
- }
- else
- {
- Configuration.SetUpgrade(false);
- }
- String = $"{Major}.{Minor}.{Patch}";
- }
- }
- public static string String { get; protected set; }
- }
- #endregion _version_
- #region _violation_
- private class Violation
- {
- public class Settings
- {
- public bool Ban;
- public ulong Cooldown;
- public float Sensitivity;
- public bool Warn;
- public Settings(bool ban = true, ulong cooldown = 7200, float sensitivity = 0.5f, bool warn = false)
- {
- Ban = ban;
- Cooldown = cooldown;
- Sensitivity = sensitivity;
- Warn = warn;
- }
- public ulong Count(ulong min, ulong max, bool squared = false)
- {
- if(squared)
- {
- return min + (ulong)((max - min) * (1.0f - Sensitivity * Sensitivity));
- }
- else
- {
- return min + (ulong)((max - min) * (1.0f - Sensitivity));
- }
- }
- public Settings Validate(ulong max)
- {
- Configuration.Clamp(ref Cooldown, 1ul, max);
- Configuration.Clamp(ref Sensitivity, 0.0f, 1.0f);
- return this;
- }
- }
- private bool ban;
- private Key category;
- private ulong cooldown;
- private ulong count;
- private TimeSpan rate;
- private bool warn;
- private Dictionary<ulong, History> histories;
- private static readonly Dictionary<string, Key> categories = new Dictionary<string, Key>();
- private static ActionQueue triggers;
- private static readonly Violation violation = new Violation(Key.NULL);
- private class History
- {
- public DateTime cooldown;
- public ulong count;
- public DateTime time;
- public DateTime warned;
- public ulong warnings;
- public History()
- {
- cooldown = DateTime.MinValue;
- count = 0;
- time = DateTime.MinValue;
- warned = DateTime.MinValue;
- warnings = 0;
- }
- }
- public Violation(Key category)
- {
- this.category = category;
- }
- private void Broadcast(ulong userid, Key action, Key type, string details, Dictionary<string, string> hook_details)
- {
- if((action == Key.Warning) && IsFlooding(userid))
- {
- return;
- }
- var actionname = Text.GetPlain(action);
- var categoryname = Text.GetPlain(category);
- var playerid = userid.ToString();
- var playername = Text.Sanitize(User.Name(userid));
- var typename = Text.GetPlain(type);
- var parameters = new Dictionary<string, string>
- {
- { "action", actionname },
- { "category", categoryname },
- { "details", details },
- { "playerid", playerid },
- { "playername", playername },
- { "type", typename }
- };
- Chat.Admin(Key.Violation, parameters);
- switch(category)
- {
- case Key.AntiCheat: parameters["color"] = 0xff6060.ToString(); parameters["categoryicon"] = ":shield:"; break;
- case Key.AntiFlood: parameters["color"] = 0xffff60.ToString(); parameters["categoryicon"] = ":stopwatch:"; break;
- case Key.IP: parameters["color"] = 0x00c0ff.ToString(); parameters["categoryicon"] = ":signal_strength:"; break;
- case Key.Steam: parameters["color"] = 0xc0c0ff.ToString(); parameters["categoryicon"] = ":gear:"; break;
- case Key.VPN: parameters["color"] = 0x00c0ff.ToString(); parameters["categoryicon"] = ":signal_strength:"; break;
- default: parameters["color"] = 0x60ff60.ToString(); parameters["categoryicon"] = ":question:"; break;
- }
- switch(action)
- {
- case Key.Banned: parameters["actionicon"] = ":no_entry:"; break;
- case Key.Kicked: parameters["actionicon"] = ":x:"; break;
- case Key.Warning: parameters["actionicon"] = ":warning:"; break;
- }
- Interface.CallHook("OnGuardianViolation", playerid, parameters);
- if(category == Key.AntiCheat)
- {
- Interface.CallHook("OnGuardian" + Enum.GetName(typeof(Key), type), playerid, hook_details);
- }
- }
- public static Key Category(string category)
- {
- Key key;
- if(string.IsNullOrEmpty(category) || !categories.TryGetValue(category, out key))
- {
- key = Key.NULL;
- }
- return key;
- }
- public static void Configure()
- {
- var settings = config.Violation.Validate(86400);
- violation.ban = settings.Ban;
- violation.cooldown = settings.Cooldown;
- violation.count = settings.Count(2, 6);
- violation.rate = TimeSpan.FromHours(1);
- violation.warn = settings.Warn;
- violation.histories = new Dictionary<ulong, History>();
- }
- public void Configure(Settings settings, ulong trigger_min, ulong trigger_max, ulong trigger_rate)
- {
- ban = settings.Ban;
- cooldown = settings.Cooldown;
- count = settings.Count(trigger_min, trigger_max);
- rate = TimeSpan.FromMilliseconds(trigger_rate);
- warn = settings.Warn;
- histories = new Dictionary<ulong, History>();
- }
- public ulong Cooldown(ulong userid)
- {
- var history = Get(userid);
- var time = DateTime.UtcNow;
- if(history.cooldown > time)
- {
- return (ulong)history.cooldown.Subtract(time).TotalSeconds + 1ul;
- }
- return 0;
- }
- public void Clear()
- {
- histories.Clear();
- histories = null;
- }
- private History Get(ulong userid)
- {
- History history;
- if(!histories.TryGetValue(userid, out history))
- {
- histories.Add(userid, history = new History());
- }
- return history;
- }
- private bool IsFlooding(ulong userid)
- {
- var current = DateTime.UtcNow;
- var history = Get(userid);
- if(history.warnings > 6)
- {
- if(current < history.warned)
- {
- return true;
- }
- else
- {
- history.warnings = 0;
- }
- }
- else
- {
- history.warnings++;
- }
- history.warned = current.AddSeconds(60.0);
- return false;
- }
- public static void Load()
- {
- Configure();
- categories.Add(Text.GetPlain(Key.AntiCheat), Key.AntiCheat);
- categories.Add(Text.GetPlain(Key.AntiFlood), Key.AntiFlood);
- categories.Add(Text.GetPlain(Key.IP), Key.IP);
- categories.Add(Text.GetPlain(Key.Steam), Key.Steam);
- categories.Add(Text.GetPlain(Key.VPN), Key.VPN);
- triggers = new ActionQueue(1.0f);
- }
- private void Reduce(ulong userid)
- {
- Get(userid).count >>= 1;
- }
- private void Reset(ulong userid)
- {
- histories.Remove(userid);
- }
- public bool Trigger(ulong userid)
- {
- var history = Get(userid);
- var time = DateTime.UtcNow;
- var sent = history.time; history.time = time;
- var elapsed = time.Subtract(sent);
- if(elapsed <= rate)
- {
- if(++history.count >= count)
- {
- if(history.cooldown < time)
- {
- history.cooldown = time.AddSeconds(cooldown);
- }
- return true;
- }
- }
- else
- {
- if(elapsed.TotalSeconds < cooldown)
- {
- history.count -= (history.count > 0ul) ? 1ul : 0ul;
- }
- else
- {
- history.count = 0;
- }
- }
- if(history.cooldown > time)
- {
- return true;
- }
- return false;
- }
- public void Trigger(ulong userid, Key type, string details, bool kick = false, Dictionary<string, string> hook_details = null)
- {
- Trigger(userid, type, details, 1ul, kick, hook_details);
- }
- public void Trigger(ulong userid, Key type, string details, ulong violations, bool kick = false, Dictionary<string, string> hook_details = null)
- {
- User.SetViolationPosition(userid);
- triggers.Enqueue(() => Triggered(userid, type, details, violations, kick, hook_details));
- }
- private void Triggered(ulong userid, Key type, string details, ulong violations, bool kick, Dictionary<string, string> hook_details)
- {
- if(User.IsBanned(userid))
- {
- return;
- }
- Key action;
- if(config.Admin.Bypass && Permissions.Admin(userid))
- {
- Reduce(userid);
- action = Key.Warning;
- }
- else
- {
- bool triggered = false;
- if(violation.ban && ban)
- {
- while(violations-- > 0)
- {
- if(triggered = violation.Trigger(userid))
- {
- break;
- }
- }
- }
- if(triggered)
- {
- Reset(userid);
- action = Key.Banned;
- User.Ban(userid, $"{Text.GetPlain(category)}: {Text.GetPlain(type)}");
- violation.Reset(userid);
- }
- else
- {
- if(!kick && (ban || (!ban && warn) || violation.warn))
- {
- action = Key.Warning;
- }
- else if(!User.IsConnected(userid))
- {
- return;
- }
- else
- {
- action = Key.Kicked;
- User.Kick(userid, $"{Text.GetPlain(category)}: {Text.GetPlain(type)}");
- }
- Reduce(userid);
- }
- }
- Broadcast(userid, action, type, details, hook_details);
- }
- public static void Unload()
- {
- categories.Clear();
- triggers.Clear();
- triggers = null;
- violation.Clear();
- }
- public void Warning(ulong userid, Key type, string details, Dictionary<string, string> hook_details = null)
- {
- triggers.Enqueue(() => Broadcast(userid, Key.Warning, type, details, hook_details));
- }
- public void Zero(ulong userid)
- {
- var history = Get(userid);
- history.cooldown = DateTime.MinValue;
- history.count = 0;
- history.time = DateTime.MinValue;
- }
- }
- #endregion _violation_
- #region _vpn_
- private class VPN
- {
- public class Settings
- {
- public VpnApi API;
- public VpnCache Cache;
- public VpnCheck Check;
- public VpnViolation Violation;
- public Settings()
- {
- API = new VpnApi();
- Cache = new VpnCache();
- Check = new VpnCheck();
- Violation = new VpnViolation();
- }
- public class VpnApi
- {
- public Guardian.API.Settings GetIpIntel;
- public Guardian.API.Settings IpApi;
- public Guardian.API.Settings IpHub;
- public Guardian.API.Settings IpQualityScore;
- public VpnApi()
- {
- GetIpIntel = new Guardian.API.Settings();
- IpApi = new Guardian.API.Settings();
- IpHub = new Guardian.API.Settings();
- IpQualityScore = new Guardian.API.Settings();
- }
- public void Validate()
- {
- Configuration.Validate(ref GetIpIntel, () => new Guardian.API.Settings(), () => GetIpIntel.Validate());
- Configuration.Validate(ref IpApi, () => new Guardian.API.Settings(), () => IpApi.Validate());
- Configuration.Validate(ref IpHub, () => new Guardian.API.Settings(), () => IpHub.Validate());
- Configuration.Validate(ref IpQualityScore, () => new Guardian.API.Settings(), () => IpQualityScore.Validate());
- }
- }
- public class VpnCache
- {
- public ulong Hours;
- public VpnCache()
- {
- Hours = 72ul;
- }
- }
- public class VpnCheck
- {
- public bool Enabled;
- public bool Strict;
- }
- public class VpnViolation
- {
- public bool Ban;
- public bool Enabled;
- public bool Warn;
- public VpnViolation()
- {
- Ban = false;
- Enabled = true;
- Warn = false;
- }
- }
- public void Validate()
- {
- Configuration.Validate(ref API, () => new VpnApi(), () => API.Validate());
- Configuration.Validate(ref Cache, () => new VpnCache());
- Configuration.Validate(ref Check, () => new VpnCheck());
- Configuration.Validate(ref Violation, () => new VpnViolation());
- }
- }
- private static ActionQueue checks;
- private static readonly Violation violation = new Violation(Key.VPN);
- public class API
- {
- public class GetIpIntel
- {
- [JsonProperty("message")]
- public string Message { get; set; }
- [JsonProperty("result")]
- public float Result { get; set; }
- [JsonProperty("status")]
- public string Status { get; set; }
- private const string api = "getipintel.net";
- public static void Check(string address, ulong userid)
- {
- if(string.IsNullOrEmpty(config.VPN.API.GetIpIntel.ApiKey))
- {
- Log.Console(Key.LogVpnCheckConfig, new Dictionary<string, string>
- {
- { "api", api },
- { "link", $"http://getipintel.net/" }
- });
- return;
- }
- var url = $"http://check.getipintel.net/check.php?ip={address}&contact={config.VPN.API.GetIpIntel.ApiKey}&format=json";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<GetIpIntel>(reply);
- if(string.IsNullOrEmpty(response.Status) || response.Status != "success")
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", response.Message },
- { "type", "STATUS" }
- });
- return;
- }
- if(config.Log.VPN.Check)
- {
- Log.Console(Key.LogVpnCheck, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"result={response.Result}" },
- });
- }
- if(response.Result > 0.99)
- {
- Violation(address, userid, api);
- }
- else if(config.VPN.Check.Strict && (response.Result > 0.95))
- {
- Violation(address, userid, api);
- }
- }
- catch
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", reply },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- public class IpApi
- {
- [JsonProperty("hosting")]
- public bool Hosting { get; set; }
- [JsonProperty("proxy")]
- public bool Proxy { get; set; }
- [JsonProperty("status")]
- public string Status { get; set; }
- private const string api = "ip-api.com";
- public static void Check(string address, ulong userid)
- {
- var url = $"http://ip-api.com/json/{address}?fields=status,proxy,hosting";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<IpApi>(reply);
- if(string.IsNullOrEmpty(response.Status) || response.Status != "success")
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", response.Status },
- { "type", "STATUS" }
- });
- return;
- }
- if(config.Log.VPN.Check)
- {
- Log.Console(Key.LogVpnCheck, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"hosting={response.Hosting}; proxy={response.Proxy}" },
- });
- }
- if(response.Proxy)
- {
- Violation(address, userid, api);
- }
- else if(config.VPN.Check.Strict && response.Hosting)
- {
- Violation(address, userid, api);
- }
- }
- catch
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", reply },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- public class IpHub
- {
- [JsonProperty("block")]
- public int Block { get; set; }
- [JsonIgnore]
- private static readonly Dictionary<string, string> headers = new Dictionary<string, string>();
- private const string api = "iphub.info";
- public static void Check(string address, ulong userid)
- {
- if(string.IsNullOrEmpty(config.VPN.API.IpHub.ApiKey))
- {
- Log.Console(Key.LogVpnCheckConfig, new Dictionary<string, string>
- {
- { "api", api },
- { "link", $"http://iphub.info/" }
- });
- return;
- }
- var url = $"http://v2.api.iphub.info/ip/{address}";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<IpHub>(reply);
- if(config.Log.VPN.Check)
- {
- Log.Console(Key.LogVpnCheck, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"block={response.Block}" },
- });
- }
- if(response.Block == 1)
- {
- Violation(address, userid, api);
- }
- else if(config.VPN.Check.Strict && (response.Block == 2))
- {
- Violation(address, userid, api);
- }
- }
- catch
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", reply },
- { "type", "JSON" }
- });
- }
- }, _instance, RequestMethod.GET, headers);
- }
- public static void Configure()
- {
- headers["X-Key"] = config.VPN.API.IpHub.ApiKey;
- }
- public static void Unload() => headers.Clear();
- }
- public class IpQualityScore
- {
- [JsonProperty("fraud_score")]
- public int FraudScore { get; set; }
- [JsonProperty("message")]
- public string Message { get; set; }
- [JsonProperty("proxy")]
- public bool Proxy { get; set; }
- [JsonProperty("recent_abuse")]
- public bool RecentAbuse { get; set; }
- [JsonProperty("success")]
- public bool Success { get; set; }
- [JsonProperty("vpn")]
- public bool VPN { get; set; }
- private const string api = "ipqualityscore.com";
- public static void Check(string address, ulong userid)
- {
- if(string.IsNullOrEmpty(config.VPN.API.IpQualityScore.ApiKey))
- {
- Log.Console(Key.LogVpnCheckConfig, new Dictionary<string, string>
- {
- { "api", api },
- { "link", $"http://ipqualityscore.com/" }
- });
- return;
- }
- var url = $"https://ipqualityscore.com/api/json/ip/{config.VPN.API.IpQualityScore.ApiKey}/{address}?allow_public_access_points=true&lighter_penalties=true&mobile=true&strictness=1";
- _instance.webrequest.Enqueue(url, string.Empty, (code, reply) =>
- {
- if(code != 200 || string.IsNullOrEmpty(reply))
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"({code}: {reply})" },
- { "type", "HTTP" }
- });
- return;
- }
- try
- {
- var response = JsonConvert.DeserializeObject<IpQualityScore>(reply);
- if(!response.Success)
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", response.Message },
- { "type", "STATUS" }
- });
- return;
- }
- if(config.Log.VPN.Check)
- {
- Log.Console(Key.LogVpnCheck, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", $"fraud_score={response.FraudScore}; proxy={response.Proxy}; recent_abuse={response.RecentAbuse}; vpn={response.VPN}" },
- });
- }
- if(response.VPN || (response.FraudScore >= 85))
- {
- Violation(address, userid, api);
- }
- else if(config.VPN.Check.Strict && (response.Proxy || response.RecentAbuse || (response.FraudScore >= 75)))
- {
- Violation(address, userid, api);
- }
- }
- catch
- {
- Log.Console(Key.LogVpnCheckError, new Dictionary<string, string>
- {
- { "address", address },
- { "api", api },
- { "info", reply },
- { "type", "JSON" }
- });
- }
- }, _instance);
- }
- }
- public static void Configure() => IpHub.Configure();
- public static void Unload() => IpHub.Unload();
- }
- private class Cache
- {
- private static readonly DataFile<string, DateTime> blocks = new DataFile<string, DateTime>("vpn_blocks");
- private static readonly DataFile<string, DateTime> bypass = new DataFile<string, DateTime>("vpn_bypass");
- public static void Block(string address)
- {
- bypass.Remove(address);
- blocks[address] = DateTime.UtcNow;
- }
- public static void Bypass(string address, ulong _reserved = 0)
- {
- blocks.Remove(address);
- bypass[address] = DateTime.UtcNow;
- }
- public static bool IsBlocked(string address) => IsCached(blocks, address);
- public static bool IsBypassed(string address) => IsCached(bypass, address);
- private static bool IsCached(DataFile<string, DateTime> cache, string address)
- {
- if(cache.Contains(address))
- {
- if(IsExpired(cache[address], DateTime.UtcNow))
- {
- cache.Remove(address);
- }
- else
- {
- return true;
- }
- }
- return false;
- }
- private static bool IsExpired(DateTime timestamp, DateTime check)
- {
- if(config.VPN.Cache.Hours == 0)
- {
- return false;
- }
- if(check == DateTime.MinValue)
- {
- check = DateTime.UtcNow;
- }
- return check >= timestamp.AddHours(config.VPN.Cache.Hours);
- }
- public static void Load()
- {
- blocks.Load();
- bypass.Load();
- Update();
- }
- public static void Save()
- {
- Update();
- blocks.Save();
- bypass.Save();
- }
- public static void Unblock(string address) => blocks.Remove(address);
- public static void Unload()
- {
- Update();
- blocks.Unload();
- bypass.Unload();
- }
- private static void Update()
- {
- var current = DateTime.UtcNow;
- Update(blocks, current);
- Update(bypass, current);
- }
- private static void Update(DataFile<string, DateTime> cache, DateTime current)
- {
- List<string> expired = new List<string>();
- cache.ForEach((address, timestamp) =>
- {
- if(IsExpired(timestamp, current))
- {
- expired.Add(address);
- }
- });
- foreach(var address in expired)
- {
- cache.Remove(address);
- }
- }
- }
- public static void Bypass(string address) => Cache.Bypass(address);
- public static void Check(string address, ulong userid)
- {
- if(!config.VPN.Check.Enabled || Permissions.Bypass.Vpn(userid) || string.IsNullOrEmpty(address))
- {
- return;
- }
- else if(Cache.IsBypassed(address))
- {
- return;
- }
- else if(Cache.IsBlocked(address))
- {
- Violation(address, userid, Text.GetPlain(Key.VpnCache));
- }
- checks.Enqueue(() => Check(address, userid, 6.0f));
- }
- private static void Check(string address, ulong userid, float delay)
- {
- if(config.VPN.API.GetIpIntel.Enabled)
- {
- Check(ref delay, address, userid, API.GetIpIntel.Check);
- }
- if(config.VPN.API.IpApi.Enabled)
- {
- Check(ref delay, address, userid, API.IpApi.Check);
- }
- if(config.VPN.API.IpHub.Enabled)
- {
- Check(ref delay, address, userid, API.IpHub.Check);
- }
- if(config.VPN.API.IpQualityScore.Enabled)
- {
- Check(ref delay, address, userid, API.IpQualityScore.Check);
- }
- Check(ref delay, address, userid, Cache.Bypass);
- }
- private static void Check(ref float delay, string address, ulong userid, Action<string, ulong> callback)
- {
- _instance.timer.In(delay, () =>
- {
- if(!Cache.IsBlocked(address))
- {
- callback(address, userid);
- }
- });
- delay += 6.0f;
- }
- public static void Configure()
- {
- violation.Configure(new Violation.Settings(true, 3600, 0.5f, config.VPN.Violation.Warn), 1, 1, 1);
- API.Configure();
- }
- public static bool IsBlocked(string address) => Cache.IsBlocked(address);
- public static bool IsBypassed(string address) => Cache.IsBypassed(address);
- public static void Load()
- {
- Configure();
- Cache.Load();
- checks = new ActionQueue(6.0f);
- }
- public static void Save() => Cache.Save();
- public static void Unblock(string address) => Cache.Unblock(address);
- public static void Unload()
- {
- checks.Clear();
- checks = null;
- violation.Clear();
- API.Unload();
- Cache.Unload();
- }
- private static void Violation(string address, ulong userid, string api)
- {
- Cache.Block(address);
- if(!(config.VPN.Violation.Enabled && config.VPN.Violation.Warn))
- {
- IP.Block(address);
- }
- foreach(var entry in IP.Find(address))
- {
- if(!User.IsConnected(entry) || Permissions.Bypass.Vpn(entry))
- {
- continue;
- }
- if(config.VPN.Violation.Enabled)
- {
- ulong violations = config.VPN.Violation.Ban ? ulong.MaxValue : 1ul;
- violation.Trigger(entry, Key.Detected, $"{api}, {address}", violations, true);
- }
- else
- {
- User.Kick(entry, Text.GetPlain(Key.VpnDetected));
- }
- }
- }
- }
- #endregion _vpn_
- #region _weapon_
- private class Weapon
- {
- public float Accuracy { get; protected set; }
- public Vector3 AimAngle { get; protected set; }
- public float AimCone { get; protected set; }
- public float AimSway { get; protected set; }
- public string AmmoName { get; protected set; }
- public List<string> Attachments { get; protected set; }
- public bool Automatic { get; protected set; }
- public DateTime Fired { get; protected set; }
- public string Name { get; protected set; }
- public float Pitch { get; protected set; }
- public BasePlayer Player { get; protected set; }
- public Vector3 Position { get; protected set; }
- public List<int> Projectiles { get; protected set; }
- public float Range { get; protected set; }
- public float Repeat { get; protected set; }
- public bool Shell { get; protected set; }
- public string ShortName { get; protected set; }
- public float Speed { get; protected set; }
- public bool Spread { get; protected set; }
- public float Swing { get; protected set; }
- public float Velocity { get; protected set; }
- public float Yaw { get; protected set; }
- public float Zoom { get; protected set; }
- private static readonly Queue<Weapon> pool = new Queue<Weapon>();
- // Ammo ID's
- private static readonly int ArrowBone = ItemManager.FindItemDefinition("arrow.bone").itemid;
- private static readonly int ArrowFire = ItemManager.FindItemDefinition("arrow.fire").itemid;
- private static readonly int ArrowHV = ItemManager.FindItemDefinition("arrow.hv").itemid;
- private static readonly int ArrowWooden = ItemManager.FindItemDefinition("arrow.wooden").itemid;
- private static readonly int GrenadeHE = ItemManager.FindItemDefinition("ammo.grenadelauncher.he").itemid;
- private static readonly int GrenadeShotgun = ItemManager.FindItemDefinition("ammo.grenadelauncher.buckshot").itemid;
- private static readonly int GrenadeSmoke = ItemManager.FindItemDefinition("ammo.grenadelauncher.smoke").itemid;
- private static readonly int NailgunNails = ItemManager.FindItemDefinition("ammo.nailgun.nails").itemid;
- private static readonly int PistolBullet = ItemManager.FindItemDefinition("ammo.pistol").itemid;
- private static readonly int PistolHV = ItemManager.FindItemDefinition("ammo.pistol.hv").itemid;
- private static readonly int PistolIncendiary = ItemManager.FindItemDefinition("ammo.pistol.fire").itemid;
- private static readonly int RifleAmmo = ItemManager.FindItemDefinition("ammo.rifle").itemid;
- private static readonly int RifleExplosive = ItemManager.FindItemDefinition("ammo.rifle.explosive").itemid;
- private static readonly int RifleHV = ItemManager.FindItemDefinition("ammo.rifle.hv").itemid;
- private static readonly int RifleIncendiary = ItemManager.FindItemDefinition("ammo.rifle.incendiary").itemid;
- private static readonly int Rocket = ItemManager.FindItemDefinition("ammo.rocket.basic").itemid;
- private static readonly int RocketHV = ItemManager.FindItemDefinition("ammo.rocket.hv").itemid;
- private static readonly int RocketIncendiary = ItemManager.FindItemDefinition("ammo.rocket.fire").itemid;
- private static readonly int ShellBuckshot = ItemManager.FindItemDefinition("ammo.shotgun").itemid;
- private static readonly int ShellHandmade = ItemManager.FindItemDefinition("ammo.handmade.shell").itemid;
- private static readonly int ShellIncendiary = ItemManager.FindItemDefinition("ammo.shotgun.fire").itemid;
- private static readonly int ShellSlug = ItemManager.FindItemDefinition("ammo.shotgun.slug").itemid;
- // Weapon ID's
- private static readonly int AssaultRifle = ItemManager.FindItemDefinition("rifle.ak").itemid;
- private static readonly int BoltActionRifle = ItemManager.FindItemDefinition("rifle.bolt").itemid;
- private static readonly int CompoundBow = ItemManager.FindItemDefinition("bow.compound").itemid;
- private static readonly int Crossbow = ItemManager.FindItemDefinition("crossbow").itemid;
- private static readonly int CustomSMG = ItemManager.FindItemDefinition("smg.2").itemid;
- private static readonly int DoubleBarrelShotgun = ItemManager.FindItemDefinition("shotgun.double").itemid;
- private static readonly int EokaPistol = ItemManager.FindItemDefinition("pistol.eoka").itemid;
- private static readonly int HuntingBow = ItemManager.FindItemDefinition("bow.hunting").itemid;
- private static readonly int L96Rifle = ItemManager.FindItemDefinition("rifle.l96").itemid;
- private static readonly int LR300AssaultRifle = ItemManager.FindItemDefinition("rifle.lr300").itemid;
- private static readonly int M249 = ItemManager.FindItemDefinition("lmg.m249").itemid;
- private static readonly int M39Rifle = ItemManager.FindItemDefinition("rifle.m39").itemid;
- private static readonly int M92Pistol = ItemManager.FindItemDefinition("pistol.m92").itemid;
- private static readonly int MP5A4 = ItemManager.FindItemDefinition("smg.mp5").itemid;
- private static readonly int MultipleGrenadeLauncher = ItemManager.FindItemDefinition("multiplegrenadelauncher").itemid;
- private static readonly int Nailgun = ItemManager.FindItemDefinition("pistol.nailgun").itemid;
- private static readonly int PumpShotgun = ItemManager.FindItemDefinition("shotgun.pump").itemid;
- private static readonly int PythonRevolver = ItemManager.FindItemDefinition("pistol.python").itemid;
- private static readonly int Revolver = ItemManager.FindItemDefinition("pistol.revolver").itemid;
- private static readonly int RocketLauncher = ItemManager.FindItemDefinition("rocket.launcher").itemid;
- private static readonly int SemiAutomaticPistol = ItemManager.FindItemDefinition("pistol.semiauto").itemid;
- private static readonly int SemiAutomaticRifle = ItemManager.FindItemDefinition("rifle.semiauto").itemid;
- private static readonly int Spas12Shotgun = ItemManager.FindItemDefinition("shotgun.spas12").itemid;
- private static readonly int Thompson = ItemManager.FindItemDefinition("smg.thompson").itemid;
- private static readonly int WaterpipeShotgun = ItemManager.FindItemDefinition("shotgun.waterpipe").itemid;
- private class Ammo
- {
- public float AimCone { get; set; }
- public float Range { get; set; }
- public float Velocity { get; set; }
- public Ammo(float aimcone, float range, float velocity)
- {
- AimCone = aimcone; Range = range; Velocity = velocity;
- }
- }
- private class Info
- {
- public float Accuracy { get; set; }
- public Dictionary<int, Ammo> Ammo { get; set; }
- public bool Automatic { get; set; }
- public string Name { get; set; }
- public Recoil Recoil { get; set; }
- public float Repeat { get; set; }
- }
- private class Recoil
- {
- public float Pitch { get; set; }
- public float Yaw { get; set; }
- public Recoil(float pitch, float yaw)
- {
- Pitch = pitch; Yaw = yaw;
- }
- }
- private static Dictionary<int, Info> weapons;
- private Weapon()
- {
- Attachments = new List<string>();
- Projectiles = new List<int>();
- }
- private static Weapon Get()
- {
- if(pool.Count > 0)
- {
- return pool.Dequeue();
- }
- else
- {
- return new Weapon();
- }
- }
- public static Weapon Get(ulong userid, int projectileid) => Projectile.Weapon(userid, projectileid);
- public static Weapon Get(BaseProjectile weapon_fired, BasePlayer player, ProtoBuf.ProjectileShoot fired = null)
- {
- var item = weapon_fired.GetItem();
- Info info;
- if(!weapons.TryGetValue(item.info.itemid, out info))
- {
- return null;
- }
- var ammo = weapon_fired.primaryMagazine.ammoType;
- Ammo ammoinfo;
- if(!info.Ammo.TryGetValue(ammo.itemid, out ammoinfo))
- {
- return null;
- }
- var accuracy = info.Accuracy;
- var spread = (ammo.itemid == ShellBuckshot) || (ammo.itemid == ShellHandmade);
- var position = weapon_fired.MuzzlePoint?.transform?.position ?? weapon_fired.transform?.position ?? player.transform.position;
- var weapon = Get();
- weapon.Accuracy = 1.0f;
- weapon.AimAngle = player.eyes.HeadRay().direction;
- weapon.AimCone = ammoinfo.AimCone;
- weapon.AimSway = 1.0f;
- weapon.AmmoName = ammo.shortname;
- weapon.Automatic = info.Automatic;
- weapon.Fired = DateTime.UtcNow;
- weapon.Name = info.Name;
- weapon.Pitch = info.Recoil.Pitch * (info.Automatic ? 0.25f : 0.5f);
- weapon.Player = player;
- weapon.Position = position;
- weapon.Range = ammoinfo.Range;
- weapon.Repeat = info.Repeat;
- weapon.Shell = spread || (ammo.itemid == ShellIncendiary) || (ammo.itemid == ShellSlug);
- weapon.ShortName = item.info.shortname;
- weapon.Speed = player.estimatedSpeed;
- weapon.Spread = spread || (ammo.itemid == GrenadeShotgun);
- weapon.Swing = 0.0f;
- weapon.Velocity = ammoinfo.Velocity;
- weapon.Yaw = info.Recoil.Yaw * (info.Automatic ? 0.125f : 0.25f); ;
- weapon.Zoom = 1.0f;
- var aimsway = 1.0f;
- foreach(var entry in player.inventory.containerWear.itemList)
- {
- if(entry.info.itemid == -1108136649) // Tactical Gloves
- {
- aimsway = 0.2f;
- break;
- }
- }
- var aiming = player.IsAiming;
- var ducked = player.IsDucked();
- var recoil = ducked ? 0.9f : 1.0f;
- if(item?.contents?.itemList != null)
- {
- bool muzzle_brake = false;
- foreach(var mod in item.contents.itemList)
- {
- switch(mod.info.shortname)
- {
- case "weapon.mod.8x.scope":
- accuracy *= 0.85f;
- recoil -= 0.2f;
- weapon.AimCone *= 0.7f;
- weapon.Zoom = aiming ? 16.0f : 1.0f;
- break;
- case "weapon.mod.small.scope":
- accuracy *= 0.85f;
- recoil -= 0.2f;
- weapon.AimCone *= 0.7f;
- weapon.Zoom = aiming ? 8.0f : 1.0f;
- break;
- case "weapon.mod.holosight":
- accuracy *= 0.3f;
- weapon.AimCone *= 0.3f;
- weapon.Zoom = aiming ? 2.0f : 1.0f;
- break;
- case "weapon.mod.muzzleboost":
- weapon.Range *= 0.9f;
- weapon.Repeat *= 0.9f;
- weapon.Velocity *= 0.9f;
- break;
- case "weapon.mod.muzzlebrake":
- accuracy *= 1.38f;
- muzzle_brake = true;
- recoil -= 0.5f;
- break;
- case "weapon.mod.silencer":
- accuracy *= 0.67f;
- aimsway -= 0.2f;
- recoil -= 0.2f;
- weapon.AimCone *= 0.7f;
- break;
- case "weapon.mod.simplesight":
- weapon.Zoom = aiming ? 0.5f : 1.0f;
- break;
- case "weapon.mod.lasersight":
- accuracy *= 0.56f;
- aimsway -= 0.9f;
- weapon.AimCone *= aiming ? 0.8f : 0.6f;
- break;
- }
- weapon.Attachments.Add(mod.info.shortname);
- }
- if(muzzle_brake)
- {
- weapon.AimCone += aiming ? 0.5f : 2.0f;
- }
- }
- weapon.Accuracy -= accuracy;
- weapon.AimSway *= (aimsway > 0.0f) ? aimsway : 0.0f;
- weapon.Pitch *= recoil;
- weapon.Yaw *= recoil;
- if((fired?.projectiles?.Count ?? 0) > 0)
- {
- foreach(var projectile in fired.projectiles)
- {
- weapon.Projectiles.Add(projectile.projectileID);
- }
- Projectile.Add(weapon);
- }
- return weapon;
- }
- public static bool IsValid(Item item) => weapons.ContainsKey(item?.info?.itemid ?? 0);
- public static void Load()
- {
- weapons = new Dictionary<int, Info>
- {
- [AssaultRifle] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.2f, 187.5f, 375.0f) },
- { RifleExplosive, new Ammo(0.5f, 112.5f, 225.0f) },
- { RifleHV, new Ammo(0.2f, 225.0f, 450.0f) },
- { RifleIncendiary, new Ammo(0.2f, 112.5f, 225.0f) }
- },
- Automatic = true,
- Name = "Assault Rifle",
- Recoil = new Recoil(13.000000f, 5.000000f),
- Repeat = 0.1333f
- },
- [BoltActionRifle] = new Info
- {
- Accuracy = 0.02f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.0f, 328.0f, 656.0f) },
- { RifleExplosive, new Ammo(0.5f, 197.0f, 394.0f) },
- { RifleHV, new Ammo(0.0f, 394.0f, 788.0f) },
- { RifleIncendiary, new Ammo(0.0f, 197.0f, 394.0f) }
- },
- Automatic = false,
- Name = "Bolt Action Rifle",
- Recoil = new Recoil(0.500000f, 4.000000f),
- Repeat = 1.7f
- },
- [CompoundBow] = new Info
- {
- Accuracy = 0.00f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ArrowBone, new Ammo(0.2f, 270.0f, 90.0f) },
- { ArrowFire, new Ammo(0.2f, 240.0f, 80.0f) },
- { ArrowHV, new Ammo(0.2f, 480.0f, 160.0f) },
- { ArrowWooden, new Ammo(0.2f, 300.0f, 100.0f) }
- },
- Automatic = false,
- Name = "Compound Bow",
- Recoil = new Recoil(1.500000f, 3.000000f),
- Repeat = 1.25f
- },
- [Crossbow] = new Info
- {
- Accuracy = 0.03f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ArrowBone, new Ammo(1.0f, 202.5f, 67.5f) },
- { ArrowFire, new Ammo(1.0f, 180.0f, 60.0f) },
- { ArrowHV, new Ammo(1.0f, 360.0f, 120.0f) },
- { ArrowWooden, new Ammo(1.0f, 225.0f, 75.0f) }
- },
- Automatic = false,
- Name = "Crossbow",
- Recoil = new Recoil(1.500000f, 3.000000f),
- Repeat = 1.0f
- },
- [CustomSMG] = new Info
- {
- Accuracy = 0.03f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.5f, 200.0f, 240.0f) },
- { PistolHV, new Ammo(0.5f, 266.7f, 320.0f) },
- { PistolIncendiary, new Ammo(0.5f, 150.0f, 180.0f) }
- },
- Automatic = true,
- Name = "Custom SMG",
- Recoil = new Recoil(6.500000f, 5.7500000f),
- Repeat = 0.1f
- },
- [DoubleBarrelShotgun] = new Info
- {
- Accuracy = 0.15f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ShellBuckshot, new Ammo(12.5f, 45.0f, 225.0f) },
- { ShellHandmade, new Ammo(12.5f, 30.0f, 100.0f) },
- { ShellIncendiary, new Ammo(12.5f, 25.0f, 100.0f) },
- { ShellSlug, new Ammo( 0.5f, 60.0f, 225.0f) }
- },
- Automatic = false,
- Name = "Double Barrel Shotgun",
- Recoil = new Recoil(2.500000f, 3.500000f),
- Repeat = 0.5f
- },
- [EokaPistol] = new Info
- {
- Accuracy = 0.17f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ShellBuckshot, new Ammo(14.0f, 45.0f, 225.0f) },
- { ShellHandmade, new Ammo(14.0f, 30.0f, 100.0f) },
- { ShellIncendiary, new Ammo(14.0f, 25.0f, 100.0f) },
- { ShellSlug, new Ammo( 2.0f, 60.0f, 225.0f) }
- },
- Automatic = false,
- Name = "Eoka Pistol",
- Recoil = new Recoil(15.00000f, 10.00000f),
- Repeat = 1.5f
- },
- [HuntingBow] = new Info
- {
- Accuracy = 0.02f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ArrowBone, new Ammo(1.0f, 135.0f, 45.0f) },
- { ArrowFire, new Ammo(1.0f, 120.0f, 40.0f) },
- { ArrowHV, new Ammo(1.0f, 240.0f, 80.0f) },
- { ArrowWooden, new Ammo(1.0f, 150.0f, 50.0f) }
- },
- Automatic = false,
- Name = "Hunting Bow",
- Recoil = new Recoil(1.500000f, 3.000000f),
- Repeat = 1.25f
- },
- [L96Rifle] = new Info
- {
- Accuracy = 0.02f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.0f, 562.5f, 1125.0f) },
- { RifleExplosive, new Ammo(0.5f, 337.5f, 675.0f) },
- { RifleHV, new Ammo(0.0f, 675.0f, 1350.0f) },
- { RifleIncendiary, new Ammo(0.0f, 337.5f, 675.0f) }
- },
- Automatic = false,
- Name = "L96 Rifle",
- Recoil = new Recoil(0.250000f, 2.000000f),
- Repeat = 2.6f
- },
- [LR300AssaultRifle] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.2f, 187.5f, 375.0f) },
- { RifleExplosive, new Ammo(0.7f, 112.5f, 225.0f) },
- { RifleHV, new Ammo(0.2f, 225.0f, 450.0f) },
- { RifleIncendiary, new Ammo(0.2f, 112.5f, 225.0f) }
- },
- Automatic = true,
- Name = "LR-300 Assault Rifle",
- Recoil = new Recoil(4.750000f, 3.000000f),
- Repeat = 0.12f
- },
- [M249] = new Info
- {
- Accuracy = 0.07f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.2f, 243.75f, 487.5f) },
- { RifleExplosive, new Ammo(0.7f, 146.25f, 292.5f) },
- { RifleHV, new Ammo(0.2f, 292.50f, 585.0f) },
- { RifleIncendiary, new Ammo(0.2f, 146.25f, 292.5f) }
- },
- Automatic = true,
- Name = "M249",
- Recoil = new Recoil(0.500000f, 1.000000f),
- Repeat = 0.12f
- },
- [M39Rifle] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.1f, 234.375f, 468.75f) },
- { RifleExplosive, new Ammo(0.6f, 140.625f, 281.25f) },
- { RifleHV, new Ammo(0.1f, 281.250f, 562.50f) },
- { RifleIncendiary, new Ammo(0.1f, 140.625f, 281.25f) }
- },
- Automatic = false,
- Name = "M39 Rifle",
- Recoil = new Recoil(1.000000f, 1.500000f),
- Repeat = 0.2f
- },
- [M92Pistol] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(1.0f, 90.0f, 300.0f) },
- { PistolHV, new Ammo(1.0f, 120.0f, 400.0f) },
- { PistolIncendiary, new Ammo(1.0f, 67.5f, 225.0f) }
- },
- Automatic = false,
- Name = "M92 Pistol",
- Recoil = new Recoil(0.500000f, 1.000000f),
- Repeat = 0.15f
- },
- [MP5A4] = new Info
- {
- Accuracy = 0.05f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.5f, 200.0f, 240.0f) },
- { PistolHV, new Ammo(0.5f, 266.7f, 320.0f) },
- { PistolIncendiary, new Ammo(0.5f, 150.0f, 180.0f) }
- },
- Automatic = true,
- Name = "MP5A4",
- Recoil = new Recoil(4.000000f, 3.625000f),
- Repeat = 0.1f
- },
- [MultipleGrenadeLauncher] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { GrenadeHE, new Ammo( 2.25f, 100.0f, 100.0f) },
- { GrenadeShotgun, new Ammo(17.25f, 225.0f, 225.0f) },
- { GrenadeSmoke, new Ammo( 2.25f, 100.0f, 100.0f) }
- },
- Automatic = false,
- Name = "Multiple Grenade Launcher",
- Recoil = new Recoil(2.500000f, 2.500000f),
- Repeat = 0.4f
- },
- [Nailgun] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { NailgunNails, new Ammo(0.75f, 25.0f, 50.0f) }
- },
- Automatic = false,
- Name = "Nailgun",
- Recoil = new Recoil(1.500000f, 1.000000f),
- Repeat = 0.15f
- },
- [PumpShotgun] = new Info
- {
- Accuracy = 0.14f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ShellBuckshot, new Ammo(12.0f, 101.25f, 225.0f) },
- { ShellHandmade, new Ammo(12.0f, 60.00f, 100.0f) },
- { ShellIncendiary, new Ammo(12.0f, 45.00f, 100.0f) },
- { ShellSlug, new Ammo( 0.0f, 135.00f, 225.0f) }
- },
- Automatic = false,
- Name = "Pump Shotgun",
- Recoil = new Recoil(2.000000f, 2.000000f),
- Repeat = 1.1f
- },
- [PythonRevolver] = new Info
- {
- Accuracy = 0.06f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.5f, 72.0f, 300.0f) },
- { PistolHV, new Ammo(0.5f, 96.0f, 400.0f) },
- { PistolIncendiary, new Ammo(0.5f, 54.0f, 225.0f) }
- },
- Automatic = false,
- Name = "Python Revolver",
- Recoil = new Recoil(0.500000f, 2.000000f),
- Repeat = 0.15f
- },
- [Revolver] = new Info
- {
- Accuracy = 0.05f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.75f, 54.0f, 300.0f) },
- { PistolHV, new Ammo(0.75f, 72.0f, 400.0f) },
- { PistolIncendiary, new Ammo(0.75f, 40.5f, 225.0f) }
- },
- Automatic = false,
- Name = "Revolver",
- Recoil = new Recoil(1.500000f, 1.000000f),
- Repeat = 0.175f
- },
- [RocketLauncher] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { Rocket, new Ammo(2.25f, 250.0f, 18.0f) },
- { RocketHV, new Ammo(2.25f, 400.0f, 40.0f) },
- { RocketIncendiary, new Ammo(2.25f, 250.0f, 18.0f) }
- },
- Automatic = false,
- Name = "Rocket Launcher",
- Recoil = new Recoil(2.500000f, 2.500000f),
- Repeat = 2.0f
- },
- [SemiAutomaticPistol] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.75f, 54.0f, 300.0f) },
- { PistolHV, new Ammo(0.75f, 72.0f, 400.0f) },
- { PistolIncendiary, new Ammo(0.75f, 40.5f, 225.0f) }
- },
- Automatic = false,
- Name = "Semi-Automatic Pistol",
- Recoil = new Recoil(1.000000f, 2.000000f),
- Repeat = 0.15f
- },
- [SemiAutomaticRifle] = new Info
- {
- Accuracy = 0.04f,
- Ammo = new Dictionary<int, Ammo>
- {
- { RifleAmmo, new Ammo(0.25f, 187.5f, 375.0f) },
- { RifleExplosive, new Ammo(0.75f, 112.5f, 225.0f) },
- { RifleHV, new Ammo(0.25f, 225.0f, 450.0f) },
- { RifleIncendiary, new Ammo(0.25f, 112.5f, 225.0f) }
- },
- Automatic = false,
- Name = "Semi-Automatic Rifle",
- Recoil = new Recoil(0.500000f, 1.000000f),
- Repeat = 0.175f
- },
- [Spas12Shotgun] = new Info
- {
- Accuracy = 0.14f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ShellBuckshot, new Ammo(12.0f, 101.25f, 225.0f) },
- { ShellHandmade, new Ammo(12.0f, 60.00f, 100.0f) },
- { ShellIncendiary, new Ammo(12.0f, 45.00f, 100.0f) },
- { ShellSlug, new Ammo( 0.0f, 135.00f, 225.0f) }
- },
- Automatic = false,
- Name = "Spas-12 Shotgun",
- Recoil = new Recoil(2.000000f, 2.000000f),
- Repeat = 0.25f
- },
- [Thompson] = new Info
- {
- Accuracy = 0.03f,
- Ammo = new Dictionary<int, Ammo>
- {
- { PistolBullet, new Ammo(0.5f, 250.0f, 300.0f) },
- { PistolHV, new Ammo(0.5f, 333.3f, 400.0f) },
- { PistolIncendiary, new Ammo(0.5f, 187.5f, 225.0f) }
- },
- Automatic = true,
- Name = "Thompson",
- Recoil = new Recoil(6.500000f, 5.750000f),
- Repeat = 0.13f
- },
- [WaterpipeShotgun] = new Info
- {
- Accuracy = 0.15f,
- Ammo = new Dictionary<int, Ammo>
- {
- { ShellBuckshot, new Ammo(13.0f, 45.0f, 225.0f) },
- { ShellHandmade, new Ammo(13.0f, 30.0f, 100.0f) },
- { ShellIncendiary, new Ammo(13.0f, 25.0f, 100.0f) },
- { ShellSlug, new Ammo( 1.0f, 60.0f, 225.0f) }
- },
- Automatic = false,
- Name = "Waterpipe Shotgun",
- Recoil = new Recoil(2.000000f, 2.000000f),
- Repeat = 2.0f
- }
- };
- }
- public void Release()
- {
- Attachments.Clear();
- Projectiles.Clear();
- pool.Enqueue(this);
- }
- public void SetSwing(float amount)
- {
- Swing = amount;
- }
- public static void Unload()
- {
- pool.Clear();
- weapons.Clear();
- weapons = null;
- }
- }
- #endregion _weapon_
- #region _webhook_
- private class WebHook
- {
- public static void Send(string url, string category, string message)
- {
- if(string.IsNullOrEmpty(url) || string.IsNullOrEmpty(message))
- {
- return;
- }
- if(string.IsNullOrWhiteSpace(category))
- {
- category = Text.GetPlain(Key.unknown);
- }
- _instance.webrequest.Enqueue(url, message, (code, reply) =>
- {
- if((code < 200) || (204 < code))
- {
- Log.Console(Key.LogWebHook, new Dictionary<string, string>
- {
- { "category", category },
- { "info", $"({code}: {reply})" },
- { "type", "http" }
- });
- }
- }, _instance, RequestMethod.POST, new Dictionary<string, string> { { "Content-Type", "application/json" } });
- }
- }
- #endregion _webhook_
- }
- }
Add Comment
Please, Sign In to add comment