C#:
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("BackpackSystem", "TopPlugin.ru", "1.0.2")]
public class BackpackSystem : RustPlugin
{
private bool needSave = false;
public Dictionary<ulong, BackpackBox> opensBackpack = new Dictionary<ulong, BackpackBox>();
public class BackpackBox : MonoBehaviour
{
private StorageContainer storage;
private BasePlayer owner;
private Item backpack;
public void Init(StorageContainer storage, BasePlayer owner)
{
this.storage = storage;
this.owner = owner;
backpack = owner.inventory.containerWear.FindItemByItemID(21402876);
backpack.LockUnlock(true);
storage.ItemFilter(backpack, -1);
foreach (var item in owner.inventory.containerMain.itemList)
{
if(item.info.itemid == 21402876 && (item.skin == 1591970438 || item.skin == 1591973955 || item.skin == 1591975312))
item.LockUnlock(true);
}
foreach (var item in owner.inventory.containerBelt.itemList)
{
if(item.info.itemid == 21402876 && (item.skin == 1591970438 || item.skin == 1591973955 || item.skin == 1591975312))
item.LockUnlock(true);
}
}
public static BackpackBox Spawn(BasePlayer player, int size = 1)
{
player.EndLooting();
var storage = SpawnContainer(player,size,false);
var box = storage.gameObject.AddComponent<BackpackBox>();
box.Init(storage, player);
return box;
}
static int rayColl = LayerMask.GetMask("Construction", "Deployed", "Tree", "Terrain", "Resource", "World", "Water", "Default", "Prevent Building");
public static StorageContainer SpawnContainer (BasePlayer player, int size, bool die)
{
var pos = player.transform.position;
if (die)
{
RaycastHit hit;
if (Physics.Raycast(new Ray(player.GetCenter(), Vector3.down), out hit, 1000, rayColl, QueryTriggerInteraction.Ignore))
{
pos = hit.point;
}
}
else
{
pos -= new Vector3(0, 100, 0);
}
return SpawnContainer(player, size, pos);
}
private static StorageContainer SpawnContainer(BasePlayer player, int size, Vector3 position)
{
var storage = GameManager.server.CreateEntity("assets/prefabs/deployable/small stash/small_stash_deployed.prefab") as StorageContainer;
if(storage == null) return null;
storage.transform.position = position;
storage.panelName = "largewoodbox";
ItemContainer container = new ItemContainer { playerOwner = player };
container.ServerInitialize((Item)null, size);
if((int)container.uid == 0)
container.GiveUID();
storage.inventory = container;
if(!storage) return null;
storage.SendMessage("SetDeployedBy", player, (SendMessageOptions)1);
storage.Spawn();
return storage;
}
private void PlayerStoppedLooting(BasePlayer player)
{
backpack.LockUnlock(false);
foreach (var item in owner.inventory.containerMain.itemList)
{
if(item.info.itemid == 21402876 && (item.skin == 1591970438 || item.skin == 1591973955 || item.skin == 1591975312))
item.LockUnlock(false);
}
foreach (var item in owner.inventory.containerBelt.itemList)
{
if(item.info.itemid == 21402876 && (item.skin == 1591970438 || item.skin == 1591973955 || item.skin == 1591975312))
item.LockUnlock(false);
}
Interface.Oxide.RootPluginManager.GetPlugin("BackpackSystem").Call("BackpackHide", backpack.uid, player.userID);
}
public void Close()
{
ClearItems();
storage.Kill();
}
public void StartLoot()
{
storage.SetFlag(BaseEntity.Flags.Open, true, false);
owner.inventory.loot.StartLootingEntity(storage, false);
owner.inventory.loot.AddContainer(storage.inventory);
owner.inventory.loot.SendImmediate();
owner.ClientRPCPlayer(null, owner, "RPC_OpenLootPanel", storage.panelName);
storage.DecayTouch();
storage.SendNetworkUpdate();
}
public void Push(List<Item> items)
{
for (int i = items.Count - 1; i >= 0; i--)
items[i].MoveToContainer(storage.inventory);
}
public void ClearItems()
{
storage.inventory.itemList.Clear();
}
public List<Item> GetItems => storage.inventory.itemList.Where(i => i != null).ToList();
}
[ConsoleCommand("backpack.open")]
void consoleCommandBackpack(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player == null) return;
if (player.inventory.loot?.entitySource != null)
{
BackpackBox bpBox;
if (opensBackpack.TryGetValue(player.userID, out bpBox) &&
bpBox.gameObject == player.inventory.loot.entitySource.gameObject)
{
return;
}
player.EndLooting();
NextTick(() => BackpackShow(player));
return;
}
BackpackShow(player);
}
[ChatCommand("bp")]
void chatCommandBackpack(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (player.inventory.loot?.entitySource != null)
{
BackpackBox bpBox;
if (opensBackpack.TryGetValue(player.userID, out bpBox) &&
bpBox.gameObject == player.inventory.loot.entitySource.gameObject)
{
return;
}
player.EndLooting();
NextTick(() => BackpackShow(player));
return;
}
BackpackShow(player);
}
void OnServerSave()
{
if (needSave)
{
SaveData();
needSave = false;
}
}
void Unload()
{
SaveData();
}
void Init()
{
LoadData();
}
private bool? CanWearItem(PlayerInventory inventory, Item item)
{
var player = inventory.gameObject.ToBaseEntity() as BasePlayer;
if (player == null) return false;
if (player.IsNpc) return null;
if (item.info.shortname == "burlap.gloves.new")
{
var item2 = inventory.containerWear.FindItemByItemID(21402876);
if (item2 != null && (item2.skin == 1591970438 || item2.skin == 1591973955 || item2.skin == 1591975312)) return false;
}
return null;
}
List<Item> RestoreItems(List<SavedItem> sItems)
{
return sItems.Select(sItem =>
{
if (sItem.weapon) return BuildWeapon(sItem);
return BuildItem(sItem);
}).Where(i => i != null).ToList();
}
Item BuildItem(SavedItem sItem)
{
if (sItem.amount < 1) sItem.amount = 1;
var item = ItemManager.CreateByItemID(sItem.itemid, sItem.amount, sItem.skinid);
if (sItem.blueprintTarget.HasValue)
{
item.blueprintTarget = sItem.blueprintTarget.Value;
}
if (!string.IsNullOrEmpty(sItem.text))
{
item.text = sItem.text;
}
if (item.hasCondition)
{
item.condition = sItem.condition;
item.maxCondition = sItem.maxcondition;
item.busyTime = sItem.busyTime;
}
if (sItem.name != null)
{
item.name = sItem.name;
}
item.flags = sItem.flags;
FlameThrower flameThrower = item.GetHeldEntity()?.GetComponent<FlameThrower>();
if(flameThrower)
flameThrower.ammo = sItem.flamefuel;
return item;
}
Item BuildWeapon(SavedItem sItem)
{
Item item = ItemManager.CreateByItemID(sItem.itemid, 1, sItem.skinid);
if (item.hasCondition)
{
item.condition = sItem.condition;
item.maxCondition = sItem.maxcondition;
}
var weapon = item.GetHeldEntity() as BaseProjectile;
if (weapon != null)
{
var def = ItemManager.FindItemDefinition(sItem.ammotype);
weapon.primaryMagazine.ammoType = def;
weapon.primaryMagazine.contents = sItem.ammoamount;
}
if (sItem.mods != null)
foreach (var mod in sItem.mods)
item.contents.AddItem(BuildItem(mod).info, 1);
return item;
}
[HookMethod("OnItemRemove")]
void OnItemRemove(Item item)
{
if (!storedData.backpacks.ContainsKey(item.uid))
return;
var ownerPlayer = item.GetOwnerPlayer();
if (ownerPlayer == null)
return;
ownerPlayer.EndLooting();
List<SavedItem> savedItems;
if (!storedData.backpacks.TryGetValue(item.uid, out savedItems)) return;
var restoredItems = RestoreItems(savedItems);
foreach (var restoredItem in restoredItems)
{
ownerPlayer.GiveItem(restoredItem);
}
storedData.backpacks.Remove(item.uid);
}
[HookMethod("BackpackHide")]
bool BackpackHide(uint itemID, ulong playerId)
{
BackpackBox box;
if (!opensBackpack.TryGetValue(playerId, out box)) return false;
opensBackpack.Remove(playerId);
if (box == null) return false;
var items = SaveItems(box.GetItems);
if (items.Count > 0)
{
storedData.backpacks[itemID] = SaveItems(box.GetItems);
//SpawnVisual(BasePlayer.FindByID(player));
}
else { storedData.backpacks.Remove(itemID); //RemoveVisual(BasePlayer.FindByID(player));
}
box.Close();
needSave = true;
return true;
}
List<SavedItem> SaveItems(List<Item> items) => items.Select(SaveItem).ToList();
SavedItem SaveItem(Item item)
{
SavedItem iItem = new SavedItem
{
amount = item.amount,
mods = new List<SavedItem>(),
skinid = item.skin,
busyTime = item.busyTime,
text = item.text
};
if (item.IsBlueprint())
{
iItem.blueprintTarget = item.blueprintTarget;
}
iItem.flags = item.flags;
if (item.info == null) return iItem;
iItem.itemid = item.info.itemid;
iItem.weapon = false;
iItem.name = item.name;
if (item.hasCondition)
{
iItem.condition = item.condition;
iItem.maxcondition = item.maxCondition;
}
FlameThrower flameThrower = item.GetHeldEntity()?.GetComponent<FlameThrower>();
if(flameThrower != null)
iItem.flamefuel = flameThrower.ammo;
if (item.info.category.ToString() != "Weapon") return iItem;
BaseProjectile weapon = item.GetHeldEntity() as BaseProjectile;
if (weapon == null) return iItem;
if (weapon.primaryMagazine == null) return iItem;
iItem.ammoamount = weapon.primaryMagazine.contents;
iItem.ammotype = weapon.primaryMagazine.ammoType.shortname;
iItem.weapon = true;
if (item.contents != null)
foreach (var mod in item.contents.itemList)
if (mod.info.itemid != 0)
iItem.mods.Add(SaveItem(mod));
return iItem;
}
void BackpackShow(BasePlayer player)
{
var backpackSize = 0;
Item item = null;
if (player.inventory.loot?.entitySource != null) return;
item = player.inventory.containerWear.FindItemByItemID(21402876);
if (item == null || (item.skin != 1591970438ul && item.skin != 1591973955ul && item.skin != 1591975312ul))
{
SendReply(player, "<color=#afafaf>Пожалуйста, оденьте рюкзак, прежде чем пытаться его открыть!</color>");
return;
}
switch (item.name)
{
case "Маленький рюкзак":
backpackSize = 6;
break;
case "Средний рюкзак":
backpackSize = 12;
break;
case "Большой рюкзак":
backpackSize = 18;
break;
}
if (Interface.Oxide.CallHook("CanBackpackOpen", player) != null) return;
timer.Once(0.1f, () =>
{
if (!player.IsOnGround())
{
SendReply(player, "<color=#afafaf>Нельзя открывать рюкзак в полёте!</color>");
return;
}
List<SavedItem> savedItems;
List<Item> items = new List<Item>();
if (storedData.backpacks.TryGetValue(item.uid, out savedItems))
items = RestoreItems(savedItems);
BackpackBox box = BackpackBox.Spawn(player, backpackSize);
opensBackpack.Add(player.userID, box);
if (items.Count > 0)
box.Push(items);
box.StartLoot();
});
}
class StoredData
{
public Dictionary<uint, List<SavedItem>> backpacks = new Dictionary<uint, List<SavedItem>>();
}
public class SavedItem
{
public string text;
public Item.Flag flags;
public int? blueprintTarget;
public int itemid;
public float condition;
public float maxcondition;
public int amount;
public int ammoamount;
public string ammotype;
public int flamefuel;
public ulong skinid;
public string name;
public bool weapon;
public float busyTime;
public List<SavedItem> mods;
}
void SaveData()
{
BackpackInfo.WriteObject(storedData);
}
void LoadData()
{
BackpackInfo = Interface.Oxide.DataFileSystem.GetFile("Temporary/backpacks/backpack");
try
{
storedData = BackpackInfo.ReadObject<StoredData>();
}
catch
{
storedData = new StoredData();
}
}
StoredData storedData;
private DynamicConfigFile BackpackInfo;
}
}