C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using UnityEngine;
using Facepunch;
namespace Oxide.Plugins
{
[Info("DropCleaner", "Crunchy", "1.1.7")]
[Description("Cleans dropped items off the server.")]
public class DropCleaner : RustPlugin
{
private class Config
{
public float IntervalSeconds = 600f;
public bool ShowWarnings = true;
public List<int> WarnAtSeconds;
public List<string> KeepShortnames;
}
private Config config;
private Timer loop;
private readonly List<Timer> warnTimers = new List<Timer>(8);
private HashSet<string> keep;
protected override void LoadDefaultConfig()
{
config = new Config
{
IntervalSeconds = 600f,
ShowWarnings = true,
WarnAtSeconds = new List<int> { 30, 15, 10, 5 },
KeepShortnames = new List<string> { "fish.anchovy" }
};
SaveConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = base.Config.ReadObject<DropCleaner.Config>();
if (config == null) throw new Exception();
}
catch
{
LoadDefaultConfig();
return;
}
if (config.WarnAtSeconds == null) config.WarnAtSeconds = new List<int> { 30, 15, 10, 5 };
if (config.KeepShortnames == null) config.KeepShortnames = new List<string>();
config.WarnAtSeconds = config.WarnAtSeconds.Distinct().ToList();
SaveConfig();
BuildKeep();
}
protected override void SaveConfig()
{
base.Config.WriteObject((DropCleaner.Config)config, true);
}
private void BuildKeep()
{
if (config.KeepShortnames != null && config.KeepShortnames.Count > 0)
keep = new HashSet<string>(config.KeepShortnames, StringComparer.OrdinalIgnoreCase);
else
keep = null;
}
private void OnServerInitialized()
{
StartLoop();
}
private void Unload()
{
StopLoop();
}
private void StartLoop()
{
StopLoop();
float interval = Mathf.Max(10f, config.IntervalSeconds);
if (config.ShowWarnings && config.WarnAtSeconds != null)
{
var seen = new HashSet<int>();
for (int i = 0; i < config.WarnAtSeconds.Count; i++)
{
int s = config.WarnAtSeconds[i];
if (s <= 0 || s >= interval) continue;
if (!seen.Add(s)) continue;
int seconds = s;
warnTimers.Add(timer.Once(interval - seconds, () =>
{
Broadcast($"Dropped items will be removed in {seconds} seconds.");
}));
}
}
loop = timer.Once(interval, () =>
{
Clean();
Broadcast("All dropped items have been cleared.");
StartLoop();
});
}
private void StopLoop()
{
loop?.Destroy();
loop = null;
for (int i = 0; i < warnTimers.Count; i++)
warnTimers[i]?.Destroy();
warnTimers.Clear();
}
private void Broadcast(string message)
{
var list = BasePlayer.activePlayerList;
for (int i = 0; i < list.Count; i++)
{
var p = list[i];
if (p != null && p.IsConnected) p.ChatMessage(message);
}
}
private void Clean()
{
var toKill = new List<BaseEntity>();
try
{
foreach (var n in BaseNetworkable.serverEntities)
{
var di = n as DroppedItem;
if (di == null || di.IsDestroyed) continue;
var info = di.item?.info;
if (keep != null && info != null && !string.IsNullOrEmpty(info.shortname) && keep.Contains(info.shortname))
continue;
toKill.Add(di);
}
for (int i = 0; i < toKill.Count; i++)
{
var e = toKill[i];
if (e != null && !e.IsDestroyed) e.Kill();
}
}
finally
{
toKill.Clear();
}
}
}
}