C#:
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine; // for Time
namespace Carbon.Plugins
{
[PluginInfo("AutoBanFree", "Gregory", "1.2.0")]
[Description("Basic version of AutoBan for Rust. Bans players based on reports with optional ban durations.")]
public class AutoBanFree : CarbonPlugin
{
private class Report
{
public string ReporterId;
public string TargetId;
public string Reason;
public double Time;
}
private Dictionary<string, List<Report>> reports = new();
private HashSet<string> bannedPlayers = new();
private int MaxReportsToBan = 3; // Max number of reports before banning
private List<string> ValidReasons = new List<string> { "cheating", "hacks", "aimbot", "hacking", "esp" }; // Predefined reasons
private string BanDuration = "72h"; // Default ban time (supports m = minutes, h = hours, d = days, w = weeks, permanent)
#region Plugin Lifecycle
protected override void Init()
{
permission.RegisterPermission("AutoBanFree.report", this);
permission.RegisterPermission("AutoBanFree.ban", this);
permission.RegisterPermission("AutoBanFree.viewreports", this);
permission.RegisterPermission("AutoBanFree.unban", this);
Puts("AutoBan-Free initialized and permissions registered.");
}
#endregion
#region Report Handling
[Command("AB.report")]
private void OnReportCommand(CarbonPlayer reporter, string cmd, string[] args)
{
if (args.Length < 2)
{
reporter.SendChatMessage("Usage: /AB.report <targetId> <reason>");
return;
}
string targetId = args[0];
string reason = string.Join(" ", args.Skip(1));
// Check if reason is valid
if (!ValidReasons.Contains(reason.ToLower()))
{
reporter.SendChatMessage($"Invalid report reason. Valid reasons: {string.Join(", ", ValidReasons)}");
return;
}
var report = new Report
{
ReporterId = reporter.Id,
TargetId = targetId,
Reason = reason,
Time = Time.realtimeSinceStartup
};
if (!reports.ContainsKey(targetId))
reports[targetId] = new List<Report>();
reports[targetId].Add(report);
Puts($"[AutoBan-Free] {reporter.Name} reported {targetId} for {reason}");
CheckReports(targetId);
}
private void CheckReports(string targetId)
{
if (!reports.ContainsKey(targetId)) return;
int count = reports[targetId].Count;
if (count >= MaxReportsToBan && !bannedPlayers.Contains(targetId))
{
IssueBan(targetId, "Too many reports");
}
}
#endregion
#region Ban Handling
private void IssueBan(string targetId, string reason)
{
long seconds;
bool permanent;
if (DurationToSeconds(BanDuration, out seconds, out permanent))
{
bannedPlayers.Add(targetId);
server.Command($"ban {targetId} \"{reason}\"");
if (permanent)
{
Puts($"[AutoBan-Free] Permanently banned {targetId} for: {reason}");
}
else
{
Puts($"[AutoBan-Free] Banned {targetId} for {BanDuration} ({seconds} seconds). Reason: {reason}");
// Schedule unban after duration
timer.Once(seconds, () =>
{
if (bannedPlayers.Contains(targetId))
{
bannedPlayers.Remove(targetId);
server.Command($"unban {targetId}");
Puts($"[AutoBan-Free] Timed ban expired: {targetId}");
}
});
}
}
else
{
// fallback to permanent ban if invalid duration
bannedPlayers.Add(targetId);
server.Command($"ban {targetId} \"{reason}\"");
Puts($"[AutoBan-Free] Invalid ban duration '{BanDuration}', defaulting to permanent for {targetId}");
}
}
[Command("AB.unban")]
private void UnbanCommand(CarbonPlayer player, string cmd, string[] args)
{
if (!permission.UserHasPermission(player.Id, "AutoBanFree.unban"))
{
player.SendChatMessage("No permission to unban.");
return;
}
if (args.Length < 1)
{
player.SendChatMessage("Usage: /AB.unban <userid>");
return;
}
string targetId = args[0];
bannedPlayers.Remove(targetId);
server.Command($"unban {targetId}");
Puts($"[AutoBan-Free] {player.Name} unbanned {targetId}");
}
#endregion
#region Helper Methods
private static bool DurationToSeconds(string input, out long seconds, out bool permanent)
{
seconds = 0;
permanent = false;
if (string.IsNullOrEmpty(input)) return false;
var s = input.Trim().ToLowerInvariant();
if (s == "permanent" || s == "perm" || s == "perma" || s == "p")
{
permanent = true;
return true;
}
try
{
var numPart = new string(s.TakeWhile(char.IsDigit).ToArray());
var unit = new string(s.SkipWhile(char.IsDigit).ToArray());
if (string.IsNullOrEmpty(numPart) || string.IsNullOrEmpty(unit)) return false;
if (!long.TryParse(numPart, out var n)) return false;
switch (unit)
{
case "m": seconds = n * 60; break;
case "h": seconds = n * 3600; break;
case "d": seconds = n * 86400; break;
case "w": seconds = n * 604800; break;
default: return false;
}
return true;
}
catch { return false; }
}
#endregion
}
}