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

FREE SkinBox : 1.4.6 1.4.6

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("SkinBox", "MBR", "1.4.6")]
    class SkinBox : CovalencePlugin {
        public class LootBoxHandler : MonoBehaviour {
            private StorageContainer container;
            private int page = 0;
            private bool cycling = false, tempAllow = false;
            public bool favoriteMode = false;
            private List<ulong> skins = new List<ulong>();
            public BasePlayer player {
                get;
                private set;
            }
            public Item item {
                get;
                private set;
            }
            private FPBS localFPBS {
                get;
                set;
            }
            public BaseEntity ent {
                get;
                private set;
            }
            private void Awake() {
                ent = GetComponent<BaseEntity>();
                container = GetComponent<StorageContainer>();
                InvokeHandler.Invoke(this, () => {
                    container.inventory.maxStackSize = 1;
                    container.SetFlag(BaseEntity.Flags.Open, true, false);
                }
                , 0.01f);
            }
            public void ForcePlayerToLoot(BasePlayer player) {
                this.player = player;
                container.PlayerOpenLoot(player, "generic_resizable", false);
            }
            public void Fill(List<ulong> skins) {
                EmptyBox();
                tempAllow = true;
                for (int i = 0; i < skins.Count; i++) {
                    var skin = skins[i];
                    var originalId = localFPBS?.originalItemId ?? this.item.info.itemid;
                    var invDef = ItemSkinDirectory.FindByInventoryDefinitionId((int)skin);
                    var targetId = (invDef.invItem as ItemSkin)?.Redirect?.itemid ?? originalId;
                    var hookVal = Interface.Oxide.CallHook("CanShowSkinboxSkin", player, skin, targetId, this.item);
                    if (hookVal != null && !(bool)hookVal) continue;
                    var item = ItemManager.CreateByItemID(originalId, 1, skin);
                    item.condition = this.item.condition;
                    item.maxCondition = this.item.maxCondition;
                    if (this.item.contents?.itemList != null) {
                        foreach (var attachment in this.item.contents.itemList) {
                            var newAttachment = ItemManager.Create(attachment.info, 1, 0);
                            newAttachment.maxCondition = attachment.maxCondition;
                            newAttachment.condition = attachment.condition;
                            newAttachment.skin = attachment.skin;
                            newAttachment.name = attachment.name;
                            newAttachment.MoveToContainer(item.contents);
                        }
                        //Lock attachment slots (prevents from stealing attachments)
                        item.contents.SetLocked(true);
                    }
                    var name = instance.SkinsAPI.Call<string>("GetSkinNameFromID", skin.ToString());
                    item.name = name;
                    var prev = this.item.GetHeldEntity() as BaseProjectile;
                    if (prev != null) {
                        var temp = item.GetHeldEntity() as BaseProjectile;
                        temp.primaryMagazine.contents = prev.primaryMagazine.contents;
                        temp.primaryMagazine.ammoType = prev.primaryMagazine.ammoType;
                    }
                    if (!item.MoveToContainer(container.inventory)) {
                        instance.PrintError("Couldn't move " + item.info.shortname);
                    }
                }
                tempAllow = false;
            }
            public void OnItemRemove(Item removed) {
                if (item == null || cycling) return;
                var skin = string.IsNullOrEmpty(removed.name) ? "Default skin" : removed.name;
                removed.name = item?.name ?? string.Empty;
                //so, the code below was MBR's.I changed it to the single line above.so far, this works fine - this was necessary to prevent losing original item name if you picked the same skin out
                /*/
                if (!string.IsNullOrEmpty(item.name) && removed.uid != item.uid)
                {
                    removed.name = item.name;
                }
                else removed.name = null;
                /*/
                removed.contents?.SetLocked(false);
                if (removed.uid != item.uid) {
                    var effect = new Effect("assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab", player.transform.position, default(Vector3));
                    EffectNetwork.Send(effect, player.net.connection);
                    if (favoriteMode) {
                        try {
                            if (instance.SkinFavorite?.IsLoaded ?? false) {
                                var riid = removed.info.itemid;
                                var rskin = removed.skin;
                                var f = FPBS.list.FirstOrDefault(x => x.newItemId == riid);
                                if (f != null) {
                                    riid = f.originalItemId;
                                    rskin = f.skinId;
                                }
                                instance.SkinFavorite.Call("SetFavoriteSkin", player.UserIDString, riid, rskin);
                                player.IPlayer.Message("<color=orange>" + skin + "</color> has been set as your favorite skin for " + removed.info.displayName.english);
                            }
                            else throw new Exception("FavoriteSkin plugin is missing/not loaded");
                        }
                        catch (Exception e) {
                            instance.Puts(e.Message + "\n" + e.StackTrace);
                            player.IPlayer.Message("An error occurred while setting your favorite skin!");
                        }
                    }
                }
                item = null;
                skins = new List<ulong>();
                localFPBS = null;
                EmptyBox();
                instance.DestroyCUI(player);
            }
            public void OnItemAdd(Item item) {
                if (container.inventory.itemList.Count != 1) return;
                this.item = item;
                if (this.item.position != 0) this.item.position = 0;
                page = 0;
                var full = instance.skins[this.item.info.itemid];
                if (full.Count == 0 && localFPBS != null) {
                    if (this.item.info.itemid == localFPBS.newItemId) {
                        full = instance.skins[localFPBS.originalItemId];
                    }
                }
                if (instance.permission.UserHasPermission(player.UserIDString, "skinbox.all") || debug) {
                    skins = full;
                }
                else {
                    if (instance.UserSkins?.IsLoaded ?? false) {
                        skins = (instance.UserSkins.Call<List<ulong>>("GetAllUserSkins", player.UserIDString) ?? new List<ulong>()).Where(x => full.Contains(x)).ToList();
                    }
                }
                // not sure if this ever happens
                if (!skins.Contains(0)) {
                    skins.Insert(0, 0);
                }
                skins.Sort();
                if (instance.SkinFavorite?.IsLoaded ?? false) {
                    ulong favorite = instance.SkinFavorite.Call<ulong>("GetFavoriteSkin", player.UserIDString, item.info.itemid);
                    if (favorite != 0) {
                        if (skins.Contains(favorite)) {
                            skins.Remove(favorite);
                        }
                        skins.Insert(0, favorite);
                    }
                }
                HandleChange(true);
            }
            public void HandleChange(bool instant, bool skipItems = false) {
                var index = page * ITEMS_PER_PAGE;
                if (index < 0) {
                    Interface.Oxide.LogError("Bad index: " + index + " (page: " + page + ") for " + player);
                    return;
                }
                ButtonType type = ButtonType.Favorite;
                if (index + ITEMS_PER_PAGE + 1 < skins.Count) type |= ButtonType.Next;
                if (page != 0) type |= ButtonType.Previous;
                Draw(instant, type);
                if (!skipItems) {
                    var list = skins.Where(x => x != (localFPBS != null ? localFPBS.skinId : item.skin)).ToList();
                    if (list.Count < 1) return;
                    var count = list.Count - index;
                    if (count < 0) {
                        Interface.Oxide.LogError("Bad count: " + count + ", list.Count " + list.Count + ", index: " + index + " for " + player);
                        return;
                    }
                    list = list.GetRange(index, Mathf.Min(ITEMS_PER_PAGE, count));
                    Fill(list);
                }
            }
            public void Draw(bool instant, ButtonType types) {
                if ((types & ButtonType.Next) == ButtonType.Next) {
                    //rate limit :Pepega:
                    InvokeHandler.Invoke(this, () => {
                        if (item != null) instance.DrawButton(player, true);
                    }
                    , instant ? 0f : 1f);
                }
                if ((types & ButtonType.Previous) == ButtonType.Previous) {
                    //rate limit :Pepega:
                    InvokeHandler.Invoke(this, () => {
                        if (item != null) instance.DrawButton(player, false);
                    }
                    , instant ? 0f : 1f);
                }
                if ((types & ButtonType.Favorite) == ButtonType.Favorite) {
                    //rate limit :Pepega:
                    InvokeHandler.Invoke(this, () => {
                        if (item != null) instance.DrawFavoriteButton(player, favoriteMode);
                    }
                    , instant ? 0f : 1f);
                }
            }
            public void OnLootStart(BasePlayer player) {
                if (!instance.boxes.Contains(this) && this.player == player) {
                    instance.boxes.Add(this);
                }
            }
            public void OnLootEnd(BasePlayer player) {
                if (item != null) {
                    if (player.IsDead()) {
                        item.Drop(player.transform.position, Vector3.zero);
                    }
                    else player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
                }
                if (instance.CUIs.ContainsKey(player)) {
                    instance.DestroyCUI(player);
                }
                foreach (var item in instance.boxes) {
                    if (item == this) {
                        instance.boxes.Remove(item);
                        break;
                    }
                }
                EmptyBox();
                InvokeHandler.Invoke(this, () => ent.KillMessage(), 0.2f);
            }
            private void EmptyBox() {
                cycling = true;
                //prevents onitemremove from fucking it all up
                foreach (var item in container.inventory.itemList.ToArray()) {
                    if (item.uid == this.item?.uid) continue;
                    CompletelyDestroy(item);
                }
                cycling = false;
            }
            public void UpdatePage(bool next) {
                if (next) page += 1;
                else page -= 1;
                var e = new Effect("assets/bundled/prefabs/fx/notice/item.select.fx.prefab", player.transform.position, Vector3.zero);
                EffectNetwork.Send(e, player.net.connection);
                HandleChange(false);
            }
            public void UpdateFavorite(bool value) {
                favoriteMode = value;
                HandleChange(true, true);
            }
            public bool CanAcceptItem(Item i) {
                if (i?.info == null) return false;
                if (instance.skins[i.info.itemid].Count < 1) {
                    if (item == null) {
                        var fpbs = FPBS.list.FirstOrDefault(x => x.newItemId == i.info.itemid);
                        if (fpbs == null) {
                            // We are putting in an item that can't be skinned?
                            return false;
                        }
                        localFPBS = fpbs;
                    }
                    else {
                        if (tempAllow) {
                            // Workaround for facepunchs bullshit
                            var fpbs = FPBS.list.FirstOrDefault(x => x.newItemId == i.info.itemid);
                            if (fpbs.originalItemId == item.info.itemid || fpbs.originalItemId == localFPBS?.originalItemId) {
                                return true;
                            }
                        }
                        instance.LogWarning("Retrunign lfaase");
                        return false;
                    }
                }
                return item == null || tempAllow;
            }
        }
#region Setup & Variables
        [PluginReference]
        private readonly Plugin SkinsAPI, UserSkins, SkinFavorite;
        private const int ITEMS_PER_PAGE = 47;
        private const bool debug = false;
        private const int rockId = 963906841;
        private static SkinBox instance;
        private Dictionary<BasePlayer, List<string>> CUIs = new Dictionary<BasePlayer, List<string>>();
        private Dictionary<int, List<ulong>> skins = new Dictionary<int, List<ulong>>();
        private Dictionary<BasePlayer, float> CommandCooldown = new Dictionary<BasePlayer, float>();
        private List<LootBoxHandler> boxes = new List<LootBoxHandler>();
        public enum ButtonType {
            Previous = 1 << 3, Next = 1 << 2, Favorite = 1 << 1
        }
#endregion
#region FP bullshit
        // skins that create a new item on creation
        private class FPBS {
            public int originalItemId;
            public ulong skinId;
            public int newItemId;
            public static List<FPBS> list = new List<FPBS>();
        }
#endregion
#region Hooks
        private void OnDefaultItemsReceived(PlayerInventory inventory) {
            if (inventory == null || inventory.baseEntity == null) return;
            ulong favorite = instance.SkinFavorite.Call<ulong>("GetFavoriteSkin", inventory.baseEntity.UserIDString, rockId);
            if (favorite == 0) return;
            foreach (var item in inventory.containerBelt.itemList) {
                if (item.info.shortname == "rock") {
                    var f = FPBS.list.FirstOrDefault(x => x.originalItemId == item.info.itemid && x.skinId == favorite);
                    if (f == null) {
                        item.skin = favorite;
                        item.MarkDirty();
                        BaseEntity heldEntity = item.GetHeldEntity();
                        if (heldEntity != null) {
                            heldEntity.skinID = favorite;
                            heldEntity.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                        }
                    }
                    else {
                        var pos = item.position;
                        var nItem = ItemManager.CreateByItemID(f.newItemId, 1, f.skinId);
                        CompletelyDestroy(item);
                        nItem.MoveToContainer(inventory.containerBelt, pos);
                    }
                    break;
                }
            }
        }
        private void Unload() {
            foreach (var changer in boxes.ToArray()) {
                changer.OnLootEnd(changer.player);
            }
            foreach (var player in BasePlayer.activePlayerList) {
                DestroyCUI(player);
            }
            instance = null;
        }
        ItemContainer.CanAcceptResult? CanAcceptItem(ItemContainer container, Item item, int targetPos) {
            if (container == null || item == null || container.entityOwner == null || container.entityOwner.net == null) return null;
            var handler = GetHandlerFromNetId(container.entityOwner.net.ID.Value);
            if (handler == null) return null;
            if (!handler.CanAcceptItem(item)) {
                return ItemContainer.CanAcceptResult.CannotAccept;
            }
            return null;
        }
        void OnItemRemovedFromContainer(ItemContainer container, Item item) {
            if (container == null || item == null || container.entityOwner == null) return;
            var component = container.entityOwner.GetComponent<LootBoxHandler>();
            component?.OnItemRemove(item);
        }
        void OnItemAddedToContainer(ItemContainer container, Item item) {
            if (container == null || item == null || container.entityOwner == null) return;
            var component = container.entityOwner.GetComponent<LootBoxHandler>();
            component?.OnItemAdd(item);
        }
        private void Init() {
            permission.RegisterPermission("skinbox.all", this);
            string[] cmdAliases = {
                "sb", "sbs", "skinbox", "scinbox", "skibox", "skin"
            }
            ;
            AddCovalenceCommand(cmdAliases, nameof(SkinCMD));
        }
        private void OnServerInitialized(bool first) {
            instance = this;
            if (!first) {
                if (SkinsAPI != null && SkinsAPI.IsLoaded) {
                    LoadSkinCache();
                }
            }
            else timer.Once(10f, () => {
                if (SkinsAPI == null) {
                    PrintError("SkinsAPI is missing, aborting!");
                    Interface.Oxide.UnloadPlugin(Name);
                    return;
                }
                LoadSkinCache();
            }
            );
        }
        private void OnLootEntity(BasePlayer player, BaseEntity entity) {
            var component = entity?.GetComponent<LootBoxHandler>();
            component?.OnLootStart(player);
        }
        private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity) {
            var component = entity?.GetComponent<LootBoxHandler>();
            component?.OnLootEnd(player);
        }
        private object OnItemCraftSkin(ItemCraftTask task, ItemCrafter crafter) {
            if (task == null || crafter?.owner == null) return null;
            if (!(SkinFavorite?.IsLoaded ?? false)) return null;
            if (skins[task.blueprint.targetItem.itemid].Count < 1) return null;
            //necessary?
            ulong favorite = instance.SkinFavorite.Call<ulong>("GetFavoriteSkin", crafter.owner.UserIDString, task.blueprint.targetItem.itemid);
            if (favorite != 0) return favorite;
            return null;
        }
