Иконка ресурса

FREE AutoRecycler : 1.0.7 1.0.7

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Oxide.Game.Rust.Cui;
using System;
using System.Diagnostics;
using System.Globalization;
using Oxide.Core;

namespace Oxide.Plugins
{
	[Info("Auto Recycler", "M&B-Studios & Mevent", "1.0.7")]
	public class AutoRecycler : RustPlugin
	{
		#region Classes

		public struct EntityAndPlayer
		{
			public BaseEntity Entity;
			public BasePlayer Player;
		}

		#endregion

		#region Fields

		private const string
			Layer = "ui.AutoRecycler.bg",
			PermAdmin = "autorecycler.admin",
			PermAutorec = "autorecycler.autorec",
			PermRecvirtual = "autorecycler.recvirtual",
			PermRecyclercratetest = "autorecycler.recyclercratetest",
			PermCharacteristics = "autorecycler.characteristics",
			PermRecboxBuy = "autorecycler.recboxbuy";

		private Dictionary<ulong, bool> PlayerAutoRecState = new Dictionary<ulong, bool>();

		private readonly Dictionary<ulong, EntityAndPlayer> _recyclers = new Dictionary<ulong, EntityAndPlayer>();
		private const int ItemsPerRow = 7;
		private const int ItemsPerPage = 35;


