C#:
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using System.Collections;
using System.Linq;
using System;
namespace Oxide.Plugins {
[Info("XSkinMenu", "rustmods.ru", "1.0.12")]
class XSkinMenu : RustPlugin {
private void InitializeLang() {
lang.RegisterMessages(new Dictionary<string, string> {
["TITLE"]
= "SKIN MENU", ["SETINFO"] = "YOU CAN CUSTOMIZE THE MENU DEPENDING ON THE SITUATION!", ["ERRORSKIN"] = "THE SKIN YOU CHOSE CAN BE CHANGED ONLY IN THE INVENTORY OR WHEN CRAFTING!", ["CLEARALL"] = "RESET ALL SELECTED SKINS", ["NOPERM"] = "No permissions!", ["NEXT"] = "NEXT", ["BACK"] = "BACK", ["weapon"] = "WEAPON", ["construction"] = "CONSTRUCTION", ["item"] = "ITEM", ["attire"] = "ATTIRE", ["tool"] = "TOOL", ["transport"] = "TRANSPORT", ["inventory"] = "CHANGE SKIN IN INVENTORY", ["entity"] = "CHANGE SKIN ON OBJECTS", ["craft"] = "CHANGE SKIN WHEN CRAFTING", ["clear"] = "CHANGE SKIN WHEN DELETING", ["give"] = "SKIN CHANGE WHEN DROP IN INVENTORY", ["friends"] = "ALLOW FRIENDS TO CHANGE YOUR SKINS"
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["TITLE"]
= "МЕНЮ СКИНОВ", ["SETINFO"] = "ВЫ МОЖЕТЕ КАСТОМНО НАСТРАИВАТЬ МЕНЮ В ЗАВИСИМОСТИ ОТ СИТУАЦИИ!", ["ERRORSKIN"] = "ВЫБРАННЫЙ ВАМИ СКИН МОЖНО ИЗМЕНИТЬ ТОЛЬКО В ИНВЕНТАРЕ ИЛИ ПРИ КРАФТЕ!", ["CLEARALL"] = "СБРОСИТЬ ВСЕ ВЫБРАННЫЕ СКИНЫ", ["NOPERM"] = "Недостаточно прав!", ["NEXT"] = "ДАЛЕЕ", ["BACK"] = "НАЗАД", ["weapon"] = "ОРУЖИЕ", ["construction"] = "СТРОИТЕЛЬСТВО", ["item"] = "ПРЕДМЕТЫ", ["attire"] = "ОДЕЖДА", ["tool"] = "ИНСТРУМЕНТЫ", ["transport"] = "ТРАНСПОРТ", ["inventory"] = "ПОМЕНЯТЬ СКИН В ИНВЕНТАРЕ", ["entity"] = "ПОМЕНЯТЬ СКИН НА ПРЕДМЕТАХ", ["craft"] = "ПОМЕНЯТЬ СКИН ПРИ КРАФТЕ", ["clear"] = "ПОМЕНЯТЬ СКИН ПРИ УДАЛЕНИИ", ["give"] = "ПОМЕНЯТЬ СКИН ПРИ ПОПАДАНИИ В ИНВЕНТАРЬ", ["friends"] = "РАЗРЕШИТЬ ДРУЗЬЯМ ИЗМЕНЯТЬ ВАШИ СКИНЫ"
}
, this, "ru");
lang.RegisterMessages(new Dictionary<string, string> {
["TITLE"]
= "МЕНЮ СКІНІВ КРУТОГО СЕРВЕРУ", ["SETINFO"] = "ВИ МОЖЕТЕ КАСТОМНО НАЛАШТУВАТИ МЕНЮ В ЗАЛЕЖНОСТІ ВІД СИТУАЦІЇ!", ["ERRORSKIN"] = "ВИБРАНИЙ ВАМИ СКІН МОЖНА ЗМІНИТИ ТІЛЬКИ В ІНВЕНТАРІ АБО ПРИ КРАФТІ!", ["CLEARALL"] = "СКИНУТИ ВСІ ОБРАНІ СКІНИ", ["NOPERM"] = "Недостатньо прав!", ["NEXT"] = "ДАЛІ", ["BACK"] = "НАЗАД", ["weapon"] = "ЗБРОЯ", ["construction"] = "БУДІВНИЦТВО", ["item"] = "ПРЕДМЕТИ", ["attire"] = "ОДЯГ", ["tool"] = "ІНСТРУМЕНТИ", ["transport"] = "ТРАНСПОРТ", ["inventory"] = "ЗМІНИТИ СКІН В ІНВЕНТАРІ", ["entity"] = "ЗМІНИТИ СКІН НА ПРЕДМЕТАХ", ["craft"] = "ЗМІНИТИ СКІН ПРИ КРАФТІ", ["clear"] = "ЗМІНИТИ СКІН ПРИ ВИДАЛЕННІ", ["give"] = "ЗМІНИТИ СКІН ПРИ ПОТРАПЛЯННІ В ІНВЕНТАР", ["friends"] = "ДОЗВОЛИТИ ДРУЗЯМ ЗМІНЮВАТИ ВАШІ СКІНИ"
}
, this, "uk");
lang.RegisterMessages(new Dictionary<string, string> {
["TITLE"]
= "MENÚ COOL SERVER SKINS", ["SETINFO"] = "¡PUEDES PERSONALIZAR EL MENÚ DEPENDIENDO DE LA SITUACIÓN!", ["ERRORSKIN"] = "¡LA PIEL QUE ELIGIÓ SE PUEDE CAMBIAR SOLO EN EL INVENTARIO O AL CREAR!", ["CLEARALL"] = "RESTABLECER TODAS LAS PIELES SELECCIONADAS", ["NOPERM"] = "¡No permisos!", ["NEXT"] = "PRÓXIMO", ["BACK"] = "ESPALDA", ["weapon"] = "ARMA", ["construction"] = "CONSTRUCCIÓN", ["item"] = "ARTÍCULO", ["attire"] = "ATUENDO", ["tool"] = "HERRAMIENTA", ["transport"] = "TRANSPORTE", ["inventory"] = "CAMBIO DE PIEL EN INVENTARIO", ["entity"] = "CAMBIAR LA PIEL DE LOS OBJETOS", ["craft"] = "CAMBIA DE PIEL AL CREAR", ["clear"] = "CAMBIAR LA PIEL AL ELIMINAR", ["give"] = "CAMBIO DE PIEL AL CAER EN EL INVENTARIO", ["friends"] = "PERMITE QUE AMIGOS CAMBIEN TUS SKINS"
}
, this, "es-ES");
}
private void GenerateItems() {
if (config.Setting.UpdateSkins) foreach (var pair in Rust.Workshop.Approved.All) {
if (pair.Value == null || pair.Value.Skinnable == null) continue;
ulong skinID = pair.Value.WorkshopdId;
string item = pair.Value.Skinnable.ItemName;
if (item.Contains("lr300")) item = "rifle.lr300";
if (!StoredDataSkins.ContainsKey(item)) StoredDataSkins.Add(item, new List<ulong>());
if (!StoredDataSkins[item].Contains(skinID)) StoredDataSkins[item].Add(skinID);
}
if (config.Setting.UpdateSkinsFacepunch) foreach (ItemDefinition item in ItemManager.GetItemDefinitions()) {
foreach (var skinID in ItemSkinDirectory.ForItem(item).Select(skin => Convert.ToUInt64(skin.id))) {
if (!StoredDataSkins.ContainsKey(item.shortname)) StoredDataSkins.Add(item.shortname, new List<ulong>());
if (!StoredDataSkins[item.shortname].Contains(skinID)) StoredDataSkins[item.shortname].Add(skinID);
}
}
Interface.Oxide.DataFileSystem.WriteObject("XDataSystem/XSkinMenu/Skins", StoredDataSkins);
}
[ConsoleCommand("skin_c")]
private void ccmdCategoryS(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.use")) {
SendReply(player, lang.GetMessage("NOPERM", this, player.UserIDString));
return;
}
if (Cooldowns.ContainsKey(player)) if (Cooldowns[player].Subtract(DateTime.Now).TotalSeconds >= 0) return;
Effect x = new Effect("assets/bundled/prefabs/fx/notice/loot.drag.grab.fx.prefab", player, 0, new Vector3(), new Vector3());
Effect z = new Effect("assets/bundled/prefabs/fx/weapons/survey_charge/survey_charge_stick.prefab", player, 0, new Vector3(), new Vector3());
switch (args.Args[0]) {
case "category" : {
CategoryGUI(player, int.Parse(args.Args[2]));
ItemGUI(player, args.Args[1]);
EffectNetwork.Send(x, player.Connection);
Cooldowns[player] = DateTime.Now.AddSeconds(0.5f);
break;
}
case "skin" : {
SkinGUI(player, args.Args[1]);
EffectNetwork.Send(x, player.Connection);
CuiHelper.DestroyUi(player, ".ItemGUI");
Cooldowns[player] = DateTime.Now.AddSeconds(0.5f);
break;
}
case "setskin" : {
string item = args.Args[1];
ulong skin = ulong.Parse(args.Args[2]);
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.skinchange") || !StoredData[player.userID].Skins.ContainsKey(item)) return;
Effect y = new Effect("assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab", player, 0, new Vector3(), new Vector3());
StoredData[player.userID].Skins[item] = skin;
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.inventory")) SendReply(player, lang.GetMessage("NOPERM", this, player.UserIDString));
else {
if (StoredData[player.userID].ChangeSI) SetSkinItem(player, item, skin);
if (config.GUI.SkinUP) SkinGUI(player, item, int.Parse(args.Args[3]));
}
EffectNetwork.Send(y, player.Connection);
Cooldowns[player] = DateTime.Now.AddSeconds(1.5f);
// Здесь не трогать!!! =)
break;
}
case "clear" : {
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.skinchange")) return;
string item = args.Args[1];
StoredData[player.userID].Skins[item] = 0;
CuiHelper.DestroyUi(player, $".I + {args.Args[2]}");
if (StoredData[player.userID].ChangeSCL) SetSkinItem(player, item, 0);
if (config.GUI.MainSkin) ItemGUI(player, args.Args[3], int.Parse(args.Args[4]));
EffectNetwork.Send(z, player.Connection);
Cooldowns[player] = DateTime.Now.AddSeconds(0.5f);
break;
}
case "clearall" : {
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.skinchange")) return;
StoredData[player.userID].Skins.Clear();
foreach (var skin in StoredDataSkins) StoredData[player.userID].Skins.Add(skin.Key, 0);
GUI(player);
EffectNetwork.Send(z, player.Connection);
Cooldowns[player] = DateTime.Now.AddSeconds(2.5f);
break;
}
}
}
[PluginReference]
private Plugin ImageLibrary;
private object OnItemSkinChange(int skinID, Item item, StorageContainer container, BasePlayer player) {
if (config.Setting.RepairBench && config.Setting.Blacklist.Contains(item.skin)) {
EffectNetwork.Send(new Effect("assets/bundled/prefabs/fx/invite_notice.prefab", player, 0, new Vector3(), new Vector3()), player.Connection);
return false;
}
else return null;
}
protected override void LoadDefaultConfig() => config = SkinConfig.GetNewConfiguration();
private void OnPlayerRespawned(BasePlayer player) {
if (config.Setting.ReskinRespawn) timer.Once(2, () => {
var items = player?.inventory?.AllItems();
if (items != null) foreach (Item item in items) if (StoredData[player.userID].Skins.ContainsKey(item.info.shortname)) SetSkinCraftGive(player, item);
}
);
}
[ConsoleCommand("xskin")]
private void ccmdAdmin(ConsoleSystem.Arg args) {
if (args.Player() == null || args.Player().IsAdmin) {
string item = args.Args[1];
if (!StoredDataSkins.ContainsKey(item)) {
PrintWarning($"Не найдено предмета <{item}> в списке!");
return;
}
switch (args.Args[0]) {
case "add" : {
ulong skinID = ulong.Parse(args.Args[2]);
if (StoredDataSkins[item].Contains(skinID)) PrintWarning($"Скин <{skinID}> уже есть в списке скинов предмета <{item}>!");
else {
StoredDataSkins[item].Add(skinID);
PrintWarning($"Скин <{skinID}> успешно добавлен в список скинов предмета <{item}>!");
}
break;
}
case "remove" : {
ulong skinID = ulong.Parse(args.Args[2]);
if (StoredDataSkins[item].Contains(skinID)) {
StoredDataSkins[item].Remove(skinID);
PrintWarning($"Скин <{skinID}> успешно удален из списка скинов предмета <{item}>!");
}
else PrintWarning($"Скин <{skinID}> не найден в списке скинов предмета <{item}>!");
break;
}
case "remove_ui" : {
ulong skinID = ulong.Parse(args.Args[2]);
if (StoredDataSkins[item].Contains(skinID)) {
BasePlayer player = args.Player();
if (player != null) {
StoredDataSkins[item].Remove(skinID);
if (config.GUI.DelSkinUP) SkinGUI(player, item, int.Parse(args.Args[3]));
EffectNetwork.Send(new Effect("assets/bundled/prefabs/fx/weapons/survey_charge/survey_charge_stick.prefab", player, 0, new Vector3(), new Vector3()), player.Connection);
PrintWarning($"Скин <{skinID}> успешно удален из списка скинов предмета <{item}>!");
}
}
else PrintWarning($"Скин <{skinID}> не найден в списке скинов предмета <{item}>!");
break;
}
case "list" : {
if (StoredDataSkins[item].Count == 0) {
PrintWarning($"Список скинов предмета <{item}> пуст!");
return;
}
string skinslist = $"Список скинов предмета <{item}>:\n";
foreach (ulong skinID in StoredDataSkins[item]) skinslist += $"\n{skinID}";
PrintWarning(skinslist);
break;
}
case "clearlist" : {
if (StoredDataSkins[item].Count == 0) {
PrintWarning($"Список скинов предмета <{item}> уже пуст!");
return;
}
else {
StoredDataSkins[item].Clear();
PrintWarning($"Список скинов предмета <{item}> успешно очищен!");
}
break;
}
}
Interface.Oxide.DataFileSystem.WriteObject("XDataSystem/XSkinMenu/Skins", StoredDataSkins);
}
}
private void CategoryGUI(BasePlayer player, int page = 0) {
CuiHelper.DestroyUi(player, ".SkinBUTTON");
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-497.5 187.5", OffsetMax = "497.5 222.5"
}
, Image = {
Color = "0 0 0 0"
}
}
, ".SGUI", ".SkinBUTTON");
int x = 0, count = config.Category.Count;
foreach (var category in config.Category) {
string color = page == x ? config.GUI.ActiveColor : config.GUI.InactiveColor;
double offset = -(81 * count--) + -(2.5 * count--);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{offset} -17.5", OffsetMax = $"{offset + 162} 17.5"
}
, Button = {
Color = config.GUI.CategoryColor, Material = "assets/icons/greyout.mat", Command = $"skin_c category {category.Key} {x}"
}
, Text = {
Text = lang.GetMessage(category.Key, this, player.UserIDString), Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 18, Color = "0.750927 0.750927 0.750927 1"
}
}
, ".SkinBUTTON", ".BUTTON");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 0", OffsetMax = "0 1.5"
}
, Image = {
Color = color, Material = "assets/icons/greyout.mat"
}
}
, ".BUTTON");
x++;
}
CuiHelper.AddUi(player, container);
}
public Dictionary<string, List<ulong>> StoredDataSkins = new Dictionary<string, List<ulong>>();
protected override void SaveConfig() => Config.WriteObject(config);
private void Unload() {
foreach (BasePlayer player in BasePlayer.activePlayerList) {
SaveData(player);
CuiHelper.DestroyUi(player, ".GUIS");
}
Interface.Oxide.DataFileSystem.WriteObject("XDataSystem/XSkinMenu/Friends", StoredDataFriends);
}
private Dictionary<ulong, bool> StoredDataFriends = new Dictionary<ulong, bool>();
private Dictionary<BasePlayer, DateTime> Cooldowns = new Dictionary<BasePlayer, DateTime>();
[ConsoleCommand("skin_s")]
private void ccmdSetting(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.setting")) {
SendReply(player, lang.GetMessage("NOPERM", this, player.UserIDString));
return;
}
if (Cooldowns.ContainsKey(player)) if (Cooldowns[player].Subtract(DateTime.Now).TotalSeconds >= 0) return;
Effect x = new Effect("assets/bundled/prefabs/fx/notice/loot.drag.grab.fx.prefab", player, 0, new Vector3(), new Vector3());
switch (args.Args[0]) {
case "open" : {
SettingGUI(player);
break;
}
case "inventory" : {
StoredData[player.userID].ChangeSI = !StoredData[player.userID].ChangeSI;
SettingGUI(player);
break;
}
case "entity" : {
StoredData[player.userID].ChangeSE = !StoredData[player.userID].ChangeSE;
SettingGUI(player);
break;
}
case "craft" : {
StoredData[player.userID].ChangeSC = !StoredData[player.userID].ChangeSC;
SettingGUI(player);
break;
}
case "clear" : {
StoredData[player.userID].ChangeSCL = !StoredData[player.userID].ChangeSCL;
SettingGUI(player);
break;
}
case "give" : {
StoredData[player.userID].ChangeSG = !StoredData[player.userID].ChangeSG;
SettingGUI(player);
break;
}
case "friends" : {
StoredDataFriends[player.userID] = !StoredDataFriends[player.userID];
SettingGUI(player);
break;
}
}
EffectNetwork.Send(x, player.Connection);
Cooldowns[player] = DateTime.Now.AddSeconds(0.5f);
}
private void SettingGUI(BasePlayer player) {
CuiHelper.DestroyUi(player, ".SettingGUI");
CuiHelper.DestroyUi(player, ".SkinGUI");
CuiHelper.DestroyUi(player, ".ItemGUI");
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-502.5 -270", OffsetMax = "502.5 177.5"
}
, Image = {
Color = config.GUI.BColor3
}
}
, ".SGUI", ".SettingGUI");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-300 -105", OffsetMax = "300 -80"
}
, Text = {
Text = lang.GetMessage("SETINFO", this, player.UserIDString), Align = TextAnchor.LowerCenter, Font = "robotocondensed-regular.ttf", FontSize = 12, Color = "0.750927 0.750927 0.750927 0.4"
}
}
, ".SettingGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-400 -75", OffsetMax = "400 75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".SettingGUI", ".SGUIM");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5"
}
, Image = {
Color = config.GUI.BColor2
}
}
, ".SGUIM", ".SGUIMM");
var player_data = StoredData[player.userID];
Dictionary<string, bool> setting = new Dictionary<string, bool> {
["inventory"]
= player_data.ChangeSI, ["entity"] = player_data.ChangeSE, ["craft"] = player_data.ChangeSC, ["clear"] = player_data.ChangeSCL, ["give"] = player_data.ChangeSG, ["friends"] = StoredDataFriends[player.userID]
}
;
int x = 0, y = 0;
foreach (var s in setting) {
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{-390 + (x * 392.5)} {25 - (y * 45)}", OffsetMax = $"{-2.5 + (x * 392.5)} {65 - (y * 45)}"
}
, Image = {
Color = config.GUI.SettingColor, Material = "assets/icons/greyout.mat"
}
}
, ".SGUIMM", ".SM");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-190 -15", OffsetMax = "-160 15"
}
, Button = {
Color = s.Value ? config.MenuS.CTButton : config.MenuS.CFButton, Sprite = s.Value ? config.MenuS.TButtonIcon : config.MenuS.FButtonIcon, Command = $"skin_s {s.Key}"
}
, Text = {
Text = ""
}
}
, ".SM");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-155 -15", OffsetMax = "190 15"
}
, Text = {
Text = lang.GetMessage(s.Key, this, player.UserIDString), Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 15, Color = "0.750927 0.750927 0.750927 1"
}
}
, ".SM");
x++;
if (x == 2) {
x = 0;
y++;
}
}
CuiHelper.AddUi(player, container);
}
private void SendInfo(BasePlayer player, string message) {
player.SendConsoleCommand("gametip.showgametip", message);
timer.Once(5f, () => player.SendConsoleCommand("gametip.hidegametip"));
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<SkinConfig>();
}
catch {
PrintWarning("Ошибка чтения конфигурации! Создание дефолтной конфигурации!");
LoadDefaultConfig();
}
SaveConfig();
}
private void OnItemAddedToContainer(ItemContainer container, Item item) {
if (item == null) return;
if (container?.playerOwner != null) {
BasePlayer player = container.playerOwner;
if (player == null || player.IsNpc || !player.userID.IsSteamId() || player.IsSleeping()) return;
if (config.Setting.ReskinConfig && !_items.ContainsKey(item.info.shortname)) return;
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.give") || !StoredData.ContainsKey(player.userID) || !StoredData[player.userID].Skins.ContainsKey(item.info.shortname)) return;
if (StoredData[player.userID].ChangeSG) SetSkinCraftGive(player, item);
}
}
private Data DATA() {
Data data = new Data();
data.ChangeSI = config.PSetting.ChangeSI;
data.ChangeSE = config.PSetting.ChangeSE;
data.ChangeSC = config.PSetting.ChangeSC;
data.ChangeSCL = config.PSetting.ChangeSCL;
data.ChangeSG = config.PSetting.ChangeSG;
return data;
}
private void SetSkinEntity(BasePlayer player, BaseEntity entity, string shortname) {
ulong skin = StoredData[player.userID].Skins[shortname];
if (skin == entity.skinID || skin == 0) return;
if (errorskins.ContainsKey(skin)) {
SendInfo(player, lang.GetMessage("ERRORSKIN", this, player.UserIDString));
return;
}
entity.skinID = skin;
entity.SendNetworkUpdate();
Effect.server.Run("assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab", entity.transform.localPosition);
}
private void OnPlayerDisconnected(BasePlayer player) {
if (StoredData.ContainsKey(player.userID)) {
SaveData(player);
StoredData.Remove(player.userID);
}
if (Cooldowns.ContainsKey(player)) Cooldowns.Remove(player);
}
private void LoadData(BasePlayer player) {
ulong userID = player.userID;
if (Interface.Oxide.DataFileSystem.ExistsDatafile($"XDataSystem/XSkinMenu/UserSettings/{userID}")) {
var Data = Interface.Oxide.DataFileSystem.ReadObject<Data>($"XDataSystem/XSkinMenu/UserSettings/{userID}");
StoredData[userID] = Data ?? DATA();
}
else StoredData[userID] = DATA();
if (!StoredDataFriends.ContainsKey(userID)) StoredDataFriends.Add(userID, config.PSetting.ChangeF);
var list = StoredData[userID].Skins;
foreach (var skin in StoredDataSkins) {
string key = skin.Key;
if (!list.ContainsKey(key)) list.Add(key, _items.ContainsKey(key) ? _items[key] : 0);
}
StoredData[userID].Skins = list;
}
private void SetSkinTransport(BasePlayer player, BaseVehicle vehicle, string shortname) {
ulong skin = StoredData[player.userID].Skins[shortname];
if (skin == vehicle.skinID || skin == 0) return;
if (errorskins.ContainsKey(skin)) shortname = errorskins[skin];
if (errorshortnames.ContainsKey(shortname)) shortname = errorshortnames[shortname];
BaseVehicle transport = GameManager.server.CreateEntity($"assets/content/vehicles/snowmobiles/{shortname}.prefab", vehicle.transform.position, vehicle.transform.rotation) as BaseVehicle;
transport.health = vehicle.health;
transport.skinID = skin;
vehicle.Kill();
transport.Spawn();
Effect.server.Run("assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab", transport.transform.localPosition);
}
[ChatCommand("skinentity")]
private void cmdSetSkinEntity(BasePlayer player) {
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.entity")) {
SendReply(player, lang.GetMessage("NOPERM", this, player.UserIDString));
return;
}
if (StoredData[player.userID].ChangeSE) {
RaycastHit rhit;
if (!Physics.Raycast(player.eyes.HeadRay(), out rhit, 3f, LayerMask.GetMask("Deployed", "Construction", "Prevent Building"))) return;
var entity = rhit.GetEntity();
if (entity == null) return;
if (entity is BaseVehicle) {
var vehicle = entity as BaseVehicle;
var shortname = vehicle.ShortPrefabName;
if (!StoredData[player.userID].Skins.ContainsKey(shortname)) return;
SetSkinTransport(player, vehicle, shortname);
}
else if (entity.OwnerID == player.userID || player.currentTeam != 0 && player.Team.members.Contains(entity.OwnerID) && StoredDataFriends.ContainsKey(entity.OwnerID) && StoredDataFriends[entity.OwnerID]) if (_shortnamesEntity.ContainsKey(entity.ShortPrefabName)) {
var shortname = _shortnamesEntity[entity.ShortPrefabName];
if (!StoredData[player.userID].Skins.ContainsKey(shortname)) return;
SetSkinEntity(player, entity, shortname);
}
}
}
private Dictionary<ulong, Data> StoredData = new Dictionary<ulong, Data>();
private static readonly Dictionary<string, int> ItemIds = new Dictionary<string, int>();
private int GetItemId(string shortname) {
int id;
if (ItemIds.TryGetValue(shortname, out id)) return id;
var def = ItemManager.FindItemDefinition(shortname);
if (!def) return ItemIds[shortname] = int.MinValue;
return ItemIds[shortname] = def.itemid;
}
private void ItemGUI(BasePlayer player, string category, int Page = 0) {
CuiHelper.DestroyUi(player, ".SettingGUI");
CuiHelper.DestroyUi(player, ".SkinGUI");
CuiHelper.DestroyUi(player, ".ItemGUI");
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-502.5 -270", OffsetMax = "502.5 177.5"
}
, Image = {
Color = "0 0 0 0"
}
}
, ".SGUI", ".ItemGUI");
var player_data = StoredData[player.userID].Skins;
int x = 0, y = 0, z = 0;
foreach (var item in config.Category[category].Skip(Page * 40)) {
if (!player_data.ContainsKey(item.Key)) continue;
ulong skinID = player_data[item.Key];
bool c = player_data.ContainsKey(item.Key), s = skinID != 0;
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{-497.5 + (x * 100)} {123.25 - (y * 100)}", OffsetMax = $"{-402.5 + (x * 100)} {218.25 - (y * 100)}"
}
, Image = {
Color = config.GUI.BlockColor, Material = "assets/icons/greyout.mat"
}
}
, ".ItemGUI", ".Item");
container.Add(new CuiElement {
Parent = ".Item", Components = {
new CuiImageComponent {
ItemId = GetItemId(item.Key), SkinId = 0,
}
, // new CuiRawImageComponent { Png = (string) ImageLibrary.Call("GetImage", config.GUI.MainSkin && c && s ? $"{skinID}152" : item.Key + 150) },
new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "7.5 7.5", OffsetMax = "-7.5 -7.5"
}
}
}
);
if (StoredDataSkins.ContainsKey(item.Key) && StoredDataSkins[item.Key].Count != 0 && c) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Command = $"skin_c skin {item.Key}"
}
, Text = {
Text = ""
}
}
, ".Item");
if (s) container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-20 5", OffsetMax = "-5 20"
}
, Button = {
Color = "1 1 1 0.75", Sprite = "assets/icons/clear.png", Command = $"skin_c clear {item.Key} {z} {category} {Page}"
}
, Text = {
Text = ""
}
}
, ".Item", $".I + {z}");
}
x++;
z++;
if (x == 10) {
x = 0;
y++;
if (y == 4) break;
}
}
bool back = Page != 0;
bool next = config.Category[category].Count > ((Page + 1) * 40);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-190 5", OffsetMax = "-100 31.75"
}
, Button = {
Color = back ? config.GUI.ActiveBackColor : config.GUI.InactiveBackColor, Command = back ? $"page.xskinmenu item back {category} {Page}" : ""
}
, Text = {
Text = lang.GetMessage("BACK", this, player.UserIDString), Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-regular.ttf", Color = back ? config.GUI.ActiveBackColorText : config.GUI.InactiveBackColorText
}
}
, ".ItemGUI");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-95 5", OffsetMax = "-5 31.75"
}
, Button = {
Color = next ? config.GUI.ActiveNextReloadColor : config.GUI.InactiveNextReloadColor, Command = next ? $"page.xskinmenu item next {category} {Page}" : ""
}
, Text = {
Text = lang.GetMessage("NEXT", this, player.UserIDString), Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-regular.ttf", Color = next ? config.GUI.ActiveNextReloadColorText : config.GUI.InactiveNextReloadColorText
}
}
, ".ItemGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "0 36.75", OffsetMax = "0 41.75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".ItemGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-200 0", OffsetMax = "-195 36.75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".ItemGUI");
if (config.Setting.ButtonClear) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "5 5", OffsetMax = "190 31.75"
}
, Button = {
Color = config.GUI.ActiveNextReloadColor, Command = "skin_c clearall"
}
, Text = {
Text = lang.GetMessage("CLEARALL", this, player.UserIDString), Align = TextAnchor.MiddleCenter, FontSize = 11, Font = "robotocondensed-regular.ttf", Color = config.GUI.ActiveNextReloadColorText
}
}
, ".ItemGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "195 0", OffsetMax = "200 36.75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".ItemGUI");
}
CuiHelper.AddUi(player, container);
}
private void SetSkinItem(BasePlayer player, string item, ulong skin) {
foreach (var i in player.inventory.FindItemIDs(ItemManager.FindItemDefinition(item).itemid)) {
if (i.skin == skin || config.Setting.Blacklist.Contains(i.skin)) continue;
if (errorskins.ContainsKey(skin)) {
i.UseItem();
Item newitem = ItemManager.CreateByName(errorskins[skin]);
newitem.condition = i.condition;
newitem.maxCondition = i.maxCondition;
if (i.contents != null) foreach (var module in i.contents.itemList) {
Item content = ItemManager.CreateByName(module.info.shortname, module.amount);
content.condition = module.condition;
content.maxCondition = module.maxCondition;
content.MoveToContainer(newitem.contents);
}
player.GiveItem(newitem);
}
else {
i.skin = skin;
i.MarkDirty();
BaseEntity entity = i.GetHeldEntity();
if (entity != null) {
entity.skinID = skin;
entity.SendNetworkUpdate();
}
}
}
}
public Dictionary<string, string> errorshortnames = new Dictionary<string, string> {
["snowmobiletomaha"]
= "tomahasnowmobile"
}
;
private void OnPlayerConnected(BasePlayer player) {
if (player.IsReceivingSnapshot) {
NextTick(() => OnPlayerConnected(player));
return;
}
LoadData(player);
}
[ChatCommand("skin")]
private void cmdOpenGUI(BasePlayer player) {
if (!permission.UserHasPermission(player.UserIDString, "xskinmenu.use")) SendReply(player, lang.GetMessage("NOPERM", this, player.UserIDString));
else GUI(player);
}
private void SkinGUI(BasePlayer player, string item, int Page = 0) {
CuiHelper.DestroyUi(player, ".SkinGUI");
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-502.5 -270", OffsetMax = "502.5 177.5"
}
, Image = {
Color = config.GUI.BColor3
}
}
, ".SGUI", ".SkinGUI");
int x = 0, y = 0;
ulong s = StoredData[player.userID].Skins[item];
foreach (var skin in StoredDataSkins[item].Skip(Page * 40)) {
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{-497.5 + (x * 100)} {123.25 - (y * 100)}", OffsetMax = $"{-402.5 + (x * 100)} {218.25 - (y * 100)}"
}
, Image = {
Color = s == skin ? config.GUI.ActiveBlockColor : config.GUI.BlockColor, Material = "assets/icons/greyout.mat"
}
}
, ".SkinGUI", ".Skin");
container.Add(new CuiElement {
Parent = ".Skin", Components = {
new CuiImageComponent {
ItemId = GetItemId(item), SkinId = skin,
}
, //new CuiRawImageComponent { Png = (string) ImageLibrary.Call("GetImage", $"{skin}152") },
new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "7.5 7.5", OffsetMax = "-7.5 -7.5"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Command = $"skin_c setskin {item} {skin} {Page}"
}
, Text = {
Text = ""
}
}
, ".Skin");
if (config.Setting.DeleteButton && player.IsAdmin) container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-20 5", OffsetMax = "-5 20"
}
, Button = {
Color = "1 1 1 0.750927", Sprite = "assets/icons/clear.png", Command = $"xskin remove_ui {item} {skin} {Page}"
}
, Text = {
Text = ""
}
}
, ".Skin");
x++;
if (x == 10) {
x = 0;
y++;
if (y == 4) break;
}
}
bool back = Page != 0;
bool next = StoredDataSkins[item].Count > ((Page + 1) * 40);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-190 5", OffsetMax = "-100 31.75"
}
, Button = {
Color = back ? config.GUI.ActiveBackColor : config.GUI.InactiveBackColor, Command = back ? $"page.xskinmenu skin back {item} {Page}" : ""
}
, Text = {
Text = lang.GetMessage("BACK", this, player.UserIDString), Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-regular.ttf", Color = back ? config.GUI.ActiveBackColorText : config.GUI.InactiveBackColorText
}
}
, ".SkinGUI");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-95 5", OffsetMax = "-5 31.75"
}
, Button = {
Color = next ? config.GUI.ActiveNextReloadColor : config.GUI.InactiveNextReloadColor, Command = next ? $"page.xskinmenu skin next {item} {Page}" : ""
}
, Text = {
Text = lang.GetMessage("NEXT", this, player.UserIDString), Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-regular.ttf", Color = next ? config.GUI.ActiveNextReloadColorText : config.GUI.InactiveNextReloadColorText
}
}
, ".SkinGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "0 36.75", OffsetMax = "0 41.75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".SkinGUI");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-200 0", OffsetMax = "-195 36.75"
}
, Image = {
Color = config.GUI.BColor1, Material = "assets/icons/greyout.mat"
}
}
, ".SkinGUI");
CuiHelper.AddUi(player, container);
}
[ConsoleCommand("page.xskinmenu")]
private void ccmdPage(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
Effect x = new Effect("assets/bundled/prefabs/fx/notice/loot.drag.grab.fx.prefab", player, 0, new Vector3(), new Vector3());
string item = args.Args[2];
int Page = int.Parse(args.Args[3]);
switch (args.Args[0]) {
case "item" : {
switch (args.Args[1]) {
case "next" : {
ItemGUI(player, item, Page + 1);
break;
}
case "back" : {
ItemGUI(player, item, Page - 1);
break;
}
}
break;
}
case "skin" : {
switch (args.Args[1]) {
case "next" : {
SkinGUI(player, item, Page + 1);
break;
}
case "back" : {
SkinGUI(player, item, Page - 1);
break;
}
}
break;
}
}
EffectNetwork.Send(x, player.Connection);
}
internal class Data {
[JsonProperty("Смена скинов в инвентаре")]
public bool ChangeSI;
[JsonProperty("Смена скинов на предметах")]
public bool ChangeSE;
[JsonProperty("Смена скинов при крафте")]
public bool ChangeSC;
[JsonProperty("Смена скинов в инвентаре после удаления")]
public bool ChangeSCL;
[JsonProperty("Смена скинов при попадании в инвентарь")]
public bool ChangeSG;
[JsonProperty("Скины")]
public Dictionary<string, ulong> Skins = new Dictionary<string, ulong>();
}
private SkinConfig config;
private class SkinConfig {
[JsonProperty("Настройки игрока по умолчанию")]
public PlayerSetting PSetting = new PlayerSetting();
[JsonProperty("Общие настройки")]
public GeneralSetting Setting = new GeneralSetting();
internal class APISetting {
[JsonProperty("Отключить проверку на наличие изображения в дате ImageLibrary (изображение будет повторно загружаться после каждой загрузки/перезагрузки плагина) - Если вы не знаете/понимаете как работают изображения в ImageLibrary или у вас проблемы с изображениями, то полезно отключить проверку (true)")]
public bool HasImage;
[JsonProperty("Какое API использовать для загрузки изображений - [ True - обычные изображения из Steam Workshop (практически все существующие скины) | False - красивые изображения (все принятые скины разработчиками, а также половина из Steam Workshop) ]")]
public bool APIOption;
}
// ... [Code preview truncated due to length. Full source in attached file] ...