#endregion
#region Commands
        [Command("skinbox2cuicmd")]
        private void SkinBoxCUICMD(IPlayer player, string command, string[] args) {
            var p = player.Object as BasePlayer;
            if (p == null) return;
            if (args.Length < 1) return;
            DestroyCUI(p);
            var box = GetHandlerFromPlayer(p);
            if (box == null) return;
            switch (args[0].ToLower()) {
                case "next" : {
                    box.UpdatePage(true);
                    return;
                }
                case "previous" : {
                    box.UpdatePage(false);
                    return;
                }
                case "favorite" : {
                    box.UpdateFavorite(!box.favoriteMode);
                    return;
                }
            }
        }
        private void SkinCMD(IPlayer player, string command, string[] args) {
            if (player.IsServer) {
                player.Reply("Server console cannot use this command!");
                return;
            }
            var p = player.Object as BasePlayer;
            if (p.IsDead()) {
                player.Reply("You cannot run this command while you are dead!");
                return;
            }
            if (p.GetParentEntity() != null) {
                player.Reply("You cannot use skinbox while being on a vehicle!");
                return;
            }
            if (CommandCooldown.ContainsKey(p)) {
                if (Time.realtimeSinceStartup < CommandCooldown[p]) {
                    player.Reply("You are using this command too fast, try again in " + Math.Round((CommandCooldown[p] - Time.realtimeSinceStartup), 1) + "s");
                    return;
                }
                CommandCooldown.Remove(p);
            }
            CommandCooldown.Add(p, Time.realtimeSinceStartup + 4);
            foreach (var changer in boxes) {
                if (changer.player.UserIDString == player.Id) {
                    player.Reply("You appear to be changing an item skin already, if this is not true <i>contact staff!</i>");
                    return;
                }
            }
            var pos = new Vector3(p.transform.position.x, -200, p.transform.position.z);
            var box = GameManager.server.CreateEntity("assets/prefabs/misc/halloween/coffin/coffinstorage.prefab", pos);
            if (box == null) {
                player.Reply("An error occurred while setting up your skinbox");
                return;
            }
            UnityEngine.Object.Destroy(box.GetComponent<DestroyOnGroundMissing>());
            UnityEngine.Object.Destroy(box.GetComponent<GroundWatch>());
            var comp = box.gameObject.AddComponent<LootBoxHandler>();
            if (args.Length > 0 && args[0].ToLower().StartsWith("fav")) {
                comp.favoriteMode = true;
            }
            box.Spawn();
            timer.Once(0.25f, () => {
                if (Interface.Oxide.CallHook("CanLootEntity", p, box) != null) {
                    player.Reply("You are not allowed to use the skinbox at this time");
                    comp.OnLootEnd(p);
                    return;
                }
                comp.ForcePlayerToLoot(p);
            }
            );
        }
        [Command("skinbox.listskins")]
        private void ListSkinsForItem(IPlayer player, string command, string[] args) {
            if (args.Length < 1) {
                player.Reply("Usage: skinbox.listskins <item id>");
                return;
            }
            int id;
            if (!int.TryParse(args[0], out id)) {
                player.Reply("Invalid item id");
                return;
            }
            var skins = new List<ulong>();
            if (!this.skins.TryGetValue(id, out skins)) {
                player.Reply("No skins found for this item");
                return;
            }
            player.Reply("Skins for item " + id + ": " + string.Join(", ", skins));
        }