		private readonly Dictionary<string, List<ItemAmount>> Chances = new()
		{
			["rifle.ak"] = new()
			{
				new()
				{
					Shortname = "riflebody",
					Chance = 50f
				}
			},
			["ammo.grenadelauncher.he"] = new()
			{
				new()
				{
					Shortname = "explosives",
					Chance = 25f
				},
				new()
				{
					Shortname = "metalpipe",
					Chance = 25f
				}
			},
			["ammo.grenadelauncher.smoke"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 25f
				}
			},
			["pistol.m92"] = new()
			{
				new()
				{
					Shortname = "semibody",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["smg.mp5"] = new()
			{
				new()
				{
					Shortname = "smgbody",
					Chance = 50f
				}
			},
			["shotgun.pump"] = new()
			{
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["pistol.python"] = new()
			{
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["pistol.revolver"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["rifle.semiauto"] = new()
			{
				new()
				{
					Shortname = "semibody",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["pistol.semiauto"] = new()
			{
				new()
				{
					Shortname = "semibody",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["smg.thompson"] = new()
			{
				new()
				{
					Shortname = "smgbody",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["holosight"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 0f
				}
			},
			["weapon.mod.lasersight"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["paddle"] = new()
			{
				new()
				{
					Shortname = "metalblade",
					Chance = 50f
				}
			},
			["knife.combat"] = new()
			{
				new()
				{
					Shortname = "metal.refined",
					Chance = 50f
				}
			},
			["speargun"] = new()
			{
				new()
				{
					Shortname = "propanetank",
					Chance = 50f
				}
			},
			["stone.spear"] = new()
			{
				new()
				{
					Shortname = "spear.wooden",
					Chance = 50f
				}
			},
			["cleaver.salvaged"] = new()
			{
				new()
				{
					Shortname = "roadsigns",
					Chance = 50f
				}
			},
			["sword.salvaged"] = new()
			{
				new()
				{
					Shortname = "metalblade",
					Chance = 50f
				}
			},
			["gun.lmg.m2"] = new()
			{
				new()
				{
					Shortname = "riflebody",
					Chance = 50f
				}
			},
			["gun.hmlmg"] = new()
			{
				new()
				{
					Shortname = "riflebody",
					Chance = 50f
				}
			},
			["rifle.bolt"] = new()
			{
				new()
				{
					Shortname = "riflebody",
					Chance = 50f
				},
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["gun.mgl"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["gun.rocket.launcher"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["trap.flameturret"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["trap.bear"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["tool.binoculars"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["tool.instant_camera"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["jackhammer"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["rf.detonator"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["axe.salvaged"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["hammer.salvaged"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["icepick.salvaged"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["explosive.satchet"] = new()
			{
				new()
				{
					Shortname = "stash.small",
					Chance = 50f
				},
				new()
				{
					Shortname = "rope",
					Chance = 50f
				}
			},
			["torch"] = new()
			{
				new()
				{
					Shortname = "cloth",
					Chance = 50f
				},
				new()
				{
					Shortname = "lowgradefuel",
					Chance = 50f
				}
			},
			["lowgradefuel"] = new()
			{
				new()
				{
					Shortname = "fat.animal",
					Chance = 38f
				},
				new()
				{
					Shortname = "cloth",
					Chance = 13f
				}
			},
			["fogmachine"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["snowmachine"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["drone"] = new()
			{
				new()
				{
					Shortname = "cctv.camera",
					Chance = 50f
				}
			},
			["skull_fire_pit"] = new()
			{
				new()
				{
					Shortname = "skull.human",
					Chance = 50f
				}
			},
			["planter.small"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["tunalight"] = new()
			{
				new()
				{
					Shortname = "can.tuna.empty",
					Chance = 50f
				}
			},
			["water.barrel"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["water.purifier"] = new()
			{
				new()
				{
					Shortname = "propanetank",
					Chance = 50f
				}
			},
			["boogieboard"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["innertube"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["paddlingpool"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["skullspikes"] = new()
			{
				new()
				{
					Shortname = "skull.human",
					Chance = 50f
				}
			},
			["telephone"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["autoturret"] = new()
			{
				new()
				{
					Shortname = "targeting.computer",
					Chance = 50f
				},
				new()
				{
					Shortname = "cctv.camera",
					Chance = 50f
				}
			},
			["computerstation"] = new()
			{
				new()
				{
					Shortname = "targeting.computer",
					Chance = 50f
				},
				new()
				{
					Shortname = "electric.rf.broadcaster",
					Chance = 50f
				},
				new()
				{
					Shortname = "electric.rf.receiver",
					Chance = 50f
				}
			},
			["elevator"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["electric.solarpanel.large"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["electric.battery.rechargable.medium"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["modularcarlift"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["ptz.cctv.camera"] = new()
			{
				new()
				{
					Shortname = "cctv.camera",
					Chance = 50f
				}
			},
			["electric.pressurepad"] = new()
			{
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				},
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["electric.rf.broadcaster"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["rf_pager"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["electric.rf.receiver"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["target.reactive"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["smart.alarm"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["smart.switch"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["storage.monitor"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["electric.teslacoil"] = new()
			{
				new()
				{
					Shortname = "techparts",
					Chance = 50f
				}
			},
			["waterpump"] = new()
			{
				new()
				{
					Shortname = "gears",
					Chance = 50f
				}
			},
			["barricade.wood"] = new()
			{
				new()
				{
					Shortname = "rope",
					Chance = 50f
				}
			},
			["door.closer"] = new()
			{
				new()
				{
					Shortname = "metalspring",
					Chance = 50f
				}
			},
			["floor.ladder.hatch"] = new()
			{
				new()
				{
					Shortname = "ladder.wooden.wall",
					Chance = 50f
				}
			},
			["water.catcher.small"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["floor.triangle.ladder.hatch"] = new()
			{
				new()
				{
					Shortname = "ladder.wooden.wall",
					Chance = 50f
				}
			},
			["barricade.woodwire"] = new()
			{
				new()
				{
					Shortname = "rope",
					Chance = 50f
				}
			},
			["ducttape"] = new()
			{
				new()
				{
					Shortname = "glue",
					Chance = 50f
				}
			},
			["shoes.boots"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["coffeecan.helmet"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["boots.frog"] = new()
			{
				new()
				{
					Shortname = "tarp",
					Chance = 50f
				}
			},
			["heavy.plate.helmet"] = new()
			{
				new()
				{
					Shortname = "sheetmetal",
					Chance = 50f
				}
			},
			["heavy.plate.pants"] = new()
			{
				new()
				{
					Shortname = "sheetmetal",
					Chance = 50f
				}
			},
			["hoodie"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["burlap.gloves"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["lumberjack hoodie"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["attire.nesthat"] = new()
			{
				new()
				{
					Shortname = "skull.wolf",
					Chance = 50f
				}
			},
			["hat.oxmask"] = new()
			{
				new()
				{
					Shortname = "skull.wolf",
					Chance = 50f
				}
			},
			["pants"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["hat.ratmask"] = new()
			{
				new()
				{
					Shortname = "skull.wolf",
					Chance = 50f
				}
			},
			["jacket.snow"] = new()
			{
				new()
				{
					Shortname = "sewingkit",
					Chance = 50f
				}
			},
			["hat.wolf"] = new()
			{
				new()
				{
					Shortname = "skull.wolf",
					Chance = 50f
				}
			},
			["wood.armor.pants"] = new()
			{
				new()
				{
					Shortname = "rope",
					Chance = 50f
				}
			},
			["wood.armor.jacket"] = new()
			{
				new()
				{
					Shortname = "rope",
					Chance = 50f
				}
			},
			["ammo.grenadelauncher.he"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 25f
				},
				new()
				{
					Shortname = "explosives",
					Chance = 25f
				}
			},
			["ammo.grenadelauncher.smoke"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 25f
				}
			},
			["arrow.fire"] = new()
			{
				new()
				{
					Shortname = "cloth",
					Chance = 25f
				}
			},
			["ammo.rocket.hv"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				}
			},
			["ammo.rocket.seeker"] = new()
			{
				new()
				{
					Shortname = "metalpipe",
					Chance = 50f
				},
				new()
				{
					Shortname = "techparts",
					Chance = 25f
				}
			}
		};

		private List<string> _itemBlacklist = new List<string>
		{
			"attackhelicopter",
			"minicopter",
			"transporthelicopter",
			"rhib",
			"rowboat",
			"tugboat",
			"submarinesolo",
			"submarineduo",
			"snowmobile",
			"snowmobiletomaha",
			"locomotive",
			"wagon",
			"workcart",
			"mlrs",
			"scraptransportheli.repair",
			"vehicle.chassis",
			"vehicle.module"
		};

		private List<ItemCategory> Categories = new();

		private Dictionary<ulong, List<string>> _players = new();

		private enum ActionType : byte
		{
			AutoRec = 0,
			RecVirtual = 1,
			RecyclerCrateTest = 2,
			Characteristics = 3
		}

		#endregion

		#region Hooks

		private void Init() => Unsubscribe(nameof(CanNetworkTo));

		private object CanNetworkTo(BaseNetworkable e, BasePlayer p)
		{
			if (e == null || p == null || p == e || p.IsAdmin) return null;

			if (IsRecycleBox(e))
				return (PlayerFromRecycler(e.net.ID.Value)?.userID ?? 0) == p.userID;
			return null;
		}

		private void OnServerSave() => SaveData();

		private void Unload()
		{
			SaveData();

			foreach (var player in BasePlayer.activePlayerList) UI_Destroy(player);

			DestroyRecyclers();
		}

		private void OnServerInitialized()
		{
			LoadData();
			RegisterPermissions();
			RegisterCommands();

			Dictionary<string, List<ItemAmount>> itemsWhichRecycleResult = new();
			foreach (var x in ItemManager.itemList)
			{
				if (_itemBlacklist.Contains(x.shortname))
					continue;

				var item = ItemManager.Create(x);
				if (item == null)
				{
					PrintError($"Item is null - {x.shortname}");
					continue;
				}

				if (item.info.Blueprint == null)
				{
					continue;
				}

				itemsWhichRecycleResult.Add(x.shortname, new());

				if (item.info.Blueprint.scrapFromRecycle > 0)
				{
					itemsWhichRecycleResult[x.shortname].Add(new ItemAmount
					{
						Shortname = "scrap",
						Amount = item.info.Blueprint.scrapFromRecycle,
						Enabled = true,
						Chance = 100
					});
				}

				foreach (var y in item.info.Blueprint.ingredients.Where(x => x.itemDef.shortname != "scrap"))
				{
					if (itemsWhichRecycleResult[x.shortname].Any(x => x.Shortname == y.itemDef.shortname))
						continue;

					float chance = -1f;

					if (Chances.ContainsKey(x.shortname))
					{
						var buf = Chances[x.shortname].FirstOrDefault(z => z.Shortname == y.itemDef.shortname);

						if (buf != null)
							chance = buf.Chance;
					}

					float num4 = y.amount / x?.Blueprint?.amountToCreate ?? 1;
					int num5 = 0;
					if (num4 <= 1f)
					{
						for (int j = 0; j < 1; j++)
						{
							if (UnityEngine.Random.Range(0f, 1f) <= num4)
							{
								num5++;
							}
						}
					}
					else
					{
						num5 = Mathf.CeilToInt(Mathf.Clamp(num4 * UnityEngine.Random.Range(1f, 1f), 0f, y.amount)) / 2;
					}


					// if (num5 > 0)
					// {
					//     int num6 = Mathf.CeilToInt((float)num5 / (float)y.itemDef.stackable);
					// }
					itemsWhichRecycleResult[x.shortname].Add(new ItemAmount
					{
						//
						Shortname = y.itemDef.shortname,
						Amount = (int) num5,
						Enabled = true,
						Chance = chance < 0 ? 100f : chance
					});
				}
			}

			if (itemsWhichRecycleResult.Count > config.RecycleItems.Count)
			{
				foreach (var item in itemsWhichRecycleResult.Where(x => !config.RecycleItems.ContainsKey(x.Key)))
				{
					config.RecycleItems.Add(item.Key, new ItemSettings()
					{
						IsEnabled = true,
						ItemAmount = item.Value
					});
				}

				SaveConfig();
			}

			FillCategories();
		}

		private void OnItemAddedToContainer(ItemContainer container, Item item)
		{
			if (container == null || item == null)
				return;
			var player = container.playerOwner;

			if (item.skin == 1)
			{
				item.skin = 0;
				return;
			}

			var itemShortname = item.info.shortname;
			if (!config.RecycleItems.TryGetValue(itemShortname, out var recycleItems))
			{
				return;
			}

			if (player == null)
			{
				if (container.entityOwner == null)
					return;

				if (!container.entityOwner.TryGetComponent<StorageContainer>(out var comp))
					return;
				if (comp.HasFlag(BaseEntity.Flags.Disabled))
					return;

				var skinid = comp.skinID;

				if (config._CrateRecycler.SkinID == skinid)
				{
					RecycleItem(player, item, recycleItems.ItemAmount, comp);
				}

				return;
			}

			if (!AutoRecycleItem(player, itemShortname))
				return;


			RecycleItem(player, item, recycleItems.ItemAmount);
		}

		private object OnEntityVisibilityCheck(BaseEntity ent, BasePlayer player, uint id, string debugName,
			float maximumDistance)
		{
			var recycler = ent as Recycler;
			if (recycler == null) return null;

			var playerFromRec = PlayerFromRecycler(ent.net.ID.Value);

			if (playerFromRec != null && player == playerFromRec)
			{
				return true;
			}

			return null;
		}

		private object OnEntityDistanceCheck(BaseEntity ent, BasePlayer player, uint id, string debugName,
			float maximumDistance, bool checkParent)
		{
			var recycler = ent as Recycler;
			if (recycler == null) return null;

			var playerFromRec = PlayerFromRecycler(ent.net.ID.Value);

			if (playerFromRec != null && playerFromRec == player)
			{
				return true;
			}

			return null;
		}

		private object OnLootEntityEnd(BasePlayer player, Recycler recycler)
		{
			var playerRecycler = RecyclerFromPlayer(player.userID);

			if (playerRecycler == null)
				return null;

			if (playerRecycler == recycler)
			{
				foreach (var x in recycler.inventory.itemList.ToArray())
					x.Drop(player.GetDropPosition(), player.GetDropVelocity());

				DestroyRecycler(recycler);
			}

			return null;
		}

		#endregion

		#region Methods

		private void CreateRecycler(BasePlayer p)
		{
			var posAdd = p.transform.position.y > 500 ? Vector3.down * 40 : Vector3.down * 500;

			var recycler =
				GameManager.server.CreateEntity("assets/bundled/prefabs/static/recycler_static.prefab",
						p.transform.position + posAdd) as
					Recycler;
			if (recycler == null) return;

			recycler.enableSaving = false;
			recycler.globalBroadcast = true;
			recycler.Spawn();

			recycler.SetFlag(BaseEntity.Flags.Locked, true);
			recycler.UpdateNetworkGroup();

			if (!recycler.isSpawned) return;
			recycler.gameObject.layer = 0;
			recycler.SendNetworkUpdateImmediate(true);
			Subscribe(nameof(CanNetworkTo));
			OpenContainer(p, recycler);

			_recyclers.Add(recycler.net.ID.Value, new EntityAndPlayer {Entity = recycler, Player = p});
		}

		public BasePlayer PlayerFromRecycler(ulong netID) =>
			!IsRecycler(netID) ? null : _recyclers[netID].Player;

		public bool IsRecycler(ulong netID) => _recyclers.ContainsKey(netID);

		public bool IsRecycleBox(BaseNetworkable e)
		{
			if (e == null || e.net == null) return false;
			return IsRecycler(e.net.ID.Value);
		}

		private void DestroyRecycler(BaseEntity e)
		{
			if (IsRecycleBox(e))
			{
				_recyclers.Remove(e.net.ID.Value);
				e.Kill();
			}

			if (_recyclers.Count == 0) Unsubscribe(nameof(CanNetworkTo));
		}

		private void DestroyRecyclers()
		{
			while (_recyclers.Count > 0)
				DestroyRecycler(_recyclers.FirstOrDefault().Value.Entity);

			Unsubscribe(nameof(CanNetworkTo));
			_recyclers.Clear();
		}

		private void OpenContainer(BasePlayer p, StorageContainer con)
		{
			timer.In(.1f, () =>
			{
				p.EndLooting();
				if (!p.inventory.loot.StartLootingEntity(con, false)) return;
				p.inventory.loot.AddContainer(con.inventory);
				p.inventory.loot.SendImmediate();
				p.ClientRPC(RpcTarget.Player("RPC_OpenLootPanel", p), con.panelName);
				p.SendNetworkUpdate();
			});
		}

		private void SetRecyclingState(BasePlayer player, string shortname, bool flag)
		{
			if (!_players.ContainsKey(player.userID))
				_players.Add(player.userID, new());

			if (flag)
			{
				if (!_players[player.userID].Contains(shortname))
					_players[player.userID].Add(shortname);

				return;
			}

			_players[player.userID].Remove(shortname);
		}

		private bool AutoRecycleItem(BasePlayer player, string shortname)
		{
			if (PlayerAutoRecState.TryGetValue(player.userID, out var state))
			{
				if (state == false)
					return false;
			}

			if (!_players.ContainsKey(player.userID))
				return false;

			if (!config.RecycleItems.TryGetValue(shortname, out var item))
				return false;

			if (!item.IsEnabled)
				return false;

			if (!_players[player.userID].Contains(shortname))
				return false;

			return true;
		}

		private bool CanUseAction(BasePlayer player, ActionType type)
		{
			if (player == null)
				return true;

			if (HasPermission(player, PermAdmin))
				return true;

			return type switch
			{
				ActionType.Characteristics => HasPermission(player, PermCharacteristics),
				ActionType.AutoRec => HasPermission(player, PermAutorec),
				ActionType.RecVirtual => HasPermission(player, PermRecvirtual),
				ActionType.RecyclerCrateTest => HasPermission(player, PermRecyclercratetest),
				_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
			};
		}

		private void FillCategories()
		{
			Categories.Add(ItemCategory.All);
			foreach (var x in config.RecycleItems)
			{
				var def = ItemManager.FindItemDefinition(x.Key);

				if (Categories.Contains(def.category))
					continue;
				Categories.Add(def.category);
			}
		}

		private void RegisterCommands()
		{
			foreach (var x in config.VirtualRecyclerCommands)
				cmd.AddChatCommand(x, this, nameof(CmdOpenVirtualRecycler));
			foreach (var x in config.AutoRecyclerUICommands)
				cmd.AddChatCommand(x, this, nameof(CmdAutorec));
		}

		private void RegisterPermissions()
		{
			permission.RegisterPermission(PermAdmin, this);
			permission.RegisterPermission(PermAutorec, this);
			permission.RegisterPermission(PermCharacteristics, this);
			permission.RegisterPermission(PermRecyclercratetest, this);
			permission.RegisterPermission(PermRecvirtual, this);
			permission.RegisterPermission(PermRecboxBuy, this);
		}

		private bool HasPermission(BasePlayer player, string perm) => player.IPlayer.HasPermission(perm);
		private ItemCategory GetItemCategory(string shortname) => ItemManager.FindItemDefinition(shortname).category;

		private IEnumerable<KeyValuePair<string, List<ItemAmount>>> GetItemsByCategory(BasePlayer player,
			ItemCategory category)
		{
			var playerHasPermission = CanUseAction(player, ActionType.Characteristics);

			if (category == ItemCategory.All)
				return playerHasPermission
					? config.RecycleItems.Select(x =>
							new KeyValuePair<string, List<ItemAmount>>(x.Key, x.Value.ItemAmount))
					: config.RecycleItems.Where(x => x.Value.IsEnabled).Select(x =>
							new KeyValuePair<string, List<ItemAmount>>(x.Key, x.Value.ItemAmount));

			return playerHasPermission
				? config.RecycleItems.Where(x => ItemManager.FindItemDefinition(x.Key).category == category).Select(y => new KeyValuePair<string, List<ItemAmount>>(y.Key, y.Value.ItemAmount))
				: config.RecycleItems.Where(x =>
						ItemManager.FindItemDefinition(x.Key).category == category && x.Value.IsEnabled).Select(y => new KeyValuePair<string, List<ItemAmount>>(y.Key, y.Value.ItemAmount));
		}

		public BaseEntity RecyclerFromPlayer(ulong uid)
		{
			foreach (EntityAndPlayer eap in _recyclers.Values)
				if (eap.Player.userID == uid)
					return eap.Entity;
			return null;
		}

		public void OpenRecycler(BasePlayer p)
		{
			if (p == null) return;
			BaseEntity result = RecyclerFromPlayer(p.userID);
			if (result == null) CreateRecycler(p);
			else
			{
				DestroyRecycler(result);
				CreateRecycler(p);
			}
		}

		private bool IsRare(float rare) => rare >= UnityEngine.Random.Range(0.0f, 100.1f);

		private void RecycleItem(BasePlayer player, Item item, List<ItemAmount> recycleItems,
			StorageContainer sc = null)
		{
			int originalItemCount = item.amount;
			item.Remove();
			foreach (var recycleItem in recycleItems)
			{
				if (!recycleItem.Enabled) continue;

				int totalAmount =
					recycleItem.Amount *
					originalItemCount;
				if (recycleItem.Chance < 99f)
				{
					int availableAmount = 0;
					for (int i = 0; i < originalItemCount; i++)
						if (IsRare(recycleItem.Chance))
							availableAmount++;

					if (availableAmount <= 0)
						continue;

					totalAmount = recycleItem.Amount * availableAmount;
				}

				var definition = ItemManager.FindItemDefinition(recycleItem.Shortname);
				if (definition == null)
				{
					Puts($"Item-Definition f r '{recycleItem.Shortname}' nicht gefunden.");
					continue;
				}


				var remaining = (float) totalAmount;
				while (remaining > 0)
				{
					var newItem = ItemManager.CreateByItemID(definition.itemid, 1);

					newItem.amount = remaining < definition.stackable ? (int) remaining : definition.stackable;

					if (newItem == null)
					{
						Puts($"Konnte Item '{recycleItem.Shortname}' nicht erstellen.");
						continue;
					}

					NextTick(() =>
					{
						Unsubscribe(nameof(OnItemAddedToContainer));
						if (sc != null)
						{
							if (!sc.inventory.GiveItem(newItem))
							{
								newItem.Drop(sc.GetDropPosition(), sc.GetDropVelocity());
								Puts($"Inventar voll.Dropping Item '{recycleItem.Shortname}' auf den Boden.");
							}
						}
						else if (!player.inventory.GiveItem(newItem))
						{
							newItem.Drop(player.GetDropPosition(), player.GetDropVelocity());
							Puts($"Inventar voll.Dropping Item '{recycleItem.Shortname}' auf den Boden.");
						}

						Subscribe(nameof(OnItemAddedToContainer));
					});

					remaining -= newItem.amount;
				}
			}
		}

		#endregion

		#region UI

		private void UI_UpdateItem(BasePlayer player, string shortname)
		{
			CuiHelper.DestroyUi(player, Layer + ".main" + ".items.div" + $".item.{shortname}" + ".bg");
			var container = new CuiElementContainer();

			var canRecycle = AutoRecycleItem(player, shortname);

			container.Add(new CuiPanel
				{
					CursorEnabled = false,
					Image =
					{
						Color = canRecycle
							? "0.5108469 0.735849 0.4408152 0.3882353"
							: "0.8156863 0.5568628 0.4745098 0.3882353"
					},
					RectTransform =
					{
						AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-39.544 -39.544",
						OffsetMax = "39.544 39.544"
					}
				}, Layer + ".main" + ".items.div" + $".item.{shortname}",
				Layer + ".main" + ".items.div" + $".item.{shortname}" + ".bg");

			var itemdef = ItemManager.itemDictionaryByName[shortname];

			container.Add(new CuiPanel
				{
					CursorEnabled = false,
					Image = {Color = "1 1 1 1", ItemId = itemdef.itemid},
					RectTransform =
					{
						AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-39.544 -39.544",
						OffsetMax = "39.544 39.544"
					}
				}, Layer + ".main" + ".items.div" + $".item.{shortname}.bg",
				Layer + ".main" + ".items.div" + $".item.{shortname}" + ".image");

			container.Add(new CuiButton
				{
					Button =
					{
						Color = canRecycle ? "0.5108469 0.735849 0.4408152 1" : "0.8156863 0.5568628 0.4745098 1",
						Command = $"ar.setstate {shortname} {!canRecycle}",
						Sprite = canRecycle ? "assets/icons/check.png" : "assets/icons/close.png"
					},
					RectTransform =
					{
						AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "15.026 15.725",
						OffsetMax = "36.174 36.875"
					}
				}, Layer + ".main" + ".items.div" + $".item.{shortname}.bg",
				Layer + ".main" + ".items.div" + $".item.{shortname}" + ".enabled");

			if (CanUseAction(player, ActionType.Characteristics))
			{
				var isEnabled = config.RecycleItems[shortname].IsEnabled;

				container.Add(new CuiButton
					{
						Button =
						{
							Color = isEnabled ? "0.09545212 0.3679245 0.1133182 0.8235294" : "1 0.03030553 0 0.8235294",
							Command = $"ar.togglestate {shortname} {!isEnabled}"
						},
						Text =
						{
							Text = isEnabled ? "ENABLED" : "DISABLED", Font = "robotocondensed-bold.ttf", FontSize = 13,
							Align = TextAnchor.MiddleCenter,
							Color = isEnabled ? "0.263648 1 0 1" : "0.6226415 0.1380384 0.1380384 1"
						},
						RectTransform =
						{
							AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-39.544 -39.543",
							OffsetMax = "39.544 -20.039"
						}
					}, Layer + ".main" + ".items.div" + $".item.{shortname}.bg",
					Layer + ".autorecycler" + ".main" + ".items.div" + $".item.{shortname}" + ".adminbtn");
			}

			CuiHelper.DestroyUi(player, Layer + ".search.bg");
			CuiHelper.AddUi(player, container);
		}

		private void UI_DrawSearch(BasePlayer player)
		{
			var container = new CuiElementContainer();

			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "0.5254902 0.5019608 0.4666667 1"},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-104.786 -46.797",
					OffsetMax = "104.786 -20.326"
				}
			}, Layer + ".main" + ".header.div", Layer + ".main" + ".header.div" + ".search.bg");

			container.Add(new CuiElement
			{
				Name = Layer + ".main" + ".header.div" + ".search.bg" + ".input",
				Parent = Layer + ".main" + ".header.div" + ".search.bg",
				Components =
				{
					new CuiInputFieldComponent
					{
						Color = "0.8078431 0.7803922 0.7411765 1", Font = "robotocondensed-bold.ttf", FontSize = 14,
						Align = TextAnchor.MiddleCenter, CharsLimit = 20, IsPassword = false, NeedsKeyboard = true
					},
					new CuiRectTransformComponent
					{
						AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-96.1 -13.235",
						OffsetMax = "96.172 13.236"
					}
				}
			});

			CuiHelper.DestroyUi(player, Layer + ".search.bg");
			CuiHelper.AddUi(player, container);
		}

		private void UI_DrawMain(BasePlayer player)
		{
			var container = new CuiElementContainer();

			container.Add(new CuiElement()
			{
				Name = Layer + ".close",
				Parent = "Overlay",
				Components =
				{
					new CuiButtonComponent()
					{
						Command = "ar.close",
						Color = "0 0 0 0.5",
						Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
					}
				}
			});

			container.Add(new CuiPanel
			{
				CursorEnabled = true,
				Image = {Color = "0.317 0.317 0.317 0.7490196"},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-434.913 -260.419",
					OffsetMax = "434.913 260.419"
				}
			}, "Overlay", Layer);

			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "1 1 1 0"},
				RectTransform =
				{
					AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "0.09 -260.419", OffsetMax = "660.17 260.421"
				}
			}, Layer, Layer + ".main");

			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "1 1 1 0"},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-330.04 219.767",
					OffsetMax = "330.04 260.42"
				}
			}, Layer + ".main", Layer + ".main" + ".header.div");

			container.Add(new CuiButton
			{
				Button = {Color = "1 1 1 0"},
				Text =
				{
					Text = "SEARCH", Font = "robotocondensed-bold.ttf", FontSize = 29, Align = TextAnchor.MiddleCenter,
					Color = "0.8078431 0.7803922 0.7411765 1"
				},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-76.091 -20.326",
					OffsetMax = "76.091 20.326"
				}
			}, Layer + ".main" + ".header.div", Layer + ".main" + ".header.div" + ".search.btn");

			UI_Destroy(player);
			CuiHelper.AddUi(player, container);

			UI_DrawCategories(player, ItemCategory.All);
			UI_DrawItems(player, ItemCategory.All);
		}

		private void UI_DrawItems(BasePlayer player, ItemCategory activeCategory, int page = 0)
		{
			CuiHelper.DestroyUi(player, Layer + ".main" + ".items.div");
			var container = new CuiElementContainer();

			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "1 1 1 0.1490196"},
				RectTransform =
				{
					AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "-0.04 -226.279", OffsetMax = "660.04 219.771"
				}
			}, Layer + ".main", Layer + ".main" + ".items.div");

			float minx = -305.04f;
			float maxx = -225.9524f;
			float miny = 143.9324f;
			float maxy = 223.02f;

			int i = 0;
			CuiHelper.AddUi(player, container);
			UI_DrawPages(player, activeCategory, page);
			float fadein = 0.01f;

			foreach (var item in GetItemsByCategory(player, activeCategory).Skip(page * ItemsPerPage).Take(ItemsPerPage))
			{
				fadein = Mathf.Lerp(0.01f, 0.5f, i / 16f);
				container.Clear();
				if (i % ItemsPerRow == 0 && i != 0)
				{
					minx = -305.04f;
					maxx = -225.9524f;
					miny -= 85.476f;
					maxy -= 85.476f;
				}

				container.Add(new CuiPanel
					{
						CursorEnabled = false,
						Image = {Color = "0.8156863 0.5568628 0.4745098 0.3882353", FadeIn = fadein},
						RectTransform =
						{
							AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{minx} {miny}",
							OffsetMax = $"{maxx} {maxy}"
						}
					}, Layer + ".main" + ".items.div", Layer + ".main" + ".items.div" + $".item.{item.Key}");


				minx += 85.496f;
				maxx += 85.496f;
				i++;
				CuiHelper.AddUi(player, container);
				UI_UpdateItem(player, item.Key);
			}
		}

		private void UI_DrawPages(BasePlayer player, ItemCategory activeCategory, int page = 0)
		{
			var container = new CuiElementContainer();

			var canNext = GetItemsByCategory(player, activeCategory).Skip((page + 1) * ItemsPerPage).Any();
			var canPrevious = page - 1 >= 0;

			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "0.317 0.317 0.317 0.6392157"},
				RectTransform =
					{AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "0 -34.166", OffsetMax = "118.486 -0.024"}
			}, Layer + ".main" + ".items.div", Layer + ".main" + ".items.div" + ".pages");

			container.Add(new CuiElement
			{
				Name = Layer + ".main" + ".items.div" + ".pages" + ".page.now",
				Parent = Layer + ".main" + ".items.div" + ".pages",
				Components =
				{
					new CuiTextComponent
					{
						Text = (page + 1).ToString(), Font = "robotocondensed-bold.ttf", FontSize = 16,
						Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
					},
					new CuiRectTransformComponent
					{
						AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-21.202 -17.071",
						OffsetMax = "21.202 17.071"
					}
				}
			});

			container.Add(new CuiButton
			{
				Button =
				{
					Color = "1 1 1 0", Command = canPrevious ? $"ar.page {activeCategory.ToString()} {page - 1}" : ""
				},
				Text =
				{
					Text = "<", Font = "robotocondensed-bold.ttf", FontSize = 24, Align = TextAnchor.MiddleCenter,
					Color = canPrevious ? "0.8078431 0.7803922 0.7411765 1" : "0.5254902 0.5019608 0.4666667 0.7607843"
				},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-59.243 -17.071",
					OffsetMax = "-21.202 17.071"
				}
			}, Layer + ".main" + ".items.div" + ".pages", Layer + ".main" + ".items.div" + ".pages" + ".previous");

			container.Add(new CuiButton
			{
				Button =
					{Color = "1 1 1 0", Command = canNext ? $"ar.page {activeCategory.ToString()} {page + 1}" : ""},
				Text =
				{
					Text = ">", Font = "robotocondensed-bold.ttf", FontSize = 24, Align = TextAnchor.MiddleCenter,
					Color = canNext ? "0.8078431 0.7803922 0.7411765 1" : "0.5254902 0.5019608 0.4666667 0.7607843"
				},
				RectTransform =
				{
					AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "21.202 -17.071",
					OffsetMax = "59.243 17.071"
				}
			}, Layer + ".main" + ".items.div" + ".pages", Layer + ".main" + ".items.div" + ".pages" + ".next");

			CuiHelper.DestroyUi(player, Layer + ".main.items.div.pages");
			CuiHelper.AddUi(player, container);
		}

//
		private void UI_DrawCategories(BasePlayer player, ItemCategory activeCategory)
		{
			var container = new CuiElementContainer();
			container.Add(new CuiPanel
			{
				CursorEnabled = false,
				Image = {Color = "0.317 0.317 0.317 0.9137255"},
				RectTransform =
				{
					AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-209.746 -260.42", OffsetMax = "-0.09 260.42"
				}
			}, Layer, Layer + ".categoies");
			float minx = -104.83f;
			float maxx = 104.83f;
			float miny = 218.6598f;
			float maxy = 245.42f;

			for (int i = 0; i < Categories.Count; i++)
			{
				var category = Categories.ElementAtOrDefault(i);

				bool isActive = category == activeCategory;

				container.Add(new CuiButton
					{
						Button = {Color = "0 0 0 0", Command = $"ar.setcategory {category.ToString()}"},
						Text = {Text = ""},
						RectTransform =
						{
							AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{minx} {miny}",
							OffsetMax = $"{maxx} {maxy}"
						}
					}, Layer + ".categoies", Layer + ".categoies" + $".category.{i}");

				container.Add(new CuiElement
				{
					Name = Layer + ".categoies" + $".category.{i}" + ".name",
					Parent = Layer + ".categoies" + $".category.{i}",
					Components =
					{
						new CuiTextComponent
						{
							Text = category.ToString().ToUpper(), Font = "robotocondensed-bold.ttf", FontSize = 20,
							Align = TextAnchor.MiddleRight,
							Color = isActive ? "0.8078431 0.7803922 0.7411765 1" : "0.6470588 0.6235294 0.6 1"
						},
						new CuiRectTransformComponent
						{
							AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-104.83 -20.88",
							OffsetMax = "95.141 20.88"
						}
					}
				});

				miny -= 26.76f;
				maxy -= 26.76f;
			}

			CuiHelper.DestroyUi(player, Layer + ".categories");
			CuiHelper.AddUi(player, container);
		}


		private void UI_Destroy(BasePlayer player)
		{
			CuiHelper.DestroyUi(player, Layer + ".close");
			CuiHelper.DestroyUi(player, Layer);
		}

		#endregion

		#region Commands

		[ChatCommand("recboxtest")]
		private void CmdGiveRecBoxTest(BasePlayer player)
		{
			if (!player.IsAdmin)
				return;

			Item item = ItemManager.CreateByName(config._CrateRecycler.Shortname, 1000, config._CrateRecycler.SkinID);
			if (!string.IsNullOrEmpty(config._CrateRecycler.DisplayName))
				item.name = config._CrateRecycler.DisplayName;

			player.GiveItem(item);
		}

		[ChatCommand("autorectoggle")]
		private void CmdAutoRecToggle(BasePlayer player)
		{
			if (player == null)
				return;

			if (!PlayerAutoRecState.ContainsKey(player.userID))
				PlayerAutoRecState.Add(player.userID, true);

			PlayerAutoRecState[player.userID] = !PlayerAutoRecState[player.userID];

			player.ChatMessage(
				$"Autorecycling is now {(PlayerAutoRecState[player.userID] ? "<color=green>enabled</color>" : "<color=red>disabled</color>")}");
		}

		[ChatCommand("recbox")]
		private void CmdRecboxInfo(BasePlayer player)
		{
			string costInfo = "Recbox price:\n";
			foreach (var cost in config.RecboxCost)
			{
				costInfo += $"{cost.Amount}x {cost.Shortname}\n";
			}

			costInfo += "Use /recboxbuy to purchase.";
			SendReply(player, costInfo);
		}

		[ChatCommand("recboxbuy")]
		private void CmdBuyRecbox(BasePlayer player)
		{
			if (!permission.UserHasPermission(player.UserIDString, PermRecboxBuy))
			{
				SendReply(player, "You do not have permission to use this command.");
				return;
			}

			foreach (var cost in config.RecboxCost)
			{
				var itemDef = ItemManager.FindItemDefinition(cost.Shortname);
				if (itemDef == null) continue;
				var playerItemCount = player.inventory.GetAmount(itemDef.itemid);
				if (playerItemCount < cost.Amount)
				{
					SendReply(player, $"Not enough {cost.Shortname}.");
					return;
				}
			}

			foreach (var cost in config.RecboxCost)
			{
				var itemDef = ItemManager.FindItemDefinition(cost.Shortname);
				player.inventory.Take(null, itemDef.itemid, cost.Amount);
			}

			GiveRecBox(player);
			SendReply(player, "You have bought a Recbox.");
		}


		private void GiveRecBox(BasePlayer player)
		{
			Item item = ItemManager.CreateByName(config._CrateRecycler.Shortname, 1, config._CrateRecycler.SkinID);
			if (!string.IsNullOrEmpty(config._CrateRecycler.DisplayName))
				item.name = config._CrateRecycler.DisplayName;

			if (!player.inventory.GiveItem(item))
			{
				item.Drop(player.GetDropPosition(), player.GetDropVelocity());
				//Puts($"Failed to add Recbox to inventory of {player.displayName}, dropped on the ground.");
			}
			else
			{
				//Puts($"Recbox successfully given to {player.displayName}.");
			}
		}

		[ConsoleCommand("ar.togglestate")]
		private void CmdToggleState(ConsoleSystem.Arg arg)
		{
			if (arg.Player() == null || arg.Args.IsNullOrEmpty())
				return;

			if (!CanUseAction(arg.Player(), ActionType.Characteristics))
				return;

			string shortname = arg.Args[0];
			if (!bool.TryParse(arg.Args[1], out var state))
				return;

			if (!config.RecycleItems.ContainsKey(shortname))
				return;

			config.RecycleItems[shortname].IsEnabled = state;
			UI_UpdateItem(arg.Player(), shortname);

			SaveConfig();
		}

		[ConsoleCommand("recyclercrate.give")]
		private void CmdRecGive(ConsoleSystem.Arg arg)
		{
			if (arg.Player() != null)
				if (!arg.Player().IsAdmin)
					return;

			Item item = ItemManager.CreateByName(config._CrateRecycler.Shortname, 1, config._CrateRecycler.SkinID);
			if (!string.IsNullOrEmpty(config._CrateRecycler.DisplayName))
				item.name = config._CrateRecycler.DisplayName;

			if (arg.Args.IsNullOrEmpty())
			{
				if (arg.Player() == null)
					return;

				if (!arg.Player().inventory.GiveItem(item))
					item.Drop(arg.Player().GetDropPosition(), arg.Player().GetDropVelocity());
				return;
			}

			var target = FindPlayer(arg.Args[0]);

			if (target.IsNullOrEmpty())
			{
				Puts($"Player '{arg.Args[0]}' not found");
				return;
			}

			if (target.Count > 1)
			{
				Puts($"Finded many players:");
				foreach (var x in target.Select(x => x.displayName))
					Puts($" - {x}");
				return;
			}

			var pl = target.FirstOrDefault();

			if (!pl.inventory.GiveItem(item))
				item.Drop(pl.GetDropPosition(), pl.GetDropVelocity());
		}

		private List<BasePlayer> FindPlayer(string id)
		{
			List<BasePlayer> players = new List<BasePlayer>();
			players.AddRange(BasePlayer.activePlayerList.Where(x =>
				x.UserIDString == id || x.displayName.Contains(id, CompareOptions.IgnoreCase)));
			return players;
		}

		[ConsoleCommand("ar.setcategory")]
		private void CmdSetCategory(ConsoleSystem.Arg arg)
		{
			if (arg.Player() == null || arg.Args.IsNullOrEmpty())
				return;

			if (!Enum.TryParse(arg.Args[0], out ItemCategory category))
				return;

			UI_DrawCategories(arg.Player(), category);
			UI_DrawItems(arg.Player(), category);
		}

		[ConsoleCommand("ar.setstate")]
		private void CmdSetState(ConsoleSystem.Arg arg)
		{
			if (arg.Player() == null || arg.Args.IsNullOrEmpty())
				return;

			if (!bool.TryParse(arg.Args[1], out var state))
				return;

			var shortname = arg.Args[0];
			if (!config.RecycleItems.TryGetValue(shortname, out var item))
				return;
			if (!item.IsEnabled)
				return;

			SetRecyclingState(arg.Player(), shortname, state);
			UI_UpdateItem(arg.Player(), shortname);
		}

		[ConsoleCommand("ar.page")]
		private void CmdPage(ConsoleSystem.Arg arg)
		{
			if (arg.Player() == null || arg.Args.IsNullOrEmpty())
				return;

			BasePlayer player = arg.Player();
			if (!int.TryParse(arg.Args[1], out var page))
				return;

			if (!Enum.TryParse(arg.Args[0], out ItemCategory category))
				return;


			UI_DrawItems(player, category, page);
		}

		[ConsoleCommand("ar.close")]
		private void CmdClose(ConsoleSystem.Arg arg)
		{
			if (arg.Player() == null)
				return;

			UI_Destroy(arg.Player());
		}

		private void CmdAutorec(BasePlayer player)
		{
			if (!CanUseAction(player, ActionType.AutoRec))
				return;

			UI_DrawMain(player);
		}

		private void CmdOpenVirtualRecycler(BasePlayer player)
		{
			if (!CanUseAction(player, ActionType.RecVirtual))
				return;

			OpenRecycler(player);
		}

		#endregion

		#region Config

		private ConfigData config;

		private class ConfigData
		{
			[JsonProperty("Auto recycler UI commands", Order = 1)]
			public List<string> AutoRecyclerUICommands;

			[JsonProperty("Virtual recycler commands", Order = 0)]
			public List<string> VirtualRecyclerCommands;

			[JsonProperty("Crate-recycler settings", Order = 5)]
			public CrateRecycler _CrateRecycler;

			[JsonProperty("Items to Recycle", Order = 100)]
			public Dictionary<string, ItemSettings> RecycleItems { get; set; }

			[JsonProperty("Recbox cost", Order = 6)] // Hinzugef gte Konfiguration f r die Recbox-Kosten
			public List<ItemAmount> RecboxCost;
		}

		private class CrateRecycler
		{
			public string Shortname;
			public string DisplayName;
			public ulong SkinID;
		}

		private class ItemAmount
		{
			[JsonIgnore] public string GUID;

			[JsonProperty("Shortname")] public string Shortname { get; set; }

			[JsonProperty("Amount")] public int Amount { get; set; }


			[JsonProperty("Chance (0.0 - 100.0)")] public float Chance;

			[JsonProperty("Enabled")] public bool Enabled { get; set; } = true;
		}

		private class ItemSettings
		{
			[JsonProperty("Items")] public List<ItemAmount> ItemAmount;
			[JsonProperty("Is enabled?")] public bool IsEnabled;

			public IEnumerable<ItemAmount> GetItemsByCategory(ItemCategory category) =>
				ItemAmount.Where(x => ItemManager.FindItemDefinition(x.Shortname).category == category);
		}

		protected override void LoadConfig()
		{
			base.LoadConfig();
			config = Config.ReadObject<ConfigData>();
		}

		protected override void SaveConfig() => Config.WriteObject(config);

		protected override void LoadDefaultConfig()
		{
			config = new ConfigData
			{
				RecycleItems = new(),
				_CrateRecycler = new CrateRecycler()
				{
					DisplayName = "Crate-recycler",
					Shortname = "box.wooden.large",
					SkinID = 3100475476
				},
				VirtualRecyclerCommands = new()
				{
					"virtualrec",
					"vrec",
					"recvirtual"
				},
				AutoRecyclerUICommands = new()
				{
					"autorec",
					"ar",
					"autorecycler"
				},
				RecboxCost = new List<ItemAmount>() // Standardkosten f r die Recbox
				{
					new ItemAmount {Shortname = "scrap", Amount = 100} // Beispielkosten
				}
			};
		}

		#endregion

		#region Data

		private void SaveData()
		{
			Interface.Oxide.DataFileSystem.WriteObject($"{Title}/players", _players);
		}

		void LoadData()
		{
			_players = Interface.Oxide?.DataFileSystem?.ReadObject<Dictionary<ulong, List<string>>>($"{Title}/players")
			           ?? new Dictionary<ulong, List<string>>();
		}

		#endregion
	}
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя 15FPS

Сверху