C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Requires: GUICreator
//#define DEBUG
//#define DEBUG2
//#define DEBUG3
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Ext.Discord.DiscordObjects;
using Steamworks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using static Oxide.Plugins.GUICreator;
namespace Oxide.Plugins {
[Info("skinit", "Ohm & Bunsen", "1.5.0")]
[Description("GUI based Item skinning")]
class skinit : RustPlugin {
#region references
[PluginReference]
private Plugin ServerRewards, Economics;
private GUICreator guiCreator;
#endregion
#region global
private static skinit PluginInstance = null;
public skinit() {
PluginInstance = this;
}
DynamicConfigFile SkinsFile;
SkinsData skinsData;
DynamicConfigFile RequestsFile;
RequestData requestData;
private const int slot = 0;
#endregion
#region classes
[JsonObject(MemberSerialization.OptIn)]
public class Request {
[JsonProperty(PropertyName = "Requester Steam ID")]
public ulong userID;
[JsonProperty(PropertyName = "Skin ID")]
public ulong skinID;
[JsonProperty(PropertyName = "Category")]
public string category;
[JsonProperty(PropertyName = "Skin")]
public Skin skin;
public Request() {
}
public Request(ulong userID, ulong skinID) {
this.userID = userID;
this.skinID = skinID;
this.category = config.defaultCatName;
}
public void init(Action<Skin> callback) {
PluginInstance.skinWebRequest(skinID, (skin) => {
if (skin != null) {
this.skin = skin;
PluginInstance.saveRequestsData();
PluginInstance.guiCreator.registerImage(PluginInstance, skin.safename, skin.url, imgSizeX : config.imgRes, imgSizeY : config.imgRes);
}
callback?.Invoke(skin);
}
);
}
public void approve(string category = null) {
if (category == null) category = this.category;
PluginInstance.addSkin(skin, category);
PluginInstance.saveSkinsData();
}
public void returnToQueue() {
PluginInstance.requestData.returnRequest(this);
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Skinnable {
[JsonProperty(PropertyName = "Item Shortname")]
public string shortname;
[JsonProperty(PropertyName = "Categories")]
public List<Category> categories = new List<skinit.Category>();
public Skinnable(string shortname) {
this.shortname = shortname;
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Category {
[JsonProperty(PropertyName = "Name")]
public string name;
public string safename => Regex.Replace(name, " ", "_");
[JsonProperty(PropertyName = "Item Shortname")]
public string shortname;
[JsonProperty(PropertyName = "Require Oxide Permission")]
public bool perm = false;
[JsonProperty(PropertyName = "Skins")]
public List<Skin> skins = new List<skinit.Skin>();
public Skinnable skinnable => PluginInstance.skinsData.GetSkinnable(this.shortname);
public Category(string name, string shortname) {
this.name = name;
this.shortname = shortname;
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Skin {
[JsonProperty(PropertyName = "Name")]
public string name;
[JsonProperty(PropertyName = "original Name")]
public string title;
public string safename => Regex.Replace(title, " ", "_") + $"_{url}";
[JsonProperty(PropertyName = "Category")]
public string category;
[JsonProperty(PropertyName = "Item Shortname")]
public string shortname;
[JsonProperty(PropertyName = "Skin ID")]
public ulong id;
[JsonProperty(PropertyName = "Preview URL")]
public string url;
public Skinnable skinnable => PluginInstance.skinsData.GetSkinnable(this.shortname);
public Category categoryObject => PluginInstance.skinsData.GetCategory(this.skinnable, this.category);
public Skin(string name, string category, string shortname, ulong id, string url) {
this.title = name;
this.name = name;
this.category = category;
this.shortname = shortname;
this.id = id;
this.url = url;
}
}
public class virtualContainer : MonoBehaviour {
public BasePlayer player;
public ItemContainer itemContainer;
public uint uid;
public Item item = null;
public virtualContainer() {
}
public void init(BasePlayer player) {
#if DEBUG2
player.ChatMessage("initialized virtual container");
#endif
this.player = player;
itemContainer = new ItemContainer {
entityOwner = player, playerOwner = player, capacity = slot + 1, isServer = true, allowedContents = ItemContainer.ContentsType.Generic
}
;
itemContainer.GiveUID();
this.uid = itemContainer.uid;
}
public static virtualContainer find(BasePlayer player) {
#if DEBUG2
player.ChatMessage("finding virtual container");
#endif
virtualContainer output = null;
player.gameObject.TryGetComponent<virtualContainer>(out output);
return output;
}
public void send() {
#if DEBUG2
player.ChatMessage("sending virtual container");
#endif
if (player == null || itemContainer == null) return;
PlayerLoot loot = player.inventory.loot;
loot.Clear();
loot.PositionChecks = false;
loot.entitySource = player;
loot.itemSource = null;
loot.AddContainer(itemContainer);
loot.SendImmediate();
player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", "lantern");
PluginInstance.sendUI(this);
PluginInstance.Subscribe(nameof(CanAcceptItem));
}
public void close() {
#if DEBUG2
player.ChatMessage("closing virtual container");
#endif
if (item != null) player.GiveItem(item);
PluginInstance.closeUI(this);
Destroy(this);
}
}
#endregion
#region oxide hooks
void Init() {
permission.RegisterPermission("skinit.use", this);
permission.RegisterPermission("skinit.admin", this);
permission.RegisterPermission("skinit.free", this);
permission.RegisterPermission("skinit.attire", this);
permission.RegisterPermission("skinit.deployable", this);
permission.RegisterPermission("skinit.tool", this);
permission.RegisterPermission("skinit.weapon", this);
SkinsFile = Interface.Oxide.DataFileSystem.GetFile("skinit/skins");
loadSkinsData();
RequestsFile = Interface.Oxide.DataFileSystem.GetFile("skinit/requests");
loadRequestsData();
}
void OnServerInitialized() {
//references
guiCreator = (GUICreator)Manager.GetPlugin("GUICreator");
if (config.useServerRewards && ServerRewards == null) Puts("ServerRewards not loaded! get it at https://umod.org/plugins/server-rewards");
if ((config.useServerRewards || config.useEconomics) && Economics == null) Puts("Economics not loaded! get it at https://umod.org/plugins/economics");
if (guiCreator == null) {
Puts("GUICreator missing! This shouldn't happen");
return;
}
InitDiscord();
ServerMgr.Instance.StartCoroutine(InitApprovedSkins());
#region config processing
//re-register skin images
ServerMgr.Instance.StartCoroutine(skinsData.RegisterImages());
//add new skins
Dictionary<string, List<ulong>> toBeAdded = new Dictionary<string, List<ulong>>();
foreach (string shortname in config.skins.Keys) {
Skinnable item = skinsData.GetSkinnable(shortname);
if (item == null) {
item = new Skinnable(shortname);
skinsData.items.Add(item);
}
foreach (string category in config.skins[shortname].Keys) {
Category cat = skinsData.GetCategory(item, category);
if (cat == null) {
cat = new Category(category, item.shortname);
item.categories.Add(cat);
}
foreach (ulong id in config.skins[shortname][category]) {
if (skinsData.GetSkin(cat, id) == null) {
if (!toBeAdded.ContainsKey(cat.name)) toBeAdded.Add(cat.name, new List<ulong>());
toBeAdded[cat.name].Add(id);
}
}
}
}
foreach (string cat in toBeAdded.Keys) {
ServerMgr.Instance.StartCoroutine(AddSkins(toBeAdded[cat], cat, false));
}
//delete removed skins
skinsData.items.RemoveAll(item => !config.skins.ContainsKey(item.shortname));
foreach (Skinnable item in skinsData.items) {
item.categories.RemoveAll(cat => !config.skins[item.shortname].ContainsKey(cat.name));
foreach (Category cat in item.categories) {
cat.skins.RemoveAll(skin => !config.skins[item.shortname][cat.name].Contains(skin.id));
}
}
saveSkinsData();
//delete approved skins
List<ulong> toBeRemoved = new List<ulong>();
foreach (Skinnable item in skinsData.items) {
foreach (Category cat in item.categories) {
cat.skins.RemoveAll(skin => IsApproved(skin.id));
}
}
saveSkinsData();
foreach(ulong id in toBeRemoved) {
Puts($"purging approved skin: {id} from data and config");
RemoveSkinFromConfig(id);
}
#endregion
//commands
cmd.AddChatCommand(config.command, this, nameof(skinitCommand));
cmd.AddConsoleCommand("skinit.add", this, nameof(addCommand));
cmd.AddConsoleCommand("skinit.approved", this, nameof(approvedCommand));
//images
guiCreator.registerImage(this, "GUI_1_1", "https://i.imgur.com/jqRb4f5.jpg");
guiCreator.registerImage(this, "GUI_1_2", "https://i.imgur.com/A1Pcc45.jpg");
guiCreator.registerImage(this, "GUI_1_3", "https://i.imgur.com/rIzu5vi.jpg");
guiCreator.registerImage(this, "GUI_1_4", "https://i.imgur.com/WjF3WwR.jpg");
guiCreator.registerImage(this, "GUI_1_5", "https://i.imgur.com/SHpMWVQ.jpg");
guiCreator.registerImage(this, "GUI_1_8", "https://i.imgur.com/36EBskB.jpg");
guiCreator.registerImage(this, "GUI_1_10", "https://i.imgur.com/x53Yq2f.jpg");
guiCreator.registerImage(this, "GUI_1_11", "https://i.imgur.com/Cy961Zc.jpg");
guiCreator.registerImage(this, "GUI_1_12", "https://i.imgur.com/wdEg6lD.jpg");
guiCreator.registerImage(this, "GUI_1_13", "https://i.imgur.com/UFSftQD.jpg");
guiCreator.registerImage(this, "GUI_1_15", "https://i.imgur.com/G7B5NTh.jpg");
guiCreator.registerImage(this, "GUI_1_16", "https://i.imgur.com/CLfx3BO.jpg");
guiCreator.registerImage(this, "GUI_1_17", "https://i.imgur.com/q0sECdd.jpg");
// guiCreator.registerImage(this, "GUI_1_6", "https://i.imgur.com/jXNQyWB.jpg");
guiCreator.registerImage(this, "GUI_1_7", "https://i.imgur.com/IfsZhBv.jpg");
guiCreator.registerImage(this, "GUI_1_9", "https://i.imgur.com/gA0yP5Z.jpg");
guiCreator.registerImage(this, "GUI_1_14", "https://i.imgur.com/yHLqrQc.jpg");
guiCreator.registerImage(this, "GUI_1_Fill_1", "https://i.imgur.com/F24t7V8.jpg");
guiCreator.registerImage(this, "GUI_1_Fill_2", "https://i.imgur.com/Fae4VRR.jpg");
guiCreator.registerImage(this, "Text_1", "https://i.imgur.com/mirJ3cR.png");
guiCreator.registerImage(this, "availableSkinsPanel", "https://i.imgur.com/ZhArsw3.png");
guiCreator.registerImage(this, "previewPanel", "https://i.imgur.com/MrTYRlK.png");
guiCreator.registerImage(this, "button_ADD", "https://i.imgur.com/tbqAmyU.png");
guiCreator.registerImage(this, "button_CHECK", "https://i.imgur.com/8f81Ave.png");
guiCreator.registerImage(this, "button_CATEGORIES", "https://i.imgur.com/nvKQode.png");
guiCreator.registerImage(this, "button_RENAME", "https://i.imgur.com/Jh3QKSH.png");
guiCreator.registerImage(this, "button_REMOVE", "https://i.imgur.com/2a5zp68.png");
guiCreator.registerImage(this, "popup_REMOVE", "https://i.imgur.com/ewo1fFE.png");
guiCreator.registerImage(this, "popup_CATEGORIES", "https://i.imgur.com/tUjpJ5T.png");
guiCreator.registerImage(this, "popup_RENAME", "https://i.imgur.com/smEo4kf.png");
guiCreator.registerImage(this, "arrow_up", "https://i.imgur.com/u6Bbq5a.png");
guiCreator.registerImage(this, "arrow_down", "https://i.imgur.com/iY9Wa2A.png");
guiCreator.registerImage(this, "new_arrow_down", "https://i.imgur.com/O4uSIAy.png");
guiCreator.registerImage(this, "dropdown", "https://i.imgur.com/8QZmPFq.png");
guiCreator.registerImage(this, "popup_ADDNEW", "https://i.imgur.com/sryvzoF.png");
guiCreator.registerImage(this, "popup_ADDNEWCATEGORY", "https://i.imgur.com/X9Q4Tyb.png");
guiCreator.registerImage(this, "popup_CHECKREQUESTS", "https://i.imgur.com/jObsFrN.png");
guiCreator.registerImage(this, "popup_PROMPT", "https://i.imgur.com/6qwc5Jr.png");
guiCreator.registerImage(this, "requestButtons", "https://i.imgur.com/ns3JGeV.png");
guiCreator.registerImage(this, "popup_HISTORY", "https://i.imgur.com/0CaZijM.png");
guiCreator.registerImage(this, "lock_unlock", "https://i.imgur.com/kfqmFTR.png");
guiCreator.registerImage(this, "lock_lock", "https://i.imgur.com/4Qx4tgi.png");
guiCreator.registerImage(this, "lock_unlockgreen", "https://i.imgur.com/ZMnJgDb.png");
guiCreator.registerImage(this, "lock_lockgreen", "https://i.imgur.com/Np52FK8.png");
//lang
lang.RegisterMessages(messages, this);
//hooks
Unsubscribe(nameof(CanAcceptItem));
}
void Unload() {
foreach(BasePlayer player in BasePlayer.activePlayerList) {
virtualContainer container = virtualContainer.find(player);
if (container != null) container.close();
}
}
private void OnPlayerLootEnd(PlayerLoot loot) {
var player = loot.gameObject.GetComponent<BasePlayer>();
if (player != loot.entitySource) return;
virtualContainer container = virtualContainer.find(player);
if (container == null) return;
#if DEBUG
player.ChatMessage($"OnPlayerLootEnd: closing virtualContainer {container.player}");
#endif
container.close();
Unsubscribe(nameof(CanAcceptItem));
}
private object CanLootPlayer(BasePlayer looter, UnityEngine.Object target) {
if (looter != target) return null;
#if DEBUG2
looter.ChatMessage("CanLootPlayer: searching for virtualContainer");
#endif
var container = virtualContainer.find(looter);
if (container == null) return null;
return true;
}
ItemContainer.CanAcceptResult? CanAcceptItem(ItemContainer container, Item item, int targetPos) {
BasePlayer player = container?.GetOwnerPlayer();
if (!player) return null;
virtualContainer vContainer = virtualContainer.find(player);
if (vContainer == null) return null;
if (item?.parent?.uid == vContainer.uid) {
onItemRemoved(vContainer, item);
vContainer.item = null;
return null;
}
if (vContainer.uid != container?.uid) return null;
if (targetPos != slot) return ItemContainer.CanAcceptResult.CannotAccept;
vContainer.item = item;
onItemInserted(vContainer, item);
return null;
}
#endregion
#region UI
#region UI parameters
float FadeIn = 0.2f;
float FadeOut = 0.2f;
#endregion
//Intitialize UI, call relevant functions to start upon keyboard command
public void sendUI(virtualContainer container) {
StringBuilder sb = new StringBuilder();
if (container.player.IPlayer.HasPermission("skinit.attire")) sb.Append("attire ");
if (container.player.IPlayer.HasPermission("skinit.deployable")) sb.Append("deployables ");
if (container.player.IPlayer.HasPermission("skinit.tool")) sb.Append("tools ");
if (container.player.IPlayer.HasPermission("skinit.weapon")) sb.Append("weapons ");
string skinPermissions = sb.ToString().ToUpper();
skinPermissions = skinPermissions.Trim();
skinPermissions = Regex.Replace(skinPermissions, " ", ", ");
#if DEBUG
container.player.ChatMessage("sending UI");
#endif
GuiContainer containerGUI = new GuiContainer(this, "background");
//containerGUI.addImage("GUI_1_1", new Rectangle(0, 0, 392, 30, 1921, 1080, true), "GUI_1_1", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_2", new Rectangle(392, 0, 271, 837, 1921, 1081, true), "GUI_1_2", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_3", new Rectangle(663, 0, 562, 576, 1921, 1081, true), "GUI_1_3", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_4", new Rectangle(1225, 0, 695, 643, 1921, 1081, true), "GUI_1_4", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_5", new Rectangle(0, 30, 134, 807, 1921, 1081, true), "GUI_1_5", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_6", new Rectangle(1225, 643, 133, 89, 1921, 1081, true), "GUI_1_8", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_7", new Rectangle(1439, 643, 481, 89, 1921, 1081, true), "GUI_1_10", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_8", new Rectangle(1225, 732, 695, 322, 1921, 1081, true), "GUI_1_11", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_9", new Rectangle(134, 814, 258, 23, 1921, 1081, true), "GUI_1_12", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_10", new Rectangle(0, 837, 74, 243, 1921, 1081, true), "GUI_1_13", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_11", new Rectangle(631, 837, 32, 71, 1921, 1081, true), "GUI_1_15", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_12", new Rectangle(74, 908, 589, 172, 1921, 1081, true), "GUI_1_16", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_13", new Rectangle(663, 1054, 1257, 26, 1921, 1081, true), "GUI_1_17", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_Fill_1", new Rectangle(1204, 146, 39, 430, 1921, 1081, true), "GUI_1_Fill_1", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_Fill_2", new Rectangle(0, 0, 134, 92, 1921, 1081, true), "GUI_1_Fill_2", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
//// containerGUI.addImage("GUI_1_14", new Rectangle(134, 30, 258, 784, 1921, 1081, true), "GUI_1_6", GuiContainer.Layer.under, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_15", new Rectangle(663, 576, 562, 478, 1921, 1081, true), "GUI_1_7", GuiContainer.Layer.under, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_16", new Rectangle(1358, 643, 81, 89, 1921, 1081, true), "GUI_1_9", GuiContainer.Layer.under, null, FadeIn, FadeOut);
//containerGUI.addImage("GUI_1_17", new Rectangle(74, 837, 557, 71, 1921, 1081, true), "GUI_1_14", GuiContainer.Layer.under, null, FadeIn, FadeOut);
//containerGUI.addImage("Text_1", new Rectangle(1334, 925, 460, 121, 1920, 1080, true), "Text_1", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
containerGUI.addPanel("Text_Permissions_1", new Rectangle(80, 907, 471, 43, 1920, 1080, true, Rectangle.Anchors.BottomLeft), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText("According to your permissions, you may skin...", 15, new GuiColor(255, 255, 255, 0.3f), TextAnchor.MiddleLeft));
containerGUI.addPanel("Text_Permissions_2", new Rectangle(80, 945, 471, 43, 1920, 1080, true, Rectangle.Anchors.BottomLeft), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText($"{skinPermissions}", 18, new GuiColor(255, 255, 255, 0.3f), TextAnchor.MiddleLeft));
containerGUI.addPanel("Text_2", new Rectangle(1249, 731, 570, 50, 1920, 1080, true, Rectangle.Anchors.BottomCenter), GuiContainer.Layer.menu, new GuiColor(50, 50, 50, 1), 0, 0, new GuiText("ITEM TO BE SKINNED", 23, new GuiColor(255, 255, 255, 0.3f)));
containerGUI.display(container.player);
panelOneBackground(container.player);
buttonsLeft(container.player);
skinitButton(container);
}
//Create "SKIN-IT" button and define what occurs on click
public enum buttonStates {
idle, noSelected, noPermission, cantAfford, redundant , success
}
;
public void skinitButton(virtualContainer container, Skin activeSkin = null, Item item = null, buttonStates flag = buttonStates.idle) {
BasePlayer player = container.player;
Action<BasePlayer, string[]> Skinit = (bPlayer, input) => {
if (activeSkin == null || item == null) {
skinitButton(container, flag : buttonStates.noSelected);
}
if (item.skin == activeSkin.id) {
skinitButton(container, activeSkin, item, skinit.buttonStates.redundant);
return;
}
if (buySkin(container, item, activeSkin)) {
skinitButton(container, flag : buttonStates.success);
}
else {
if(!hasPermission(player, item, activeSkin.categoryObject)) {
skinitButton(container, activeSkin, item, flag : buttonStates.noPermission);
}
else if(getCost(player, item, activeSkin.categoryObject) > getPoints(player)) {
skinitButton(container, activeSkin, item, flag : buttonStates.cantAfford);
}
}
}
;
GuiContainer containerGUI = new GuiContainer(this, "skinitButton", "background");
Rectangle pos = new Rectangle(1585, 833, 234, 82, 1920, 1080, true, Rectangle.Anchors.BottomCenter);
if (flag == buttonStates.success) {
containerGUI.addPlainButton("checkout_success", pos, GuiContainer.Layer.menu, new GuiColor(67, 84, 37, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("SUCCESS", 30, new GuiColor(134, 190, 41, 0.8f)));
timer.Once(1f, () => // After a second launch panelOne again with default parameters
{
if (GuiTracker.getGuiTracker(player).getContainer(PluginInstance, "background") == null) return;
skinitButton(container);
}
);
}
else if (flag == buttonStates.noPermission) {
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player.transform.position);
containerGUI.addPlainButton("checkout_failure", pos, GuiContainer.Layer.menu, new GuiColor(65, 33, 32, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("NO PERMISSION", 20, new GuiColor(162, 51, 46, 0.8f)));
timer.Once(1f, () => // After a second launch panelOne again with default parameters
{
if (GuiTracker.getGuiTracker(player).getContainer(PluginInstance, "background") == null) return;
skinitButton(container, activeSkin, item);
}
);
}
else if (flag == buttonStates.cantAfford) {
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player.transform.position);
containerGUI.addPlainButton("checkout_failure", pos, GuiContainer.Layer.menu, new GuiColor(65, 33, 32, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("CAN'T AFFORD", 20, new GuiColor(162, 51, 46, 0.8f)));
timer.Once(1f, () => // After a second launch panelOne again with default parameters
{
if (GuiTracker.getGuiTracker(player).getContainer(PluginInstance, "background") == null) return;
skinitButton(container, activeSkin, item);
}
);
}
else if (flag == buttonStates.noSelected) {
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player.transform.position);
containerGUI.addPlainButton("checkout_attempt", pos, GuiContainer.Layer.menu, new GuiColor(65, 33, 32, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("NO SKIN SELECTED!", 20, new GuiColor(162, 51, 46, 0.8f)));
timer.Once(1f, () => // After a second launch panelOne again with default parameters
{
if (GuiTracker.getGuiTracker(player).getContainer(PluginInstance, "background") == null) return;
skinitButton(container);
}
);
}
else if(flag == skinit.buttonStates.redundant) {
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player.transform.position);
containerGUI.addPlainButton("checkout_redundant", pos, GuiContainer.Layer.menu, new GuiColor(65, 33, 32, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("ALREADY HAS THIS!", 20, new GuiColor(162, 51, 46, 0.8f)));
timer.Once(1f, () => {
if (GuiTracker.getGuiTracker(player).getContainer(PluginInstance, "background") == null) return;
skinitButton(container);
}
);
}
else {
containerGUI.addPlainButton("checkout", pos, GuiContainer.Layer.menu, new GuiColor(67, 84, 37, 0.8f), FadeIn = 0.05f, FadeOut = 0.05f, new GuiText("SKIN-IT!", 30, new GuiColor(134, 190, 41, 0.8f)), Skinit);
}
containerGUI.display(player);
}
//Define a function which will split a list into lists of a given size (default = 30)
public static List<List<T>> SplitIntoChunks<T>(List<T> list, int chunkSize = 30) {
if (chunkSize <= 0) {
throw new ArgumentException("chunkSize must be greater than 0.");
}
List<List<T>> retVal = new List<List<T>>();
int index = 0;
while (index < list.Count) {
int count = list.Count - index > chunkSize ? chunkSize : list.Count - index;
retVal.Add(list.GetRange(index, count));
index += chunkSize;
}
return retVal;
}
//Create background for the "Available Skins" and "Preview" panel
public void panelOneBackground(BasePlayer player) // also background for preview panel
{
GuiContainer containerGUI = new GuiContainer(this, "panelOneBackground", "background");
containerGUI.addImage("availableSkinsPanel", new Rectangle(452, 32, 1021, 451, 1920, 1080, true), "availableSkinsPanel", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
containerGUI.addImage("previewPanel", new Rectangle(1492, 32, 389, 451, 1920, 1080, true), "previewPanel", GuiContainer.Layer.menu, null, FadeIn, FadeOut);
containerGUI.addPanel("previewPanelText", new Rectangle(1501, 0, 371, 74, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText("PREVIEW", 30, new GuiColor(255, 255, 255, 1)));
containerGUI.addPanel("availableSkinsPanelText", new Rectangle(696, 0, 534, 74, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText("AVAILABLE SKINS", 30, new GuiColor(255, 255, 255, 1)));
containerGUI.display(player);
}
//Define a function which will destroy all popups upon call
public void destroyPopups(BasePlayer player) {
GuiTracker.getGuiTracker(player).destroyGui(this, "popupRemove");
GuiTracker.getGuiTracker(player).destroyGui(this, "popupRename");
GuiTracker.getGuiTracker(player).destroyGui(this, "popupCategories");
GuiTracker.getGuiTracker(player).destroyGui(this, "categorySelection");
GuiTracker.getGuiTracker(player).destroyGui(this, "dropdown");
GuiTracker.getGuiTracker(player).destroyGui(this, "popupAddnew");
GuiTracker.getGuiTracker(player).destroyGui(this, "popupReviewRequests");
GuiTracker.getGuiTracker(player).destroyGui(this, "popupPendingRequests");
GuiTracker.getGuiTracker(player).destroyGui(this, "suggestNewStepOne");
GuiTracker.getGuiTracker(player).destroyGui(this, "suggestNewStepTwo");
GuiTracker.getGuiTracker(player).destroyGui(this, "suggestNewStepThree");
}
//Populate Available Skins with Pages of 30 Items Each and Right/Left Functionality
public void availableSkins(BasePlayer player, Item item, List<List<Skin>> skinListOfLists, int activeSkin = 0, int page = 0) {
double OriginX = 487;
double xSpacing;
double OriginY;
double OriginY1 = 87;
double OriginY2 = 210;
double OriginY3 = 339;
double Height = 95;
double maximumWidth = 950;
int picturesEachRow = 10;
int numberOfRows = 3;
int totalPictures = picturesEachRow * numberOfRows;
double widthEach = maximumWidth / picturesEachRow;
List<Skin> skinList = skinListOfLists[page];
GuiContainer containerGUI = new GuiContainer(this, "panelOne", "categories");
int i = 0;
foreach (Skin s in skinList) {
int index = i;
Action<BasePlayer, string[]> callback = (bPlayer, input) => {
availableSkins(player, item, skinListOfLists, activeSkin = index, page);
//staffOnlyButtonsRight(player, skinList[index]);
previewPanel(bPlayer, item, skinList[index]);
skinitButton(virtualContainer.find(player), skinList[index], item);
destroyPopups(player);
}
;
if (i < picturesEachRow) {
xSpacing = OriginX + (widthEach * i);
OriginY = OriginY1;
containerGUI.addImage($"picture{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), skinList[i].safename, GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton($"button{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), callback);
}
else if (i >= picturesEachRow && i < (picturesEachRow * 2)) {
xSpacing = (OriginX + (widthEach * i)) - (widthEach * picturesEachRow);
OriginY = OriginY2;
containerGUI.addImage($"picture{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), skinList[i].safename, GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton($"button{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), callback);
}
else if (i < totalPictures) {
xSpacing = (OriginX + (widthEach * i)) - ((widthEach * picturesEachRow) * 2);
OriginY = OriginY3;
containerGUI.addImage($"picture{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), skinList[i].safename, GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton($"button{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), callback);
}
i++;
}
Action<BasePlayer, string[]> GoRight = (bPlayer, input) => {
if (page == skinListOfLists.Count - 1) {
page = 0;
availableSkins(player, item, skinListOfLists, activeSkin = 0, page);
destroyPopups(player);
}
else {
page += 1;
availableSkins(player, item, skinListOfLists, activeSkin = 0, page);
destroyPopups(player);
}
}
;
Action<BasePlayer, string[]> GoLeft = (bPlayer, input) => {
if (page == 0) {
page = skinListOfLists.Count - 1;
availableSkins(player, item, skinListOfLists, activeSkin = 0, page);
destroyPopups(player);
}
else {
page -= 1;
availableSkins(player, item, skinListOfLists, activeSkin = 0, page);
destroyPopups(player);
}
}
;
if (skinListOfLists.Count > 1) {
containerGUI.addPlainButton("goRight", new Rectangle(1437, 230, 56, 56, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn, FadeOut, new GuiText(">>", 25, new GuiColor(255, 255, 255, 0.8f)), GoRight);
containerGUI.addPlainButton("goLeft", new Rectangle(431, 230, 56, 56, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn, FadeOut, new GuiText("<<", 25, new GuiColor(255, 255, 255, 0.8f)), GoLeft);
}
containerGUI.display(player);
}
//Populate Preview Panel with Selected Skin from Available Skins
public void previewPanel(BasePlayer player, Item item, Skin skin) {
GuiContainer containerGUI = new GuiContainer(this, "previewPanel", "panelOne");
containerGUI.addImage("previewPicture", new Rectangle(1520, 66, 332, 333, 1920, 1080, true), skin.safename, GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPanel("previewPictureText", new Rectangle(1501, 399, 371, 74, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText($"{skin.name}", 20, new GuiColor(255, 255, 255, 0.5f)));
containerGUI.addPanel("Text_CostToSkin", new Rectangle(1349, 690, 426, 32, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText($"COST TO SKIN: {getCost(player, item, skin.categoryObject)}", 19, new GuiColor(255, 255, 255, 0.4f), TextAnchor.MiddleLeft));
containerGUI.display(player);
staffOnlyButtonsRight(player, skin);
}
public void sendCategories(BasePlayer player, Item item, List<Category> categoriesList, int activeCategory = 0, int page = 0) {
double OriginY = 494;
double Height = 46;
double maximumWidth = 1429;
double OriginX = 452;
int fontSize = 15;
bool isStaff = isAdmin(player);
// Placeholder to make category padlock appear
string lockImage = "lock_lock";
List<List<Category>> ListOfCategories = SplitIntoChunks<Category>(categoriesList, 5);
List<Category> activeCategoriesList = ListOfCategories[page];
double widthEach = maximumWidth / activeCategoriesList.Count;
GuiContainer containerGUI = new GuiContainer(this, "categories", "background");
containerGUI.addPanel("Text_AccountBalance", new Rectangle(1349, 790, 426, 35, 1920, 1080, true, Rectangle.Anchors.BottomCenter), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), 0, 0, new GuiText($"ACCOUNT BALANCE: {getPoints(player)}", 19, new GuiColor(255, 255, 255, 0.4f), TextAnchor.MiddleLeft));
int i = 0;
foreach (Category Cat in activeCategoriesList) {
double xSpacing = OriginX + (widthEach * i);
double xSpacingIndented = xSpacing+(widthEach*.025);
int index = i;
Action<BasePlayer, string[]> callback = (bPlayer, input) => {
if (activeCategory == index) return;
sendCategories(bPlayer, item, categoriesList, index, page);
}
;
Action<BasePlayer, string[]> lockChange = (bPlayer, input) => {
toggleCategoryPerm(Cat);
sendCategories(player, item, categoriesList, activeCategory, page);
}
;
if (isStaff == true && Cat.name != config.defaultCatName) {
if (Cat.perm) {
lockImage = "lock_lock";
}
else {
lockImage = "lock_unlock";
}
}
if (i == activeCategory) {
containerGUI.addPlainButton($"category_{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(67, 84, 37, 0.8f), FadeIn, FadeOut, new GuiText(Cat.name.ToUpper(), fontSize, new GuiColor(134, 190, 41, 0.8f)), callback);
if (isStaff == true && Cat.name != config.defaultCatName) containerGUI.addButton($"padlockbutton_{i}", new Rectangle(xSpacingIndented, OriginY, 25, 40, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn, FadeOut, new GuiText("", fontSize, new GuiColor(0, 0, 0, 0)), lockChange, imgName : $"{lockImage}green");
}
else {
containerGUI.addPlainButton($"category_{i}", new Rectangle(xSpacing, OriginY, widthEach, Height, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn, FadeOut, new GuiText(Cat.name.ToUpper(), fontSize, new GuiColor(255, 255, 255, 0.8f)), callback);
if (isStaff == true && Cat.name != config.defaultCatName) containerGUI.addButton($"padlockbutton_{i}", new Rectangle(xSpacingIndented, OriginY, 25, 40, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn, FadeOut, new GuiText("", fontSize, new GuiColor(0, 0, 0, 0)), lockChange, imgName : lockImage);
}
i++;
}
Action<BasePlayer, string[]> goUp = (bPlayer, input) => {
sendCategories(player, item, categoriesList, activeCategory, page + 1);
}
;
Action<BasePlayer, string[]> goDown = (bPlayer, input) => {
sendCategories(player, item, categoriesList, activeCategory, page - 1);
}
;
if(page < ListOfCategories.Count -1) containerGUI.addPlainButton("goUp", new Rectangle(maximumWidth+OriginX, OriginY, 46, 46, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(74, 29, 33, 0), FadeIn, FadeOut, new GuiText(">>", 20, new GuiColor(255, 255, 255, 0.5f)), goUp);
if(page > 0) containerGUI.addPlainButton("goDown", new Rectangle(OriginX-50, OriginY, 46, 46, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(74, 29, 33, 0), FadeIn, FadeOut, new GuiText("<<", 20, new GuiColor(255, 255, 255, 0.5f)), goDown);
containerGUI.display(player);
int whereYouAre = (page * 5) + activeCategory;
sendSkins(player, item, categoriesList[whereYouAre]);
}
public void sendSkins(BasePlayer player, Item item, Category category) {
List<List<Skin>> ListOfLists = SplitIntoChunks<Skin>(category.skins, 30);
availableSkins(player, item, ListOfLists);
}
//Create staff-only buttons to the right
public void staffOnlyButtonsRight(BasePlayer player, Skin activeSkin) // Creates buttons for staff only to see when clicking on an item
{
bool isStaff = isAdmin(player);
if (isStaff == true) {
GuiContainer containerGUI = new GuiContainer(this, "buttonsRight", "categories");
// Function when you click the remove button
Action<BasePlayer, string[]> removeSkin = (bPlayer, input) => {
if (GuiTracker.getGuiTracker(player).getContainer(this, "popupRemove") == null) {
destroyPopups(player);
popupRemove(player, activeSkin);
}
else {
destroyPopups(player);
}
}
;
// Function when you click the rename button
Action<BasePlayer, string[]> renameSkin = (bPlayer, input) => {
if (GuiTracker.getGuiTracker(player).getContainer(this, "popupRename") == null) {
destroyPopups(player);
popupRename(player, activeSkin);
}
else {
destroyPopups(player);
}
}
;
// Function when you click the categories button
Action<BasePlayer, string[]> categorySkin = (bPlayer, input) => {
if (GuiTracker.getGuiTracker(player).getContainer(this, "popupCategories") == null) {
destroyPopups(player);
popupCategories(player, activeSkin);
}
else {
destroyPopups(player);
}
}
;
// Button to change category of skin
containerGUI.addImage("categories_image", new Rectangle(1539, 351, 67, 67, 1920, 1080, true), "button_CATEGORIES", GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton("categories_button", new Rectangle(1539, 351, 67, 67, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), categorySkin);
// Button to rename skin
containerGUI.addImage("rename_image", new Rectangle(1653, 354, 62, 62, 1920, 1080, true), "button_RENAME", GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton("rename_button", new Rectangle(1653, 354, 62, 62, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), renameSkin);
// Button to remove skin
containerGUI.addImage("remove_image", new Rectangle(1765, 354, 62, 62, 1920, 1080, true), "button_REMOVE", GuiContainer.Layer.menu, null, FadeIn = 0.25f, FadeIn = 0.25f);
containerGUI.addPlainButton("remove_button", new Rectangle(1765, 354, 62, 62, 1920, 1080, true), GuiContainer.Layer.menu, new GuiColor(0, 0, 0, 0), FadeIn = 0, FadeIn = 0, new GuiText("", 15, new GuiColor(255, 255, 255, 0.8f)), removeSkin);
containerGUI.display(player);
}
}
//Define what happens when you click remove, rename, or recategorize buttons
// Popup for when you click the remove button
public void popupRemove(BasePlayer player, Skin activeSkin) {
if (GuiTracker.getGuiTracker(player).getContainer(this, "popupRemove") == null) {
destroyPopups(player);
GuiContainer containerGUI = new GuiContainer(this, "popupRemove", "background");
Skin skin = activeSkin;
Action<BasePlayer, string[]> confirm = (bPlayer, input) => {
PluginInstance.removeSkin(skin);
destroyPopups(player);
prompt(player, $"Removed {activeSkin.name}", "SKIN REMOVED");
virtualContainer container = virtualContainer.find(player);
if (skinsData.GetSkinnable(container.item.info.shortname) != null) onItemInserted(container, container.item);
else onItemRemoved(container, container.item);
}
;
Action<BasePlayer, string[]> cancel = (bPlayer, input) => {
destroyPopups(player);
staffOnlyButtonsRight(player, activeSkin);
}
// ... [Code preview truncated due to length. Full source in attached file] ...