C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
TODO:
- Add options to enable/disable each container type (wear, bar, main)
- Finish implementing permissions support
- Fix GetUselessItems giving an NRE
*/
using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Game.Rust.Cui;
namespace Oxide.Plugins
{
[Info("QuickSort", "Wulf/lukespragg", "1.0.2", ResourceId = 1263)]
[Description("Adds a new GUI that allows players to quickly sort items into containers")]
class QuickSort : RustPlugin
{
// Do NOT edit this file, instead edit QuickSort.json in oxide/config and QuickSort.en.json in the oxide/lang directory,
// or create a new language file for another language using the 'en' file as a default.#region Initialization
//const string permSort = "quicksort.allowed";
void Loaded()
{
#if !RUST
throw new NotSupportedException("This plugin does not support this game");
#endif
LoadDefaultConfig();
LoadDefaultMessages();
//permission.RegisterPermission(permSort, this);
}
#endregion
#region Configuration
bool lootAllowed;
float lootDelay;
protected override void LoadDefaultConfig()
{
Config["LootAllowed"] = lootAllowed = GetConfig("LootAllowed", true);
Config["LootDelay"] = lootDelay = GetConfig("LootDelay", 0f);
SaveConfig();
}
#endregion
#region Localization
void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Deposit"] = "Deposit",
["DepositAll"] = "All",
["DepositAmmo"] = "Ammo",
["DepositAttire"] = "Attire",
["DepositConstruction"] = "Construction",
["DepositExisting"] = "Existing",
["DepositFood"] = "Food",
["DepositItems"] = "Deployables",
["DepositMedical"] = "Medical",
["DepositResources"] = "Resources",
["DepositTools"] = "Tools",
["DepositTraps"] = "Traps",
["DepositWeapons"] = "Weapons",
["LootAll"] = "Loot All"
}, this);
}
#endregion
#region Player Hooks
void OnLootPlayer(BasePlayer player) => SortUi(player);
void OnLootEntity(BasePlayer player) => SortUi(player);
#endregion
#region Stuff
[ConsoleCommand("global.quicksort")]
void AutoDeposit(ConsoleSystem.Arg arg)
{
if (arg.Player() == null) return;
var player = arg.Player();
var container = GetLootedInventory(player);
var playerMain = player.inventory.containerMain;
var playerWear = player.inventory.containerWear;
var playerBelt = player.inventory.containerBelt;
if (container == null || playerMain == null) return;
List<Item> itemsSelected;
if (arg.Args != null && arg.Args.Length == 1)
{
if (arg.Args[0].Equals("existing"))
{
itemsSelected = GetExistingItems(playerMain, container);
}
else
{
var category = StringToItemCategory(arg.Args[0]);
itemsSelected = GetItemsOfType(playerMain, category);
itemsSelected.AddRange(GetItemsOfType(playerWear, category));
itemsSelected.AddRange(GetItemsOfType(playerBelt, category));
}
}
else
{
itemsSelected = CloneItemList(playerMain.itemList);
itemsSelected.AddRange(CloneItemList(playerWear.itemList));
itemsSelected.AddRange(CloneItemList(playerBelt.itemList));
}
/*var uselessItems = GetUselessItems(itemsSelected, container);
foreach (var item in uselessItems) itemsSelected.Remove(item);
foreach (var item in itemsSelected) PrintWarning(item.info.shortname);*/
itemsSelected.Sort((item1, item2) => item2.info.itemid.CompareTo(item1.info.itemid));
MoveItems(itemsSelected, container);
}
[ConsoleCommand("quicksort.loot")]
void AutoLoot(ConsoleSystem.Arg arg)
{
if (arg.Player() == null || !lootAllowed) return;
timer.Once(lootDelay, () => DoAutoLoot(arg.Player()));
}
#region Config Commands
[ConsoleCommand("quicksort.lootallowed")]
void SetLootAllowed(ConsoleSystem.Arg arg)
{
if (!arg.isAdmin || arg.Args.Length != 1) return;
bool x;
if (!bool.TryParse(arg.Args[0], out x)) return;
lootAllowed = x;
Config["LootAllowed"] = lootAllowed;
SaveConfig();
}
[ConsoleCommand("quicksort.lootdelay")]
void SetLootDelay(ConsoleSystem.Arg arg)
{
if (!arg.isAdmin || arg.Args.Length != 1) return;
float x;
if (!float.TryParse(arg.Args[0], out x)) return;
lootDelay = x;
Config["LootDelay"] = lootDelay;
SaveConfig();
}
#endregion
void DoAutoLoot(BasePlayer player)
{
var container = GetLootedInventory(player);
var playerMain = player.inventory.containerMain;
if (container == null || playerMain == null) return;
var itemsSelected = CloneItemList(container.itemList);
itemsSelected.Sort((item1, item2) => item2.info.itemid.CompareTo(item1.info.itemid));
MoveItems(itemsSelected, playerMain);
}
IEnumerable<Item> GetUselessItems(IEnumerable<Item> items, ItemContainer container)
{
var uselessItems = new List<Item>();
var furnace = container.entityOwner.GetComponent<BaseOven>();
if (furnace == null) return uselessItems;
foreach (var item in items)
{
var cookable = item.info.GetComponent<ItemModCookable>();
if (item.info.GetComponent<ItemModBurnable>() == null && cookable == null) continue;
if (cookable.lowTemp > CookingTemperature(furnace) || cookable.highTemp < CookingTemperature(furnace))
uselessItems.Add(item);
}
return uselessItems;
}
static float CookingTemperature(BaseOven oven)
{
switch (oven.temperature)
{
case BaseOven.TemperatureType.Warming:
return 50f;
case BaseOven.TemperatureType.Cooking:
return 200f;
case BaseOven.TemperatureType.Smelting:
return 1000f;
case BaseOven.TemperatureType.Fractioning:
return 1500f;
case BaseOven.TemperatureType.Normal:
return 15f;
default:
throw new ArgumentOutOfRangeException();
}
}
List<Item> CloneItemList(IEnumerable<Item> list)
{
var clone = new List<Item>();
foreach (var item in list) clone.Add(item);
return clone;
}
ItemContainer GetLootedInventory(BasePlayer player)
{
var playerLoot = player.inventory.loot;
if (playerLoot != null && playerLoot.IsLooting())
return playerLoot.containers[0];
return null;
}
void MoveItems(IEnumerable<Item> items, ItemContainer to)
{
foreach (var item in items) item.MoveToContainer(to);
}
List<Item> GetItemsOfType(ItemContainer container, ItemCategory category)
{
var items = new List<Item>();
foreach (var item in container.itemList)
if (item.info.category == category) items.Add(item);
return items;
}
ItemCategory StringToItemCategory(string categoryName)
{
var categoryNames = Enum.GetNames(typeof(ItemCategory));
for (var i = 0; i < categoryNames.Length; i++)
if (categoryName.ToLower().Equals(categoryNames[i].ToLower()))
return (ItemCategory)i;
return (ItemCategory)categoryNames.Length;
}
List<Item> GetExistingItems(ItemContainer primary, ItemContainer secondary)
{
var existingItems = new List<Item>();
if (primary == null || secondary == null) return existingItems;
foreach (var t in primary.itemList)
{
foreach (var t1 in secondary.itemList)
{
if (t.info.itemid != t1.info.itemid) continue;
existingItems.Add(t);
break;
}
}
return existingItems;
}
#endregion
#region User Interface
static readonly Dictionary<ulong, string> guiInfo = new Dictionary<ulong, string>();
void SortUi(BasePlayer player)
{
// Destroy existing UI
string gui;
if (guiInfo.TryGetValue(player.userID, out gui)) CuiHelper.DestroyUi(player, gui);
player.inventory.loot.entitySource.gameObject.AddComponent<UIDestroyer>();
guiInfo[player.userID] = CuiHelper.GetGuid();
var elements = new CuiElementContainer();
var panel = elements.Add(new CuiPanel
{
Image = { Color = "0.5 0.5 0.5 0.33" },
RectTransform = { AnchorMin = "0.677 0.769", AnchorMax = "0.963 0.96" }
}, "Overlay", guiInfo[player.userID]);
elements.Add(new CuiLabel
{
Text = { Text = Lang("Deposit"), FontSize = 16, Align = TextAnchor.MiddleCenter },
RectTransform = { AnchorMin = "0.02 0.8", AnchorMax = "0.3 1" }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort existing", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.02 0.6", AnchorMax = "0.3 0.8" },
Text = { Text = Lang("DepositExisting"), FontSize = 16, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.02 0.35", AnchorMax = "0.3 0.55" },
Text = { Text = Lang("DepositAll"), FontSize = 16, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort.loot", Color = "0 0.7 0 0.5" },
RectTransform = { AnchorMin = "0.02 0.05", AnchorMax = "0.3 0.3" },
Text = { Text = Lang("LootAll"), FontSize = 16, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort weapon", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.35 0.8", AnchorMax = "0.63 0.94" },
Text = { Text = Lang("DepositWeapons"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort ammunition", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.35 0.6", AnchorMax = "0.63 0.75" },
Text = { Text = Lang("DepositAmmo"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort medical", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.35 0.41", AnchorMax = "0.63 0.555" },
Text = { Text = Lang("DepositMedical"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort attire", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.35 0.235", AnchorMax = "0.63 0.368" },
Text = { Text = Lang("DepositAttire"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort resources", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.35 0.05", AnchorMax = "0.63 0.19" },
Text = { Text = Lang("DepositResources"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort construction", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.67 0.8", AnchorMax = "0.95 0.94" },
Text = { Text = Lang("DepositConstruction"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort items", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.67 0.6", AnchorMax = "0.95 0.75" },
Text = { Text = Lang("DepositItems"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort tool", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.67 0.41", AnchorMax = "0.95 0.555" },
Text = { Text = Lang("DepositTools"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort food", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.67 0.235", AnchorMax = "0.95 0.368" },
Text = { Text = Lang("DepositFood"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
elements.Add(new CuiButton
{
Button = { Command = "quicksort traps", Color = "1 0.5 0 0.5" },
RectTransform = { AnchorMin = "0.67 0.05", AnchorMax = "0.95 0.19" },
Text = { Text = Lang("DepositTraps"), FontSize = 14, Align = TextAnchor.MiddleCenter }
}, panel);
// Create the UI elements
CuiHelper.AddUi(player, elements);
}
#region Cleanup
class UIDestroyer : MonoBehaviour
{
void PlayerStoppedLooting(BasePlayer player)
{
// Destroy existing UI
string gui;
if (guiInfo.TryGetValue(player.userID, out gui)) CuiHelper.DestroyUi(player, gui);
Destroy(this);
}
}
void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
{
// Destroy existing UI
string gui;
if (guiInfo.TryGetValue(player.userID, out gui)) CuiHelper.DestroyUi(player, gui);
}
}
#endregion
#endregion
#region Helpers
private T GetConfig<T>(string name, T defaultValue)
{
if (Config[name] == null) return defaultValue;
return (T)Convert.ChangeType(Config[name], typeof(T));
}
//private bool IsAllowed(string id, string perm) => permission.UserHasPermission(id, perm);
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
#endregion
}
}