C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Network;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Pool;
using System.Text;
using Facepunch;
namespace Oxide.Plugins {
[Info("Skinner", "rustmods.ru", "2.1.6")]
[Description("Brings automation and ease to skinning items")]
public class Skinner : CovalencePlugin {
static Skinner skinner;
#region Perms
private const string permdefault = "skinner.default";
private const string permitems = "skinner.items";
private const string permcraft = "skinner.craft";
private const string permskininv = "skinner.skininv";
private const string permskinteam = "skinner.skinteam";
private const string permskinteamblock = "skinner.skinteamblock";
private const string permskincon = "skinner.skincon";
private const string permbypassauth = "skinner.bypassauth";
private const string permimport = "skinner.import";
private const string permskinbase = "skinner.skinbase";
private const string permskinall = "skinner.skinall";
private const string permskinauto = "skinner.skinauto";
private const string permskinautotoggle = "skinner.skinautotoggled";
private const string permskinrequest = "skinner.skinrequest";
private const string permskintry = "skinner.permskintry";
private List<string> permissions = new List<string>() {
permdefault, permcraft, permitems, permbypassauth, permskincon, permskininv, permimport, permskinbase, permskinall, permskinteam, permskinteamblock, permskinrequest, permskintry, permskinauto, permskinautotoggle
}
;
#endregion Perms
#region Init
private void OnServerInitialized() {
skinner = this;
_skinNames = new Dictionary<ulong, string>();
_cachedSkins = new Dictionary<int, List<ulong>>();
_WaitForSecondsMore = CoroutineEx.waitForSeconds(1f);
foreach (string perm in permissions) permission.RegisterPermission(perm, this);
foreach (string perm in config.Cooldowns.Keys) permission.RegisterPermission($"skinner.{perm}", this);
AddCovalenceCommand(config.cmdsskin, "SkinCMD");
AddCovalenceCommand(config.cmdsskincraft, "DefaultSkinsCMD");
AddCovalenceCommand(config.cmdsskinitems, "SkinItemCMD");
AddCovalenceCommand(config.cmdsskininv, "SkinInvCMD");
AddCovalenceCommand(config.cmdsskincon, "SkinConCMD");
AddCovalenceCommand(config.cmdtoggleautoskin, "SkinAutoCMD");
AddCovalenceCommand(config.cmdskinimport, "SkinImportCMD");
AddCovalenceCommand(config.cmdcollectionimport, "SkinImportCollection");
AddCovalenceCommand(config.cmdskinbase, "SkinBaseCMD");
AddCovalenceCommand(config.cmdskinallitems, "SkinAllItemsCMD");
AddCovalenceCommand(config.cmdskinteam, "SkinTeamCMD");
AddCovalenceCommand(config.cmdskinrequest, "SkinRequestCMD");
List<string> tempList = new List<string>(config.cmdskinset);
tempList.Add("setSelectCMD");
AddCovalenceCommand(tempList.ToArray(), "SetSelectCMD");
AddCovalenceCommand(config.cmdskinrequests, "SkinRequestsCMD");
AddCovalenceCommand(new[] {
"sbNextPage"
}
, "SBNextPageCMD");
AddCovalenceCommand(new[] {
"sbBackPage"
}
, "SBBackPageCMD");
AddCovalenceCommand(new[] {
"searchCMD"
}
, "SearchCMD");
AddCovalenceCommand(new[] {
"requestSelectCMD"
}
, "RequestSelectCMD");
foreach (var skin in config.ImportedSkinList) {
if (!string.IsNullOrEmpty(skin.Value.itemDisplayname) && !string.IsNullOrEmpty(skin.Value.itemShortname)) continue;
if (_WorkshopSkinIDCollectionList.Contains(skin.Key.ToString())) continue;
_WorkshopSkinIDCollectionList.Add(skin.Key.ToString());
}
if (!config.sprayCanOveride) Unsubscribe("OnActiveItemChanged");
if (!config.useOnItemCraft) Unsubscribe("OnItemCraftFinished");
//InitUI
InitUI();
if (getCollectionscouroutine != null) {
Puts("getcollections already running!!");
}
else {
getCollectionscouroutine = GetCollectionSkinIDS();
ServerMgr.Instance.StartCoroutine(getCollectionscouroutine);
}
}
private void Loaded() {
_defaultSkins = Interface.Oxide.DataFileSystem.GetFile("Skinner/DefaultCraftSkins");
_playerData = Interface.Oxide.DataFileSystem.GetFile("Skinner/PlayerUsageData");
_skinRequestsData = Interface.Oxide.DataFileSystem.GetFile("Skinner/SkinsRequestData");
LoadData();
}
private void Unload() {
if (getCollectionscouroutine != null) ServerMgr.Instance.StopCoroutine(getCollectionscouroutine);
if (getSteamWorkshopSkinData != null) ServerMgr.Instance.StopCoroutine(getSteamWorkshopSkinData);
if (getSteamWorkshopRequestData != null) ServerMgr.Instance.StopCoroutine(getSteamWorkshopRequestData);
if (notifyDiscordCoroutine != null) ServerMgr.Instance.StopCoroutine(notifyDiscordCoroutine);
foreach (var player in BasePlayer.allPlayerList) {
UI.DestroyUI(player, BSkinPageUI);
UI.DestroyUI(player, BSkinSearchUI);
UI.DestroyUI(player, BSkinSetsSelectUI);
UI.DestroyUI(player, BSkinRequestsUI);
if (_playerUsageData.TryGetValue(player.userID, out PlayerData playerData)) playerData.UpdateLastOnline();
}
foreach (var player in BasePlayer.allPlayerList) {
if (player.TryGetComponent<BoxController>(out BoxController boxController)) {
UnityEngine.Object.Destroy(boxController);
}
if (player.TryGetComponent<InventoryWatcher>(out InventoryWatcher inventoryWatcher)) {
UnityEngine.Object.Destroy(inventoryWatcher);
}
if (player.TryGetComponent<SpraycanController>(out SpraycanController spraycanController)) {
UnityEngine.Object.Destroy(spraycanController);
}
}
SaveData();
skinner = null;
_WaitForSecondsMore = null;
}
public static Dictionary<ulong, string>? _skinNames;
public static Dictionary<int, List<ulong>>? _cachedSkins;
private static ulong maskID = (ulong)1 << 63;
private static ulong maskID2 = 31551;
private ulong SetMask(ulong num) {
return num | maskID;
}
private ulong Get2Unmasked(ulong num) {
return num & ~maskID2;
}
public static ulong GetMask(ulong skinID, int itemID, bool redirectSkin = false) {
return redirectSkin ? (ulong)itemID | maskID : skinID;
}
public static bool HasMask(ulong uID) {
return (uID & maskID) == maskID;
}
public static ulong UnsetMask(ulong num) {
return num & ~maskID;
}
private void AddSkin(ulong skinID, int itemID, string displayName, int redirectID = -1) {
if (config.blacklistedskins.Contains(skinID) || config.blacklisteditems.Contains(itemID) || config.blacklisteditems.Contains(redirectID)) return;
if (!_cachedSkins.TryGetValue(itemID, out List<ulong> skinsList)) {
skinsList = new List<ulong>() {
0ul
}
;
_cachedSkins[itemID] = skinsList;
}
ulong uID = GetMask(skinID, redirectID, redirectID != -1);
if (!skinsList.Contains(uID)) skinsList.Add(uID);
_skinNames[uID] = displayName;
}
private int totskins = 0;
private void GetSkins() {
if ((Steamworks.SteamInventory.Definitions?.Length ?? 0) == 0) {
Puts("Waiting for Steamworks to update skin item definitions");
Steamworks.SteamInventory.OnDefinitionsUpdated += GetSkins;
return;
}
int sk = 0;
Puts("Steamworks Updated, Updating Skins");
Steamworks.SteamInventory.OnDefinitionsUpdated -= GetSkins;
Dictionary<int, ItemCategory> catDefinitions = new Dictionary<int, ItemCategory>();
foreach (ItemDefinition itemDef in ItemManager.GetItemDefinitions()) {
if (!catDefinitions.ContainsKey(itemDef.itemid)) {
catDefinitions.Add(itemDef.itemid, itemDef.category);
}
if (!config.autoImportApproved) break;
if (itemDef.isRedirectOf != null) {
AddSkin(0ul, itemDef.isRedirectOf.itemid, string.Empty, itemDef.itemid);
continue;
}
foreach (var skin in ItemSkinDirectory.ForItem(itemDef)) {
if (skin.id == 0) continue;
ItemSkin itemSkin = skin.invItem as ItemSkin;
if (itemSkin == null) continue;
bool isredirect = itemSkin?.Redirect != null;
if (isredirect) AddSkin((ulong)skin.id, itemDef.itemid, skin.invItem?.displayName?.english ?? itemDef.displayName.english, itemSkin.itemDefinition.itemid);
else AddSkin((ulong)skin.id, itemDef.itemid, skin.invItem?.displayName?.english ?? itemDef.displayName.english);
}
}
foreach (Steamworks.InventoryDef item in Steamworks.SteamInventory.Definitions) {
if (!config.autoImportApproved) break;
string shortname = item.GetProperty("itemshortname") == "lr300.item" ? "rifle.lr300" : item.GetProperty("itemshortname");
if (string.IsNullOrEmpty(shortname) || item.Id < 100) continue;
ulong skinid;
if (!ulong.TryParse(item.GetProperty("workshopid"), out skinid)) {
skinid = (ulong)item.Id;
}
if (skinid < 1000000) continue;
ItemDefinition steamitemdef = ItemManager.FindItemDefinition(shortname);
if (steamitemdef == null) continue;
if (_cachedSkins.TryGetValue(steamitemdef.itemid, out List<ulong> cachedskinsList)) {
if (cachedskinsList.Contains((ulong)item.Id)) continue;
}
if (steamitemdef.isRedirectOf != null) AddSkin(skinid, steamitemdef.isRedirectOf.itemid, item.Name, steamitemdef.itemid);
else AddSkin(skinid, steamitemdef.itemid, item.Name);
}
UpdateImportedSkins();
List<int> skincachekeys = Pool.Get<List<int>>();
skincachekeys.AddRange(new List<int>(_cachedSkins.Keys));
for (int i = skincachekeys.Count - 1; i >= 0; i--) {
var item2 = _cachedSkins[skincachekeys[i]];
if (item2.Count == 1) {
_cachedSkins.Remove(skincachekeys[i]);
continue;
}
ItemDefinition itemdef = ItemManager.FindItemDefinition(skincachekeys[i]);
if (itemdef?.Blueprint == null) {
_cachedSkins.Remove(skincachekeys[i]);
continue;
}
sk += item2.Count;
}
Pool.FreeUnmanaged(ref skincachekeys);
SaveConfig();
//Re-order to look nice
List<KeyValuePair<int, List<ulong>>> tempList = new List<KeyValuePair<int, List<ulong>>>(_cachedSkins);
tempList.Sort((pair1, pair2) => catDefinitions[pair1.Key].CompareTo(catDefinitions[pair2.Key]));
_cachedSkins.Clear();
foreach (KeyValuePair<int, List<ulong>> pair in tempList) {
_cachedSkins.Add(pair.Key, pair.Value);
}
_cachedSkinKeys = new List<int>(_cachedSkins.Keys);
Interface.CallHook("OnSkinnerCacheUpdated", _cachedSkins);
Puts($"{sk} skins were indexed, Skin indexing complete");
}
public static List<int>? _cachedSkinKeys;
private void UpdateImportedSkins() {
List<ulong> keys = Pool.Get<List<ulong>>();
keys.AddRange(new List<ulong>(config.ImportedSkinList.Keys));
for (int i = config.ImportedSkinList.Count - 1; i >= 0; i--) {
var whitelistSkin = config.ImportedSkinList[keys[i]];
if (string.IsNullOrEmpty(whitelistSkin.itemDisplayname) || string.IsNullOrEmpty(whitelistSkin.itemShortname)) {
config.ImportedSkinList.Remove(keys[i]);
continue;
}
ItemDefinition itemdef = ItemManager.FindItemDefinition(whitelistSkin.itemShortname);
if (itemdef == null) {
config.ImportedSkinList.Remove(keys[i]);
Puts($"Could not find item definition for {whitelistSkin.itemShortname} {keys[i]}");
continue;
}
AddSkin(keys[i], itemdef.itemid, whitelistSkin.itemDisplayname);
}
Pool.FreeUnmanaged(ref keys);
}
#endregion Init
#region Configuration
private Configuration config;
public class Configuration {
[JsonProperty("Skin Commands (skin items in you inventory")]
public string[] cmdsskin = new[] {
"skin", "s", "skinbox", "sb"
}
;
[JsonProperty("Skin Items Commands (skin items you have already placed")]
public string[] cmdsskinitems = new[] {
"skinitem", "si", "skindeployed", "sd"
}
;
[JsonProperty("Set default items to be skinned")]
public string[] cmdsskincraft = new[] {
"skincraft", "sc"
}
;
[JsonProperty("Automatically set all items in you inventory to your default skins")]
public string[] cmdsskininv = new[] {
"skininv", "sinv"
}
;
[JsonProperty("Automatically set all items a container to your default skins")]
public string[] cmdsskincon = new[] {
"skincon", "scon"
}
;
[JsonProperty("Automatically skin all deployables in your base")]
public string[] cmdskinbase = new[] {
"skinbase", "skinbuilding"
}
;
[JsonProperty("Automatically skin all items in your base")]
public string[] cmdskinallitems = new[] {
"skinall", "sa"
}
;
[JsonProperty("Automatically skin all items that are moved into you inventory")]
public string[] cmdtoggleautoskin = new[] {
"skinauto", "sauto"
}
;
[JsonProperty("Skin your teams inventories with your skin set")]
public string[] cmdskinteam = new[] {
"skinteam", "st"
}
;
[JsonProperty("Request workshop skins via workshop ID")]
public string[] cmdskinrequest = new[] {
"skinrequest", "sr"
}
;
[JsonProperty("Approve workshop skin requests")]
public string[] cmdskinrequests = new[] {
"skinrequests", "srs"
}
;
[JsonProperty("Set your selected skin set")]
public string[] cmdskinset = new[] {
"skinset", "ss"
}
;
[JsonProperty("Import Custom Skins")]
public string[] cmdskinimport = new[] {
"skinimport", "sip"
}
;
[JsonProperty("Import Workshop Collection Command")]
public string[] cmdcollectionimport = new[] {
"colimport", "cip"
}
;
[JsonProperty("Skin Request Notification Discord Webhook")]
public string DiscordWebhook = "";
[JsonProperty("Custom Page Change UI Positon anchor/offset 'min x, min y', 'max x', max y'")]
public string[] uiposition = new[] {
"0.5 0.0", "0.5 0.0", "198 60", "400 97"
}
;
[JsonProperty("Custom Searchbar UI Positon anchor/offset 'min x, min y', 'max x', max y'")]
public string[] uisearchposition = new[] {
"0.5 0.0", "0.5 0.0", "410 635", "572 660"
}
;
[JsonProperty("Custom Set Selection UI Positon anchor/offset 'min x, min y', 'max x', max y'")]
public string[] uisetsposition = new[] {
"0.5 0.0", "0.5 0.0", "250 610", "573 633"
}
;
[JsonProperty("Auto import approved skins")]
public bool autoImportApproved = true;
[JsonProperty("Remove player data after inactivity (days)")]
public int removedataTime = 14;
[JsonProperty("Apply names of skins to skinned items")]
public bool applySkinNames = true;
[JsonProperty("Add Search Bar UI")]
public bool searchbar = true;
[JsonProperty("Use on itemcraft hook (skin items after crafting - not required when using skinauto)")]
public bool useOnItemCraft = false;
[JsonProperty("Override spraycan behaviour")]
public bool sprayCanOveride = false;
[JsonProperty("Use spraycan effect when holding spraycan and skinning deployables")]
public bool sprayCanEffect = true;
[JsonProperty("Blacklisted Skins (skinID)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ulong> blacklistedskins = new List<ulong>();
[JsonProperty("Blacklisted Items (itemID)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<int> blacklisteditems = new List<int>();
[JsonProperty("Import Skin collections (steam workshop ID)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ulong> skinCollectionIDs = new List<ulong>();
[JsonProperty("Command based cooldowns ('permission' : 'command' seconds")]
public Dictionary<string, CoolDowns> Cooldowns = new Dictionary<string, CoolDowns>() {
{
"Default30CD", new CoolDowns()
}
}
;
[JsonProperty("Imported Skins List", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<ulong, ImportedItem> ImportedSkinList = new Dictionary<ulong, ImportedItem>();
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
public struct ImportedItem {
public string itemShortname;
public string itemDisplayname;
}
public struct RequestItem {
public ulong skinID;
public int itemID;
public string itemDisplayname;
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) {
throw new JsonException();
}
var configDict = config.ToDictionary();
Dictionary<string, object> defaultconObjects = new Dictionary<string, object>();
foreach (var obj in Config) {
defaultconObjects.Add(obj.Key, obj.Value);
}
if (configDict.Count != defaultconObjects.Count) {
Puts("Configuration appears to be outdated; updating and saving");
SaveConfig();
}
else {
foreach (var key in configDict.Keys) {
if (defaultconObjects.ContainsKey(key)) continue;
Puts("Configuration appears to be outdated; updating and saving");
SaveConfig();
break;
}
}
}
catch {
Puts($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig() {
Puts($"Configuration changes saved to {Name}.json");
Config.WriteObject(config, true);
}
#endregion Configuration
#region Data
private DynamicConfigFile _defaultSkins;
private DynamicConfigFile _playerData;
private DynamicConfigFile _skinRequestsData;
private Dictionary<ulong, CoolDowns> _playercooldowns = new Dictionary<ulong, CoolDowns>();
private Dictionary<ulong, int> _playerSelectedSet = new Dictionary<ulong, int>();
private void LoadData() {
List<ulong> skipdata = Pool.Get<List<ulong>>();
try {
_playerUsageData = new Dictionary<ulong, PlayerData>();
long timenow = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
//need to read as dec and parse to ulong
var temp = _playerData.ReadObject<Dictionary<ulong, PlayerDataDec>>();
foreach (var pair in temp) {
//Not logged in for two weeks
if (timenow - pair.Value.lastonline > config.removedataTime * 86400) {
skipdata.Add(pair.Key);
continue;
}
_playerUsageData.Add(pair.Key, new PlayerData() {
lastonline = pair.Value.lastonline
}
);
foreach (var innerDict in pair.Value.skinusage) {
List<ulong> ulongList = new List<ulong>();
foreach (decimal d in innerDict.Value) {
ulong id = decimal.ToUInt64(d);
if (HasMask(id) && config.blacklisteditems.Contains((int)UnsetMask(id))) continue;
ulongList.Add(decimal.ToUInt64(d));
}
_playerUsageData[pair.Key].skinusage.TryAdd(innerDict.Key, ulongList);
}
}
}
catch {
_playerUsageData = new Dictionary<ulong, PlayerData>();
}
try {
_playerDefaultSkins = new Dictionary<ulong, Dictionary<int, ulong>[]>();
//need to read as dec and parse to ulong
var temp = _defaultSkins.ReadObject<Dictionary<ulong, Dictionary<int, decimal>[]>>();
foreach (var outerPair in temp) {
if (skipdata.Contains(outerPair.Key)) continue;
var innerDictArray = new Dictionary<int, ulong>[outerPair.Value.Length];
for (int i = 0; i < outerPair.Value.Length; i++) {
var innerDict = new Dictionary<int, ulong>();
foreach (var innerPair in outerPair.Value[i]) {
if (HasMask((ulong)innerPair.Value) && config.blacklisteditems.Contains((int)UnsetMask((ulong)innerPair.Value))) continue;
innerDict.Add(innerPair.Key, (ulong)innerPair.Value);
}
innerDictArray[i] = innerDict;
}
_playerDefaultSkins.Add(outerPair.Key, innerDictArray);
}
}
catch {
_playerDefaultSkins = new Dictionary<ulong, Dictionary<int, ulong>[]>();
}
try {
_requestsData = _skinRequestsData.ReadObject<List<RequestItem>>();
}
catch {
_requestsData = new List<RequestItem>();
}
Pool.FreeUnmanaged(ref skipdata);
}
private void SaveData() {
Puts("DataSaved");
_defaultSkins.WriteObject(_playerDefaultSkins);
_playerData.WriteObject(_playerUsageData);
_skinRequestsData.WriteObject(_requestsData);
}
private Dictionary<ulong, Dictionary<int, ulong>[]> _playerDefaultSkins;
private Dictionary<ulong, PlayerData> _playerUsageData;
private List<RequestItem> _requestsData;
public class PlayerDataDec {
public Dictionary<int, List<decimal>> skinusage = new Dictionary<int, List<decimal>>();
public long lastonline {
get;
set;
}
= 0;
}
public class PlayerData {
public Dictionary<int, List<ulong>> skinusage = new Dictionary<int, List<ulong>>();
public long lastonline {
get;
set;
}
= 0;
public void AddSkinUsage(ulong skinID, int itemID, int rItemID = 0) {
if (skinID == 0 && rItemID == 0) return;
if (!skinusage.TryGetValue(itemID, out var list)) {
list = new List<ulong>(6);
skinusage[itemID] = list;
}
ulong uID = GetMask(skinID, rItemID, rItemID != 0);
for (int i = list.Count - 1; i >= 0; i--) {
if (list[i] != uID) continue;
list.RemoveAt(i);
}
if (list.Count >= 6) {
list.RemoveAt(0);
}
list.Add(uID);
}
public List<ulong>? GetSkinUsage(int itemID) {
if (!skinusage.TryGetValue(itemID, out List<ulong>? usageList)) {
return null;
}
return usageList;
}
public void UpdateLastOnline() {
lastonline = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
}
public class CoolDowns {
public float skin = 30f;
public float skinitem = 30f;
public float skincraft = 30f;
public float skincon = 30f;
public float skininv = 30f;
public float skinteam = 30f;
public float skinbase = 60f;
public float skinall = 60f;
}
#endregion Data
#region Localization
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["NoPerms"]
= "You don't have permissions to use this command", ["NoBuildingAuth"] = "You must have building auth to use this", ["NoObjectsFound"] = "No object found", ["NoSkins"] = "No skins available", ["ImportSkinArgs"] = "Bad args, Required input skinid", ["ImportCollectionArgs"] = "Bad args, Required input collectionID", ["SkinIDError"] = "Cannot parse skinid {0}", ["NoShortname"] = "No item found for shortname : {0}", ["DuplicateSkin"] = "Duplicate Skin ID for : {0} {1}", ["SkinImported2"] = "Skin {0} has been imported and saved", ["SkinRequested"] = "Skin {0} has been requested", ["AlreadyRequesting"] = "Already updating requests data please wait...", ["RequestingData"] = "Updating requests data please wait...", ["CollectionImported2"] = "Steam Skin Collection {0} has been imported and saved", ["CommandCooldown"] = "You can not use this command for another {0}", ["CompletedInvSkin"] = "All items in your inventory have been set to your default skins", ["CompletedConSkin"] = "All items in {0} have been set to your default skins", ["CompletedBuildingSkin"] = "All {0} in your base have been set to your default skins", ["CompletedAllSkin"] = "All {0} items in your base have been set to your default skins", ["SkinSetSelected"] = "Skin set {0} selected", ["SkinSetSelectedArgs"] = "Bad args, Required input set No.1, 2 or 3", ["AutoSkinEnabled"] = "Auto skins enabled", ["AutoSkinDisabled"] = "Auto skins disabled", ["CompletedTeamSkin"] = "All items in your team have been set skin set {0}", ["NoTeam"] = "You need to be in a team to use this feature", ["TeamSkinBlockEnabled"] = "You enabled team skins", ["TeamSkinBlockDisabled"] = "You disabled team skins"
}
, this);
}
#endregion Localization
#region Commands
private void SkinAutoCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer? player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permskinauto)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (!player.TryGetComponent<InventoryWatcher>(out InventoryWatcher inventoryWatcher)) {
player.gameObject.AddComponent<InventoryWatcher>();
ChatMessage(iplayer, "AutoSkinEnabled");
permission.GrantUserPermission(player.UserIDString, permskinautotoggle, this);
return;
}
permission.RevokeUserPermission(player.UserIDString, permskinautotoggle);
UnityEngine.Object.Destroy(inventoryWatcher);
ChatMessage(iplayer, "AutoSkinDisabled");
}
private void SkinImportCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer? player = iplayer.Object as BasePlayer;
if (player != null) {
if (!HasPerm(player.UserIDString, permimport)) {
ChatMessage(iplayer, "NoPerms");
return;
}
}
else if (!iplayer.IsServer) return;
if (args.Length < 1) {
ChatMessage(iplayer, "ImportSkinArgs");
return;
}
ulong skinid = 0ul;
if (!ulong.TryParse(args[0], out skinid)) {
ChatMessage(iplayer, "ImportSkinArgs", args[0]);
return;
}
_WorkshopSkinIDCollectionList.Add(skinid.ToString());
if (getSteamWorkshopSkinData != null) {
Puts("getSteamWorkshopSkinData already running!!");
}
else {
getSteamWorkshopSkinData = GetSteamWorkshopSkinData();
ServerMgr.Instance.StartCoroutine(getSteamWorkshopSkinData);
}
ChatMessage(iplayer, "SkinImported2", args[0]);
}
private void SkinImportCollection(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player != null) {
if (!HasPerm(player.UserIDString, permimport)) {
ChatMessage(iplayer, "NoPerms");
return;
}
}
else if (!iplayer.IsServer) return;
if (args.Length < 1) {
ChatMessage(iplayer, "ImportCollectionArgs");
return;
}
ulong collectionid = 0ul;
if (!ulong.TryParse(args[0], out collectionid)) {
ChatMessage(iplayer, "ImportCollectionArgs", args[0]);
return;
}
config.skinCollectionIDs.Add(collectionid);
if (getCollectionscouroutine != null) {
Puts("getcollections already running!!");
}
else {
getCollectionscouroutine = GetCollectionSkinIDS();
ServerMgr.Instance.StartCoroutine(getCollectionscouroutine);
}
ChatMessage(iplayer, "CollectionImported2", args[0]);
}
private void SkinCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permdefault)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (_viewingcon.TryGetValue(player.userID, out BoxController? boxController)) {
if (boxController != null) UnityEngine.Object.Destroy(boxController);
_viewingcon.Remove(player.userID);
return;
}
//Check for cooldown
float cdtime = 0;
//Find shortest cd perm
foreach (var cdperm in config.Cooldowns) {
if (!HasPerm(player.UserIDString, $"skinner.{cdperm.Key}")) continue;
if (cdtime == 0) cdtime = cdperm.Value.skin;
else if (cdtime > cdperm.Value.skin) cdtime = cdperm.Value.skin;
}
if (cdtime > 0) {
if (!_playercooldowns.TryGetValue(player.userID, out CoolDowns? coolDowns)) _playercooldowns.Add(player.userID, new CoolDowns() {
skin = Time.time
}
);
else {
if (coolDowns.skin + cdtime > Time.time) {
ChatMessage(iplayer, "CommandCooldown", TimeSpan.FromSeconds(coolDowns.skin + cdtime - Time.time).ToString("hh' hrs 'mm' mins 'ss' secs'"));
return;
}
coolDowns.skin = Time.time;
}
}
ItemContainer itemContainer = CreateContainer();
if (itemContainer == null) return;
boxController = player.gameObject.AddComponent<BoxController>();
boxController.inventory = itemContainer;
boxController.StartAwake();
boxController.StartItemSkin();
_viewingcon.Add(player.userID, boxController);
player.Invoke(() => StartLooting(player, itemContainer), 0.3f);
}
private void DefaultSkinsCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permcraft)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (_viewingcon.TryGetValue(player.userID, out BoxController? boxController)) {
if (boxController != null) UnityEngine.Object.Destroy(boxController);
_viewingcon.Remove(player.userID);
return;
}
//Check for cooldown
float cdtime = 0;
//Find shortest cd perm
foreach (var cdperm in config.Cooldowns) {
if (!HasPerm(player.UserIDString, $"skinner.{cdperm.Key}")) continue;
if (cdtime == 0) cdtime = cdperm.Value.skincraft;
else if (cdtime > cdperm.Value.skincraft) cdtime = cdperm.Value.skincraft;
}
if (cdtime > 0) {
if (!_playercooldowns.TryGetValue(player.userID, out CoolDowns? coolDowns)) _playercooldowns.Add(player.userID, new CoolDowns() {
skincraft = Time.time
}
);
else {
if (coolDowns.skincraft + cdtime > Time.time) {
ChatMessage(iplayer, "CommandCooldown", TimeSpan.FromSeconds(coolDowns.skincraft + cdtime - Time.time).ToString("hh' hrs 'mm' mins 'ss' secs'"));
return;
}
coolDowns.skincraft = Time.time;
}
}
if (!_playerDefaultSkins.ContainsKey(player.userID)) _playerDefaultSkins.Add(player.userID, new Dictionary<int, ulong>[3] {
new Dictionary<int, ulong>(), new Dictionary<int, ulong>(), new Dictionary<int, ulong>()
}
);
ItemContainer itemContainer = CreateContainer();
boxController = player.gameObject.AddComponent<BoxController>();
boxController.inventory = itemContainer;
boxController.StartAwake();
boxController.SkinCraft();
_viewingcon.TryAdd(player.userID, boxController);
player.Invoke(() => StartLooting(player, itemContainer), 0.3f);
}
private void SkinRequestCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permskinrequest)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (args.Length < 1) {
ChatMessage(iplayer, "ImportSkinArgs");
return;
}
if (!ulong.TryParse(args[0], out ulong skinidResult)) {
ChatMessage(iplayer, "ImportSkinArgs");
return;
}
ChatMessage(iplayer, "SkinRequested", skinidResult);
foreach (var a in _requestsData) {
if (a.skinID == skinidResult) return;
}
_requestsData.Add(new RequestItem {
skinID = skinidResult
}
);
if (string.IsNullOrEmpty(config.DiscordWebhook)) return;
_discordData.Add(new DiscordData() {
SkinID = skinidResult, player = player
}
);
if (notifyDiscordCoroutine != null) {
Puts("getcollections already running!!");
}
else {
notifyDiscordCoroutine = NotifyDiscord();
ServerMgr.Instance.StartCoroutine(notifyDiscordCoroutine);
}
}
private void SkinRequestsCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permimport)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (_requestsData.Count == 0) {
ChatMessage(iplayer, "NoRequests");
return;
}
if (getSteamWorkshopRequestData != null) {
ChatMessage(iplayer, "AlreadyRequesting");
return;
}
else {
ChatMessage(iplayer, "RequestingData");
getSteamWorkshopRequestData = GetSteamWorkshopSkinRequests();
ServerMgr.Instance.StartCoroutine(getSteamWorkshopRequestData);
}
if (_viewingcon.TryGetValue(player.userID, out BoxController? boxController)) {
if (boxController != null) UnityEngine.Object.Destroy(boxController);
_viewingcon.Remove(player.userID);
return;
}
ItemContainer itemContainer = CreateContainer();
boxController = player.gameObject.AddComponent<BoxController>();
boxController.inventory = itemContainer;
boxController.StartAwake();
_viewingcon.TryAdd(player.userID, boxController);
player.StartCoroutine(CheckforRequests(player, itemContainer, boxController));
}
private static WaitForSeconds _WaitForSecondsMore;
private IEnumerator CheckforRequests(BasePlayer player, ItemContainer itemContainer, BoxController boxController) {
yield return _WaitForSecondsMore;
int i = 0;
for (i = 0; i < 15; i++) {
if (getSteamWorkshopRequestData == null) break;
ChatMessage(player.IPlayer, "Updating requests data please wait...");
yield return _WaitForSecondsMore;
}
if (i >= 15) {
ChatMessage(player.IPlayer, "Updating requests timed out try again later");
UnityEngine.Object.Destroy(boxController);
}
else {
boxController.SkinRequests();
StartLooting(player, itemContainer);
}
}
private static int Layermask = LayerMask.GetMask("Deployed", "Construction");
private void SkinItemCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permitems)) {
ChatMessage(iplayer, "NoPerms");
return;
}
if (player.inventory.loot.IsLooting()) {
player.EndLooting();
return;
}
if (!player.CanBuild() && !HasPerm(player.UserIDString, permbypassauth)) {
ChatMessage(iplayer, "NoBuildingAuth");
return;
}
RaycastHit raycastHit;
if (!Physics.Raycast(player.eyes.HeadRay(), out raycastHit, 5f, Layermask)) {
ChatMessage(iplayer, "NoObjectsFound");
return;
}
BaseCombatEntity entity = raycastHit.GetEntity() as BaseCombatEntity;
ItemDefinition? itemDefinition = null;
if (entity.pickup.itemTarget != null) {
itemDefinition = entity.pickup.itemTarget;
}
else if (entity.repair.itemTarget != null) {
itemDefinition = entity.repair.itemTarget;
}
if (itemDefinition == null) {
ChatMessage(iplayer, "NoObjectsFound");
return;
}
if (!_cachedSkins.ContainsKey(itemDefinition.isRedirectOf != null ? itemDefinition.isRedirectOf.itemid : itemDefinition.itemid)) {
ChatMessage(iplayer, "NoSkins");
return;
}
if (_viewingcon.TryGetValue(player.userID, out BoxController? boxController)) {
if (boxController != null) UnityEngine.Object.Destroy(boxController);
_viewingcon.Remove(player.userID);
return;
}
//Check for cooldown
float cdtime = 0;
//Find shortest cd perm
foreach (var cdperm in config.Cooldowns) {
if (!HasPerm(player.UserIDString, $"skinner.{cdperm.Key}")) continue;
if (cdtime == 0) cdtime = cdperm.Value.skinitem;
else if (cdtime > cdperm.Value.skinitem) cdtime = cdperm.Value.skinitem;
}
if (cdtime > 0) {
if (!_playercooldowns.TryGetValue(player.userID, out CoolDowns? coolDowns)) _playercooldowns.Add(player.userID, new CoolDowns() {
skinitem = Time.time
}
);
else {
if (coolDowns.skinitem + cdtime > Time.time) {
ChatMessage(iplayer, "CommandCooldown", TimeSpan.FromSeconds(coolDowns.skinitem + cdtime - Time.time).ToString("hh' hrs 'mm' mins 'ss' secs'"));
return;
}
coolDowns.skinitem = Time.time;
}
}
if (args.Length > 0 && int.TryParse(args[0], out int setselect)) {
Dictionary<int, ulong> cachedskins = GetCachedSkins(player, setselect);
if (cachedskins.Count < 1) return;
int itemID = itemDefinition.isRedirectOf != null ? itemDefinition.isRedirectOf.itemid : itemDefinition.itemid;
if (cachedskins.TryGetValue(itemID, out ulong uID)) {
SkinDeployable(entity, uID);
}
return;
}
ItemContainer itemContainer = CreateContainer();
boxController = player.gameObject.AddComponent<BoxController>();
boxController.inventory = itemContainer;
boxController.StartAwake();
boxController.SkinDeplyoables(entity, itemDefinition);
_viewingcon.TryAdd(player.userID, boxController);
player.Invoke(() => StartLooting(player, itemContainer), 0.3f);
}
private void SkinInvCMD(IPlayer iplayer, string command, string[] args) {
BasePlayer player = iplayer.Object as BasePlayer;
if (player == null) return;
if (!HasPerm(player.UserIDString, permskininv)) {
ChatMessage(iplayer, "NoPerms");
return;
}
int setselect = -1;
if (args.Length > 0 && !int.TryParse(args[0], out setselect)) {
setselect = -1;
}
Dictionary<int, ulong> cachedskins = GetCachedSkins(player, setselect);
if (cachedskins.Count < 1) return;
if (player.inventory == null) return;
//Check for cooldown
float cdtime = 0;
//Find shortest cd perm
foreach (var cdperm in config.Cooldowns) {
if (!HasPerm(player.UserIDString, $"skinner.{cdperm.Key}")) continue;
if (cdtime == 0) cdtime = cdperm.Value.skininv;
else if (cdtime > cdperm.Value.skininv) cdtime = cdperm.Value.skininv;
}
if (cdtime > 0) {
if (!_playercooldowns.TryGetValue(player.userID, out CoolDowns? coolDowns)) _playercooldowns.Add(player.userID, new CoolDowns() {
skininv = Time.time
}
);
else {
if (coolDowns.skininv + cdtime > Time.time) {
ChatMessage(iplayer, "CommandCooldown", TimeSpan.FromSeconds(coolDowns.skininv + cdtime - Time.time).ToString("hh' hrs 'mm' mins 'ss' secs'"));
return;
}
coolDowns.skininv = Time.time;
}
}
List<Item> itemstoSkin = Pool.Get<List<Item>>();
player.inventory.GetAllItems(itemstoSkin);
for (int i = 0; i < itemstoSkin.Count; i++) {
Item item = itemstoSkin[i];
if (item?.info == null) continue;
if (item.IsBackpack()) {
if (item?.contents != null && !item.contents.itemList.IsNullOrEmpty()) //Fix for diving tanks
{
foreach (var bitem in item.contents.itemList) itemstoSkin.Add(bitem);
}
continue;
}
if (ca
// ... [Code preview truncated due to length. Full source in attached file] ...