#endregion
#region Methods
        private void LoadSkinCache() {
            var totalSkins = 0;
            foreach (var item in ItemManager.itemList) {
                var skins = SkinsAPI.Call<List<ulong>>("GetSkinsForItem", item.itemid) ?? new List<ulong>();
                if (skins.Count > 1) {
                    totalSkins += skins.Count - 1;
                }
                this.skins.Add(item.itemid, skins);
            }
            foreach (var item in ItemManager.itemList) {
                foreach (var skinId in skins[item.itemid]) {
                    ItemSkinDirectory.Skin skin = ItemSkinDirectory.FindByInventoryDefinitionId((int)skinId);
                    ItemSkin itemSkin = skin.invItem as ItemSkin;
                    if (itemSkin?.Redirect == null) {
                        continue;
                    }
                    var ns = itemSkin.Redirect.itemid;
                    FPBS.list.Add(new FPBS {
                        originalItemId = item.itemid, newItemId = ns, skinId = skinId
                    }
                    );
                }
            }
            Puts("Skin cache loaded, there are " + skins.Count + " items that have skins (" + totalSkins + " skins in total) and " + FPBS.list.Count + " weird skins");
        }
        public void DestroyCUI(BasePlayer player) {
            if (!CUIs.ContainsKey(player)) return;
            if (CUIs[player].Count > 0) {
                foreach (var id in CUIs[player]) {
                    CuiHelper.DestroyUi(player, id);
                }
                CUIs[player] = new List<string>();
            }
        }
        public LootBoxHandler GetHandlerFromNetId(ulong id) {
            foreach (var handler in boxes) {
                if (handler.ent.net.ID.Value == id) return handler;
            }
            return null;
        }
        public LootBoxHandler GetHandlerFromPlayer(BasePlayer player) {
            foreach (var handler in boxes) {
                if (handler.player?.userID == player.userID) return handler;
            }
            return null;
        }
        public static void CompletelyDestroy(Item item) {
            if (item == null) return;
            item.GetWorldEntity()?.KillMessage();
            item.GetHeldEntity()?.KillMessage();
            item.RemoveFromWorld();
            item.RemoveFromContainer();
            item.Remove();
        }
        private void DrawFavoriteButton(BasePlayer player, bool enabled) {
            var menu = new CuiElementContainer();
            var id = menu.Add(new CuiPanel {
                Image = {
                    Color = "0.0 0.0 0.0 0.0"
                }
                , RectTransform = {
                    AnchorMin = "0.65 0.005", AnchorMax = "0.90 0.065"
                }
                ,
            }
            , "Overlay");
            if (!CUIs.ContainsKey(player)) {
                CUIs.Add(player, new List<string>());
            }
            CUIs[player].Add(id);
            menu.Add(new CuiButton {
                Button = {
                    Command = "skinbox2cuicmd favorite", Color = enabled ? "0.55 0.70 0.40 0.95" : "0.7 0.1 0.2 0.95",
                }
                , RectTransform = {
                    AnchorMin = "0.00 0.00", AnchorMax = "1.00 1.00"
                }
                , Text = {
                    Text = enabled ? "Favorite mode is ON! <size=11>(skin you select will\nbe saved as favorite and displayed first next time)</size>" : "Favorite mode is OFF <size=11>(Running /skinbox fav\nstarts skinbox with favorite mode enabled)</size>", FontSize = 15, Align = TextAnchor.MiddleCenter
                }
            }
            , id);
            CuiHelper.AddUi(player, menu);
        }
        private void DrawButton(BasePlayer player, bool next) {
            var min = next ? "0.80 0.07" : "0.65 0.07";
            var max = next ? "0.90 0.13" : "0.75 0.13";
            var command = next ? "skinbox2cuicmd next" : "skinbox2cuicmd previous";
            var menu = new CuiElementContainer();
            var id = menu.Add(new CuiPanel {
                Image = {
                    Color = "0.0 0.0 0.0 0.0"
                }
                , RectTransform = {
                    AnchorMin = min, AnchorMax = max
                }
                ,
            }
            , "Overlay");
            if (!CUIs.ContainsKey(player)) {
                CUIs.Add(player, new List<string>());
            }
            CUIs[player].Add(id);
            menu.Add(new CuiButton {
                Button = {
                    Command = command, Color = "0.80 0.55 0.15 0.95",
                }
                , RectTransform = {
                    AnchorMin = "0.00 0.00", AnchorMax = "1.00 1.00"
                }
                , Text = {
                    Text = next ? "Next Page" : "Previous Page", FontSize = 15, Align = TextAnchor.MiddleCenter
                }
            }
            , id);
            CuiHelper.AddUi(player, menu);
        }
#endregion
    }
}

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