C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using System.Collections.Generic;
namespace Oxide.Plugins
{
[Info("ClothingSlots", "Jake_Rich", "1.1.4")]
[Description("Available Inventory Slots Depends On Clothing Worn")]
public partial class ClothingSlots : RustPlugin
{
public static ClothingSlots _plugin;
public static JSONFile<ConfigData> _settingsFile; //I know static stuff persists, it's handled in this case :)
public static ConfigData Settings { get { return _settingsFile.Instance; } }
public PlayerDataController<SlotPlayerData> PlayerData;
void Init()
{
_plugin = this;
}
void Loaded()
{
_settingsFile = new JSONFile<ConfigData>($"{Name}", ConfigLocation.Config, extension: ".json");
PlayerData = new PlayerDataController<SlotPlayerData>();
if (lang_en.Count > 0)
{
lang.RegisterMessages(lang_en, this); //Setup lang now by default in case it is needed
}
}
void OnServerInitialized()
{
Settings.Setup();
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
OnPlayerConnected(player);
}
}
void Unload()
{
foreach (var data in PlayerData.All) data.SetSlots(30); //Reset slot limit when unloading plugin
PlayerData.Unload();
}
void OnPlayerConnected(BasePlayer player) => PlayerData.Get(player).UpdateSlots();
void OnPlayerDisconnected(BasePlayer player) => PlayerData.Get(player).UpdateSlots();
void OnPlayerRespawned(BasePlayer player) => PlayerData.Get(player).UpdateSlots();
void OnPlayerDeath(BasePlayer player) => PlayerData.Get(player).UpdateSlots();
object CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainer, int targetSlot, int amount)
{
if (item == null || playerLoot == null)
{
return null;
}
BasePlayer _BasePlayer = playerLoot.baseEntity;
if (!_BasePlayer.IsValid())
{
return null;
}
BasePlayer player = playerLoot.GetComponent<BasePlayer>();
if (player == null)
{
return null;
}
ItemContainer _targetContainer = playerLoot.FindContainer(targetContainer);
if (_targetContainer == null)
{
return null;
}
if (targetSlot != -1)
{
return null;
}
if (item.parent != playerLoot.containerBelt)
{
return null;
}
if (item.info.GetComponent<ItemModWearable>() != null)
{
if (item.MoveToContainer(playerLoot.containerWear))
{
return false;
}
}
return null;
}
void OnItemAddedToContainer(ItemContainer container, Item item)
{
if (container == null || item == null)
{
return;
}
BasePlayer player = container.GetOwnerPlayer();
if (player == null || !player.userID.IsSteamId())
{
return;
}
if (container != player.inventory.containerWear || player.inventory.containerWear.uid != container.uid)
{
return;
}
PlayerData.Get(player).UpdateSlots();
}
void OnItemRemovedFromContainer(ItemContainer container, Item item)
{
if (container == null || item == null)
{
return;
}
BasePlayer player = container.GetOwnerPlayer();
if (player == null || !player.userID.IsSteamId())
{
return;
}
if (container != player.inventory.containerWear || player.inventory.containerWear.uid != container.uid)
{
return;
}
NextFrame(() =>
{
//NextFrame it, so when clothing is put into the inventory it will move when capacity decreases
if (player == null || !player.userID.IsSteamId() || player.IsDead())
{
return;
}
PlayerData.Get(player).UpdateSlots();
});
}
public class ClothingSetting
{
[JsonProperty(PropertyName = "Available inventory slots (Main)")]
public int Slots = 0;
public ClothingSetting()
{
}
public ClothingSetting(ItemDefinition clothing)
{
}
}
public class ConfigData
{
[JsonProperty(PropertyName = "Available inventory slots (Belt)")]
public int DefaultSlots = 6;
[JsonProperty(PropertyName = "Clothing settings (item shortname) and (available inventory slots)")]
public Dictionary<string, ClothingSetting> Clothing = new Dictionary<string, ClothingSetting>() //Default values are as follows
{
{"hazmatsuit", new ClothingSetting() { Slots = 12, } },
{"hazmatsuit.arcticsuit", new ClothingSetting() { Slots = 12, } },
{"hazmatsuit.spacesuit", new ClothingSetting() { Slots = 12, } },
{"hazmatsuit.lumberjack", new ClothingSetting() { Slots = 12, } },
{"mask.balaclava", new ClothingSetting() { Slots = 1, } },
{"diving.tank", new ClothingSetting() { Slots = 5, } },
{"mask.bandana", new ClothingSetting() { Slots = 1, } },
{"shoes.boots", new ClothingSetting() { Slots = 4, } },
{"scientistsuit_heavy", new ClothingSetting() { Slots = 24, } },
{"roadsign.jacket", new ClothingSetting() { Slots = 1, } },
{"tshirt.long", new ClothingSetting() { Slots = 1, } },
{"hat.beenie", new ClothingSetting() { Slots = 1, } },
{"diving.wetsuit", new ClothingSetting() { Slots = 4, } },
{"wood.armor.pants", new ClothingSetting() { Slots = 1, } },
{"wood.armor.jacket", new ClothingSetting() { Slots = 1, } },
{"wood.armor.helmet", new ClothingSetting() { Slots = 1, } },
{"metal.facemask", new ClothingSetting() { Slots = 1, } },
{"metal.facemask.hockey", new ClothingSetting() { Slots = 1, } },
{"attire.hide.vest", new ClothingSetting() { Slots = 1, } },
{"jacket.snow", new ClothingSetting() { Slots = 16, } },
{"hat.cap", new ClothingSetting() { Slots = 1, } },
{"roadsign.kilt", new ClothingSetting() { Slots = 1, } },
{"burlap.gloves", new ClothingSetting() { Slots = 1, } },
{"jumpsuit.suit", new ClothingSetting() { Slots = 8, } },
{"attire.ninja.suit", new ClothingSetting() { Slots = 6, } },
{"hazmatsuit_scientist_arctic", new ClothingSetting() { Slots = 24, } },
{"hazmatsuit.nomadsuit", new ClothingSetting() { Slots = 12, } },
{"attire.bunny.onesie", new ClothingSetting() { Slots = 8, } },
{"halloween.mummysuit", new ClothingSetting() { Slots = 5, } },
{"ghostsheet", new ClothingSetting() { Slots = 1, } },
{"hazmatsuit_scientist", new ClothingSetting() { Slots = 24, } },
{"hazmatsuit_scientist_peacekeeper", new ClothingSetting() { Slots = 24, } },
{"halloween.surgeonsuit", new ClothingSetting() { Slots = 5, } },
{"scarecrow.suit", new ClothingSetting() { Slots = 5, } },
{"barrelcostume", new ClothingSetting() { Slots = 24, } },
{"attire.egg.suit", new ClothingSetting() { Slots = 4, } },
{"bone.armor.suit", new ClothingSetting() { Slots = 4, } },
{"deer.skull.mask", new ClothingSetting() { Slots = 1, } },
{"attire.bunnyears", new ClothingSetting() { Slots = 1, } },
{"jacket", new ClothingSetting() { Slots = 8, } },
{"diving.fins", new ClothingSetting() { Slots = 1, } },
{"shirt.tanktop", new ClothingSetting() { Slots = 1, } },
{"hat.oxmask", new ClothingSetting() { Slots = 1, } },
{"hat.dragonmask", new ClothingSetting() { Slots = 1, } },
{"hat.ratmask", new ClothingSetting() { Slots = 1, } },
{"hat.tigermask", new ClothingSetting() { Slots = 1, } },
{"metal.plate.torso", new ClothingSetting() { Slots = 1, } },
{"attire.hide.helterneck", new ClothingSetting() { Slots = 1, } },
{"twitch.headset", new ClothingSetting() { Slots = 1, } },
{"burlap.shoes", new ClothingSetting() { Slots = 1, } },
{"attire.banditguard", new ClothingSetting() { Slots = 24, } },
{"attire.reindeer.headband", new ClothingSetting() { Slots = 1, } },
{"nightvisiongoggles", new ClothingSetting() { Slots = 1, } },
{"hat.boonie", new ClothingSetting() { Slots = 1, } },
{"roadsign.gloves", new ClothingSetting() { Slots = 1, } },
{"burlap.gloves.new", new ClothingSetting() { Slots = 1, } },
{"burlap.headwrap", new ClothingSetting() { Slots = 1, } },
{"scarecrowhead", new ClothingSetting() { Slots = 1, } },
{"diving.mask", new ClothingSetting() { Slots = 1, } },
{"attire.hide.poncho", new ClothingSetting() { Slots = 1, } },
{"partyhat", new ClothingSetting() { Slots = 1, } },
{"hat.gas.mask", new ClothingSetting() { Slots = 1, } },
{"shirt.collared", new ClothingSetting() { Slots = 4, } },
{"burlap.shirt", new ClothingSetting() { Slots = 1, } },
{"attire.hide.boots", new ClothingSetting() { Slots = 3, } },
{"boots.frog", new ClothingSetting() { Slots = 2, } },
{"gloweyes", new ClothingSetting() { Slots = 1, } },
{"pumpkin", new ClothingSetting() { Slots = 1, } },
{"jumpsuit.suit.blue", new ClothingSetting() { Slots = 8, } },
{"sunglasses", new ClothingSetting() { Slots = 1, } },
{"tactical.gloves", new ClothingSetting() { Slots = 1, } },
{"lumberjack hoodie", new ClothingSetting() { Slots = 12, } },
{"hoodie", new ClothingSetting() { Slots = 12, } },
{"heavy.plate.pants", new ClothingSetting() { Slots = 1, } },
{"heavy.plate.jacket", new ClothingSetting() { Slots = 1, } },
{"heavy.plate.helmet", new ClothingSetting() { Slots = 1, } },
{"twitchsunglasses", new ClothingSetting() { Slots = 1, } },
{"hat.miner", new ClothingSetting() { Slots = 1, } },
{"tshirt", new ClothingSetting() { Slots = 1, } },
{"hat.wolf", new ClothingSetting() { Slots = 1, } },
{"hat.bunnyhat", new ClothingSetting() { Slots = 1, } },
{"santahat", new ClothingSetting() { Slots = 1, } },
{"clatter.helmet", new ClothingSetting() { Slots = 1, } },
{"riot.helmet", new ClothingSetting() { Slots = 1, } },
{"bucket.helmet", new ClothingSetting() { Slots = 1, } },
{"coffeecan.helmet", new ClothingSetting() { Slots = 1, } },
{"attire.snowman.helmet", new ClothingSetting() { Slots = 1, } },
{"hat.candle", new ClothingSetting() { Slots = 1, } },
{"attire.nesthat", new ClothingSetting() { Slots = 1, } },
{"pants.shorts", new ClothingSetting() { Slots = 2, } },
{"pants", new ClothingSetting() { Slots = 4, } },
{"burlap.trousers", new ClothingSetting() { Slots = 1, } },
{"attire.hide.pants", new ClothingSetting() { Slots = 2, } },
{"attire.hide.skirt", new ClothingSetting() { Slots = 1, } },
{"cratecostume", new ClothingSetting() { Slots = 24, } },
};
public void Setup()
{
var clothing = ItemManager.itemList.Where(x => x.GetComponent<ItemModWearable>());
bool modified = false;
foreach (var attire in clothing)
{
if (_plugin.ItemNotClothing(attire.shortname))
{
//_plugin.Puts($"Item Not Clothing (shortname - {attire.shortname})");
continue;
}
if (!Clothing.ContainsKey(attire.shortname))
{
Clothing.Add(attire.shortname, new ClothingSetting(attire));
modified = true;
}
}
if (modified)
{
_settingsFile.Save();
}
//Outputs default values I put above
//_plugin.Puts(string.Join("\n", Clothing.Select(x=>$"{{\"{x.Key}\", new ClothingSetting() {{ Slots = {x.Value.Slots}, }} }},").ToArray()));
}
}
bool ItemNotClothing(string shortname)
{
switch (shortname)
{
case "movembermoustache":
return true;
case "santabeard":
return true;
case "movembermoustachecard":
return true;
case "frankensteins.monster.01.head":
return true;
case "frankensteins.monster.01.legs":
return true;
case "frankensteins.monster.01.torso":
return true;
case "frankensteins.monster.02.head":
return true;
case "frankensteins.monster.02.legs":
return true;
case "frankensteins.monster.02.torso":
return true;
case "frankensteins.monster.03.head":
return true;
case "frankensteins.monster.03.legs":
return true;
case "frankensteins.monster.03.torso":
return true;
case "sunglasses02black":
return true;
case "sunglasses02camo":
return true;
case "sunglasses02red":
return true;
case "sunglasses03black":
return true;
case "sunglasses03chrome":
return true;
case "sunglasses03gold":
return true;
default:
return false;
}
}
public class SlotPlayerData : BasePlayerData
{
public void SetSlots(int slots)
{
if (Player == null || !Player.userID.IsSteamId() || !Player.IsConnected)
{
return;
}
Player.inventory.containerBelt.MarkDirty();
Player.inventory.containerMain.MarkDirty();
if (slots <= 6)
{
Player.inventory.containerBelt.capacity = slots;
Player.inventory.containerMain.capacity = 0;
UpdateInventories();
return;
}
Player.inventory.containerBelt.capacity = 6;
if (slots >= 30)
{
Player.inventory.containerMain.capacity = 24;
}
else
{
Player.inventory.containerMain.capacity = slots - 6;
}
UpdateInventories();
}
private void UpdateInventory(ItemContainer container)
{
foreach (var invalidItem in container.itemList.ToList())
{
if (invalidItem.position >= container.capacity)
{
bool hasMovedItem = false;
for (int slot = 0; slot < Player.inventory.containerMain.capacity; slot++)
{
var slotItem = container.GetSlot(slot);
if (slotItem != null && invalidItem != null)
{
if (slotItem.CanStack(invalidItem))
{
int maxStack = slotItem.MaxStackable();
if (slotItem.amount < maxStack)
{
slotItem.amount += invalidItem.amount;
if (slotItem.amount > maxStack)
{
invalidItem.amount = slotItem.amount - maxStack;
slotItem.amount = maxStack;
}
else
{
//Combined item
hasMovedItem = true;
invalidItem.Remove();
ItemManager.DoRemoves();
break;
}
}
}
continue;
}
invalidItem.position = slot;
hasMovedItem = true;
break;
}
if (hasMovedItem == false)
{
invalidItem.Drop(Player.GetDropPosition(), Player.GetDropVelocity());
}
}
}
}
private void UpdateInventories()
{
if (Player.inventory.containerBelt.capacity < 6)
{
UpdateInventory(Player.inventory.containerBelt);
}
if (Player.inventory.containerMain.capacity < 24)
{
UpdateInventory(Player.inventory.containerMain);
}
}
public void UpdateSlots()
{
int targetSlots = Settings.DefaultSlots;
foreach (var clothing in Player.inventory.containerWear.itemList.ToList())
{
targetSlots += Settings.Clothing[clothing.info.shortname].Slots;
}
SetSlots(targetSlots);
}
}
#region Lang API
public Dictionary<string, string> lang_en = new Dictionary<string, string>()
{
};
public static string GetLangMessage(string key, BasePlayer player)
{
return _plugin.lang.GetMessage(key, _plugin, player.UserIDString);
}
public static string GetLangMessage(string key, ulong player)
{
return _plugin.lang.GetMessage(key, _plugin, player.ToString());
}
public static string GetLangMessage(string key, string player)
{
return _plugin.lang.GetMessage(key, _plugin, player);
}
#endregion
#region PlayerData
public class BasePlayerData
{
[JsonIgnore]
public BasePlayer Player { get; set; }
public string userID { get; set; } = "";
public BasePlayerData()
{
}
public BasePlayerData(BasePlayer player) : base()
{
userID = player.UserIDString;
Player = player;
}
}
public class PlayerDataController<T> where T : BasePlayerData
{
[JsonPropertyAttribute(Required = Required.Always)]
private Dictionary<string, T> playerData { get; set; } = new Dictionary<string, T>();
private JSONFile<Dictionary<string, T>> _file;
private Timer _timer;
public IEnumerable<T> All { get { return playerData.Values; } }
public PlayerDataController()
{
}
public PlayerDataController(string filename = null)
{
if (filename == null)
{
return;
}
_file = new JSONFile<Dictionary<string, T>>(filename);
_timer = _plugin.timer.Every(60.0f, () =>
{
_file.Save();
});
}
public void Unload()
{
if (_file == null)
{
return;
}
_file.Save();
}
public T Get(string identifer)
{
T data;
if (!playerData.TryGetValue(identifer, out data))
{
data = Activator.CreateInstance<T>();
playerData[identifer] = data;
}
return data;
}
public T Get(ulong userID)
{
return Get(userID.ToString());
}
public T Get(BasePlayer player)
{
var data = Get(player.UserIDString);
data.Player = player;
return data;
}
public bool Has(ulong userID)
{
return playerData.ContainsKey(userID.ToString());
}
public void Set(string userID, T data)
{
playerData[userID] = data;
}
public bool Remove(string userID)
{
return playerData.Remove(userID);
}
public void Update(T data)
{
playerData[data.userID] = data;
}
}
#endregion
#region Configuration Files
public enum ConfigLocation
{
Data = 0,
Config = 1,
Logs = 2,
Plugins = 3,
Lang = 4,
Custom = 5,
}
public class JSONFile<Type> where Type : class
{
private DynamicConfigFile _file;
public string _name { get; set; }
public Type Instance { get; set; }
private ConfigLocation _location { get; set; }
private string _path { get; set; }
public JSONFile(string name, ConfigLocation location = ConfigLocation.Data, string path = null, string extension = ".json")
{
_name = name.Replace(".json", "");
_location = location;
switch (location)
{
case ConfigLocation.Data:
{
_path = $"{Oxide.Core.Interface.Oxide.DataDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Config:
{
_path = $"{Oxide.Core.Interface.Oxide.ConfigDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Logs:
{
_path = $"{Oxide.Core.Interface.Oxide.LogDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Lang:
{
_path = $"{Oxide.Core.Interface.Oxide.LangDirectory}/{name}{extension}";
break;
}
case ConfigLocation.Custom:
{
_path = $"{path}/{name}{extension}";
break;
}
}
_file = new DynamicConfigFile(_path);
_file.Settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
Init();
}
public virtual void Init()
{
Load();
Save();
Load();
}
public virtual void Load()
{
if (!_file.Exists())
{
Save();
}
Instance = _file.ReadObject<Type>();
if (Instance == null)
{
Instance = Activator.CreateInstance<Type>();
Save();
}
return;
}
public virtual void Save()
{
_file.WriteObject(Instance);
return;
}
public virtual void Reload()
{
Load();
}
private void Unload(Plugin sender, PluginManager manager)
{
}
}
#endregion
}
}