C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
* <----- End-User License Agreement ----->
* Copyright © 2024 Iftebinjan
* Devoloper: Iftebinjan (Contact: https://discord.gg/HFaGs8YwsH)
*
* You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of This Software without the Developer’s consent
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
using System;
using System.Collections.Generic;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
namespace Oxide.Plugins {
[Info("TCUpgrades", "ifte", "1.1.1")]
[Description("Tool Cupboard Upgrade!")]
public class TCUpgrades : RustPlugin {
/*------------------------------------
*
* TCUpgrades by Ifte
* Support: https://discord.gg/cCWadjcapr
* Fiverr: https://www.fiverr.com/s/e2pkYY
* Eror404 not found
*
------------------------------------*/
/* Version: 1.1.1
* - Fixed for the April force wipe
*/
/* Version: 1.1.0
* - Added Multi TC Support
* - Updated checks for surrunding area of blocks and deployables
* - Added Cost for reskin and NoCostReskin perm
* - Added Cost multipliers and vip multipliers
* - Added New Lunar Wallpapers, if there is any missing let me know
* - Added & updated langs
* - More optimiations
*/
/* Version: 1.0.5
* - Updated for the latest rust force wipe
*/
/* Version: 1.0.4
* - Fixed an issue with Auth Remove BTN
* - Fixed config issue
* - Fixed on server wiped clear data
*/
/* Version: 1.0.3
* - Added new config options
* - Added default skin options
* - Added wallpaper placeableable by both side
* - Added Random color for metal skin
* - Fixed Carbon UI bugs (Showing black bars on screen)
* - Fixed some other bugs
*/
/* Version: 1.0.2
* - Updated lang files
* - Updated for the latest rust release.*/
#region Variables
[PluginReference]
private Plugin ImageLibrary, Toastify, Notify, NoEscape;
private Configuration config;
private const string PermAuthList = $"TCUpgrades.authlist";
private const string PermUpgrades = $"TCUpgrades.upgrade";
private const string PermRepair = $"TCUpgrades.repair";
private const string PermSkinBase = $"TCUpgrades.skin";
private const string PermWallpaper = $"TCUpgrades.wallpaper";
private const string PermUpgradesNoCost = $"TCUpgrades.upgrade.nocost";
private const string PermReskinNoCost = $"TCUpgrades.reskin.nocost";
private const string PermRepairNoCost = $"TCUpgrades.repair.nocost";
private const string PermWallpaperNoCost = $"TCUpgrades.wallpaper.nocost";
private const string PermDefault = $"TCUpgrades.default";
private const string PermWood = $"TCUpgrades.wood";
private const string PermStone = $"TCUpgrades.stone";
private const string PermMetal = $"TCUpgrades.metal";
private const string PermHQM = $"TCUpgrades.hqm";
private const string PermDeploy = $"TCUpgrades.deploy";
private const string ClickFX = "assets/bundled/prefabs/fx/notice/loot.drag.grab.fx.prefab";
readonly int layerMasks = LayerMask.GetMask("Construction");
private readonly float DistanceThreshold = 5f;
private enum NotificationPluginType {
None, Toastify, Notify
}
;
private readonly Dictionary<ulong, string> SkinBase = new Dictionary<ulong, string>() {
{
999, "tclevels.icons.wood.normal"
}
, //999
{
10232, "tclevels.icons.wood.frontier"
}
, {
2, "tclevels.icons.wood.ginger"
}
, {
1000, "tclevels.icons.stone.normal"
}
, //1000
{
10223, "tclevels.icons.stone.brick"
}
, {
10225, "tclevels.icons.stone.brutalist"
}
, {
10220, "tclevels.icons.stone.adobe"
}
, {
1001, "tclevels.icons.metal.normal"
}
, //1001
{
10221, "tclevels.icons.metal.container"
}
,
}
;
private readonly Dictionary<uint, string> MetalColors = new() {
[9999]
= "tclevels.icons.random", [1] = "0.38 0.56 0.74 1.0", [2] = "0.45 0.71 0.34 1.0", [3] = "0.57 0.29 0.83 1.0", [4] = "0.42 0.17 0.11 1.0", [5] = "0.82 0.46 0.13 1.0", [6] = "0.87 0.87 0.87 1.0", [7] = "0.20 0.20 0.18 1.0", [8] = "0.40 0.33 0.27 1.0", [9] = "0.20 0.22 0.34 1.0", [10] = "0.24 0.35 0.20 1.0", [11] = "0.73 0.30 0.18 1.0", [12] = "0.78 0.53 0.39 1.0", [13] = "0.84 0.66 0.22 1.0", [14] = "0.34 0.33 0.31 1.0", [15] = "0.21 0.34 0.37 1.0", [16] = "0.66 0.61 0.56 1.0"
}
;
private readonly Dictionary<BuildingGrade.Enum, HashSet<ulong>> BuildingSkins = new Dictionary<BuildingGrade.Enum, HashSet<ulong>>() {
{
BuildingGrade.Enum.Wood, new HashSet<ulong> {
999, 2, 10232
}
}
, {
BuildingGrade.Enum.Stone, new HashSet<ulong> {
1000, 10223, 10225, 10220
}
}
, {
BuildingGrade.Enum.Metal, new HashSet<ulong> {
1001, 10221
}
}
,
}
;
private readonly Dictionary<ulong, int> WallpaperSkins = new Dictionary<ulong, int>() {
{
0, -1501434104
}
, {
10246, -1501434104
}
, {
10243, -1501434104
}
, {
10242, -1501434104
}
, {
10266, -1501434104
}
, {
10263, -1501434104
}
, {
10262, -1501434104
}
, {
10261, -1501434104
}
, {
10260, -1501434104
}
, {
10259, -1501434104
}
, {
10258, -1501434104
}
, {
10257, -1501434104
}
, {
10256, -1501434104
}
, {
10255, -1501434104
}
, {
10254, -1501434104
}
, {
10253, -1501434104
}
, {
10252, -1501434104
}
, {
10251, -1501434104
}
, {
10250, -1501434104
}
, {
10249, -1501434104
}
, {
10248, -1501434104
}
, {
10247, -1501434104
}
, {
10245, -1501434104
}
, {
10244, -1501434104
}
, {
10267, -1501434104
}
, {
10268, -1501434104
}
, //10272, 10274, 10275, 10276, 10277, 10278, 10279
{
10272, -1501434104
}
, {
10274, -1501434104
}
, {
10275, -1501434104
}
, {
10276, -1501434104
}
, {
10277, -1501434104
}
, {
10278, -1501434104
}
, {
10279, -1501434104
}
,
}
;
private readonly Dictionary<string, string> imageList = new Dictionary<string, string>() {
{
"tclevels.icons.x", "https://i.ibb.co/K0cD7b7/x.png"
}
, {
"tclevels.icons.lock", "https://i.ibb.co/ZzkjrmQ/image.png"
}
, {
"tclevels.icons.info", "https://i.postimg.cc/qqwJym7X/info.png"
}
, {
"tclevels.icons.twig", "https://i.postimg.cc/kXgNJ00n/sticks.png"
}
, {
"tclevels.icons.wood", "https://i.postimg.cc/vm67dkB2/wood.png"
}
, {
"tclevels.icons.stone", "https://i.postimg.cc/DwNQHn2b/stones.png"
}
, {
"tclevels.icons.metal", "https://i.postimg.cc/Hkn46VCg/metal-fragments.png"
}
, {
"tclevels.icons.hqm", "https://i.postimg.cc/HsB90bRz/metal-refined.png"
}
, {
"tclevels.icons.deoply", "https://i.postimg.cc/HWcbkS67/cupboard-tool.png"
}
, {
"tclevels.icons.wood.frontier", "https://i.postimg.cc/ZKHDDc0w/frontier.png"
}
, {
"tclevels.icons.wood.ginger", "https://i.postimg.cc/X74z8hNZ/gingerbread.png"
}
, {
"tclevels.icons.stone.brick", "https://i.postimg.cc/rsLY7ZSP/brick.png"
}
, {
"tclevels.icons.stone.brutalist", "https://i.postimg.cc/tJtmbdkC/brutalist.png"
}
, {
"tclevels.icons.stone.adobe", "https://i.postimg.cc/9XGkyV25/adobe.png"
}
, {
"tclevels.icons.metal.container", "https://i.postimg.cc/gJhTSb6h/container.png"
}
, {
"tclevels.icons.wood.normal", "https://i.postimg.cc/xCnfkzXv/wood-1.png"
}
, {
"tclevels.icons.stone.normal", "https://i.postimg.cc/6Qd650p6/stone.png"
}
, {
"tclevels.icons.metal.normal", "https://i.postimg.cc/MGkKS4xr/metal.png"
}
, {
"tclevels.icons.random", "https://i.postimg.cc/43kBx8vB/dRFs4.png"
}
}
;
#endregion
#region Config
protected override void LoadConfig() {
base.LoadConfig();
config = Config.ReadObject<Configuration>();
if (config.Version < Version) UpdateConfigValues();
Config.WriteObject(config, true);
}
protected override void SaveConfig() => Config.WriteObject(config, true);
protected override void LoadDefaultConfig() => config = GetBaseConfig();
private void UpdateConfigValues() {
PrintWarning("Your config file is outdated! Updating config values...");
if (config.Version < new VersionNumber(1, 1, 0)) {
Configuration baseConfig = GetBaseConfig();
config.Features.EnableAutoUpgradeBase.defualtCost = baseConfig.Features.EnableAutoUpgradeBase.defualtCost;
config.Features.EnableAutoUpgradeBase.permissionsCostModifers = baseConfig.Features.EnableAutoUpgradeBase.permissionsCostModifers;
config.Features.EnableBaseSkinUpgrade.defualtCost = baseConfig.Features.EnableBaseSkinUpgrade.defualtCost;
config.Features.EnableBaseSkinUpgrade.permissionsCostModifers = baseConfig.Features.EnableBaseSkinUpgrade.permissionsCostModifers;
config.Features.EnableBaseWallpaperUpgrade.defualtCost = baseConfig.Features.EnableBaseWallpaperUpgrade.defualtCost;
config.Features.EnableBaseWallpaperUpgrade.permissionsCostModifers = baseConfig.Features.EnableBaseWallpaperUpgrade.permissionsCostModifers;
config.Features.EnableBaseRepairUpgrade.defualtCost = baseConfig.Features.EnableBaseRepairUpgrade.defualtCost;
config.Features.EnableBaseRepairUpgrade.permissionsCostModifers = baseConfig.Features.EnableBaseRepairUpgrade.permissionsCostModifers;
}
config.Version = Version;
PrintWarning("Config updated!");
}
private class Configuration {
[JsonProperty(PropertyName = "General Options")]
public GeneralOptions General {
get;
set;
}
[JsonProperty(PropertyName = "Features")]
public FeaturesOptions Features {
get;
set;
}
[JsonProperty(PropertyName = "Notifications")]
public Notifications notifications {
get;
set;
}
public VersionNumber Version {
get;
set;
}
}
private class GeneralOptions {
[JsonProperty("Only owner can use features of TC")]
public bool onlyOwner {
get;
set;
}
[JsonProperty("Support for NoEscape plugin")]
public bool supportNoEscape {
get;
set;
}
[JsonProperty("Support for CombatBlock plugin")]
///
public bool supportCombatBlock {
get;
set;
}
[JsonProperty("Use Automatic Upgrades on build")]
///
public bool autoUponBuild {
get;
set;
}
}
private class Options {
[JsonProperty("Enable Use")]
public bool enableUse {
get;
set;
}
[JsonProperty("Default use frequency time in sec")]
public float defaultTime {
get;
set;
}
[JsonProperty("Permissions use frequency time in sec", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> permissions {
get;
set;
}
[JsonProperty("Default cost modifers (1 = default, 0.5 = half decrease, 1.5 half increase)")]
public float defualtCost {
get;
set;
}
[JsonProperty("Permissions costs modifers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> permissionsCostModifers {
get;
set;
}
}
private class UIOptions {
[JsonProperty("UI Buttons Default offset")]
public string btnOffsets {
get;
set;
}
}
private class Notifications {
[JsonProperty("Enable chat notifications")]
public bool EenableChatNotify {
get;
set;
}
[JsonProperty("Chat notify prefix")]
public string Prefix {
get;
set;
}
[JsonProperty("Chat notify avatarID")]
public ulong Avatarid {
get;
set;
}
[JsonProperty("Enable GameTip notify")]
public bool EenableGameTipnotify {
get;
set;
}
[JsonProperty("Notifications plugin (0 = disabled | 1 = Toastify | 2 = Notify)")]
public NotificationPluginType NotificationPlugin {
get;
set;
}
[JsonProperty("Sync your notifications ID with below keywords")]
public NotificationsType NotificationTypes {
get;
set;
}
}
private class FeaturesOptions {
[JsonProperty("Enable Auth List")]
public AuthListOptions auttOptions {
get;
set;
}
[JsonProperty("Enable auto upgrade base")]
public Options EnableAutoUpgradeBase {
get;
set;
}
[JsonProperty("Enable base skin upgrade")]
public Options EnableBaseSkinUpgrade {
get;
set;
}
[JsonProperty("Enable base wallpaper upgrade")]
public Options EnableBaseWallpaperUpgrade {
get;
set;
}
[JsonProperty("Enable base repair upgrade")]
public Options EnableBaseRepairUpgrade {
get;
set;
}
}
private class AuthListOptions {
[JsonProperty(PropertyName = "Enable Auth List")]
public bool enable {
get;
set;
}
[JsonProperty("Only owner can see the Remove BTN?")]
public bool onlyOwnerRemoveBTN {
get;
set;
}
}
private class NotificationsType {
public string Error {
get;
set;
}
public string Success {
get;
set;
}
public string Info {
get;
set;
}
}
private Configuration GetBaseConfig() {
return new Configuration() {
General = new GeneralOptions() {
onlyOwner = false, supportNoEscape = true, supportCombatBlock = false, autoUponBuild = true
}
, Features = new FeaturesOptions() {
auttOptions = new AuthListOptions() {
enable = true, onlyOwnerRemoveBTN = false
}
, EnableAutoUpgradeBase = new Options() {
enableUse = true, defaultTime = 1.5f, permissions = new Dictionary<string, float>() {
{
"tcupgrades.vip", 1.0f
}
, {
"tcupgrades.mvp", 0.5f
}
,
}
, defualtCost = 1.0f, permissionsCostModifers = new Dictionary<string, float>() {
{
"tcupgrades.vip", 0.5f
}
, {
"tcupgrades.mvp", 0.2f
}
,
}
}
, EnableBaseSkinUpgrade = new Options() {
enableUse = true, defaultTime = 1.5f, permissions = new Dictionary<string, float>() {
{
"tcupgrades.vip", 1.0f
}
, {
"tcupgrades.mvp", 0.5f
}
,
}
, defualtCost = 1.0f, permissionsCostModifers = new Dictionary<string, float>() {
{
"tcupgrades.vip", 0.5f
}
, {
"tcupgrades.mvp", 0.2f
}
,
}
}
, EnableBaseWallpaperUpgrade = new Options() {
enableUse = true, defaultTime = 1.5f, permissions = new Dictionary<string, float>() {
{
"tcupgrades.vip", 1.0f
}
, {
"tcupgrades.mvp", 0.5f
}
,
}
, defualtCost = 1.0f, permissionsCostModifers = new Dictionary<string, float>() {
{
"tcupgrades.vip", 0.5f
}
, {
"tcupgrades.mvp", 0.2f
}
,
}
}
, EnableBaseRepairUpgrade = new Options() {
enableUse = true, defaultTime = 1.5f, permissions = new Dictionary<string, float>() {
{
"tcupgrades.vip", 1.0f
}
, {
"tcupgrades.mvp", 0.5f
}
,
}
, defualtCost = 1.0f, permissionsCostModifers = new Dictionary<string, float>() {
{
"tcupgrades.vip", 0.5f
}
, {
"tcupgrades.mvp", 0.2f
}
,
}
}
,
}
, notifications = new Notifications() {
EenableChatNotify = true, Prefix = "<color=orange>TC UPGRADES:</color>", Avatarid = 0, EenableGameTipnotify = true, NotificationPlugin = NotificationPluginType.None, NotificationTypes = new NotificationsType() {
Error = "error", Success = "success", Info = "info"
}
}
, Version = Version
}
;
}
#endregion
#region Data
private Hash<ulong, PlayerState> playersState = new Hash<ulong, PlayerState>();
private StoredData data = new StoredData();
private class PlayerState {
[JsonIgnore]
public ulong cupboardId;
[JsonIgnore]
public bool UIon;
[JsonIgnore]
public Coroutine upgradeCoroutine;
[JsonIgnore]
public Coroutine repairCoroutine;
[JsonIgnore]
public Coroutine skinCoroutine;
[JsonIgnore]
public Coroutine wallpaperCoroutine;
[JsonIgnore]
public HashSet<BuildingBlock> buildingHash;
[JsonIgnore]
public Queue<BuildingBlock> buildingQueue;
[JsonIgnore]
public HashSet<DecayEntity> decayHash;
[JsonIgnore]
public Queue<DecayEntity> decayQueue;
public ulong Wood = 0;
public ulong Stone = 0;
public ulong Metal = 0;
public ulong HQM = 0;
public uint MetalColor = 1;
public bool ShowEffect = true;
public PlayerState() {
buildingHash = Pool.Get<HashSet<BuildingBlock>>();
buildingQueue = Pool.Get<Queue<BuildingBlock>>();
decayHash = Pool.Get<HashSet<DecayEntity>>();
decayQueue = Pool.Get<Queue<DecayEntity>>();
}
}
private class StoredData {
public Dictionary<ulong, PlayerState> playerData = new();
}
private void SaveData() {
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/{Name}", data);
}
private void LoadData() {
data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"{Name}/{Name}");
if (data == null) {
data = new StoredData();
}
foreach (var d in data.playerData) {
playersState.Add(d.Key, d.Value);
}
}
#endregion
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string>() {
{
"NoRepairableStructures", "No repairable structures found."
}
, {
"NoRepairableDeployables", "No repairable deployables found."
}
, {
"NoUpgradeGrade", "No upgradable structures found."
}
, {
"NoWallpaper", "No changeable wallpaper found."
}
, {
"NoSkining", "No skin changeable block found."
}
, {
"AlreadyUpgrading", "An upgrade is already in progress.Please wait for it to finish."
}
, {
"AlreadyRepairing", "A repair process is already running.Please wait for it to complete."
}
, {
"AlreadySkining", "A base skinning process is already in progress.Please wait."
}
, {
"AlreadyWallpaper", "A wallpaper application is already in progress.Please wait."
}
, {
"NoResources", "Not enough resources in the tool cupboard to proceed with the upgrade."
}
, {
"NoResourcesReskin", "Not enough resources in the tool cupboard to proceed with the skin upgrade."
}
, {
"UpgradeComplete", "Material upgrade successfully completed."
}
, {
"RepairComplete", "Material repair successfully completed."
}
, {
"SkiningComplete", "Base skinning successfully completed."
}
, {
"WallpaperComplete", "Base wallpaper application successfully completed."
}
, {
"ProgressStatus", "Successfully updated {0} items."
}
, {
"RaidBlocked", "You cannot use this feature while under Raid Block."
}
, {
"CombatBlocked", "You cannot use this feature while under Combat Block."
}
, {
"StopCoro", "The process has been successfully stopped."
}
, {
"NoPerm", "You don't have permission to use this."
}
, {
"AUTHBTN", "AUTHS"
}
, {
"UPGRADEBTN", "UPGRADE"
}
, {
"REPAIRBTN", "REPAIR"
}
, {
"SKINBTN", "SKIN"
}
, {
"WALLPAPERBTN", "WALLPAPER"
}
, {
"EFFECTSON", "EFFECTS ON"
}
, {
"EFFECTSOFF", "EFFECTS OFF"
}
,
}
, this);
}
#endregion
#region Commands
[ConsoleCommand("tcupgrades.cmd")]
private void ConsoleCommandThings(ConsoleSystem.Arg arg) {
BasePlayer player = arg?.Player();
if (player == null) {
return;
}
string command = arg.Args[0];
var tc = player.GetBuildingPrivilege();
SoundEffect(player, ClickFX);
switch (command) {
case "cancelProcess" : {
DestroyUI(player);
StopPlayerCoroutine(player);
SendMessage(player, "StopCoro", true);
SendNotification(player, "error", "StopCoro");
NextTick(() => {
OnLootEntity(player, tc);
}
);
return;
}
case "authList" : {
DestroySide(player);
AuthList(player);
return;
}
case "changeEffects" : {
CuiHelper.DestroyUi(player, "EffectBTN");
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
value.ShowEffect = !value.ShowEffect;
EffectBTN(player);
return;
}
case "close_authlist" : {
CuiHelper.DestroyUi(player, "AuthList");
return;
}
case "close_UpgradeMat" : {
CuiHelper.DestroyUi(player, "UpgradeMaterial");
CuiHelper.DestroyUi(player, "EffectBTN");
return;
}
case "close_RepairBase" : {
CuiHelper.DestroyUi(player, "RepairBase");
CuiHelper.DestroyUi(player, "EffectBTN");
return;
}
case "close_SkinBase" : {
CuiHelper.DestroyUi(player, "SkinBase");
CuiHelper.DestroyUi(player, "EffectBTN");
return;
}
case "close_Wallpapers" : {
CuiHelper.DestroyUi(player, "WallpaperCg");
CuiHelper.DestroyUi(player, "ShowWallpaper");
CuiHelper.DestroyUi(player, "EffectBTN");
return;
}
case "close_WallpaperShow" : {
CuiHelper.DestroyUi(player, "WallpaperCg");
CuiHelper.DestroyUi(player, "ShowWallpaper");
CuiHelper.DestroyUi(player, "EffectBTN");
return;
}
case "removeFromAuth" : {
ulong id;
ulong playerID;
if (!ulong.TryParse(arg.Args[1], out id)) {
Puts("Failed to parse 'id' from arguments.");
return;
}
if (!ulong.TryParse(arg.Args[2], out playerID)) {
return;
}
if (tc == null) {
return;
}
if (!tc.IsAuthed(player)) {
return;
}
tc.authorizedPlayers.RemoveWhere(x => x.userid == playerID);
tc.SendNetworkUpdate();
AuthList(player);
return;
}
case "addToPromote" : {
ulong id;
ulong playerID;
if (!ulong.TryParse(arg.Args[1], out id)) {
return;
}
if (!ulong.TryParse(arg.Args[2], out playerID)) {
return;
}
return;
}
case "upgradeMaterials" : {
DestroySide(player);
UpgradeMaterial(player);
EffectBTN(player);
return;
}
case "selectToUpgrade" : {
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
string material = arg.Args[1];
DestroySide(player);
UpgradeMaterial(player, material);
EffectBTN(player);
return;
}
case "upgradeTo" : {
if (IsBlocked(player)) return;
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
string materialFrom = arg.Args[1];
string materialTo = arg.Args[2];
if (playersState[player.userID].upgradeCoroutine != null) {
DestroySide(player);
SendMessage(player, "AlreadyUpgrading", true);
SendNotification(player, "error", "AlreadyUpgrading");
return;
}
if (!ValidPermission(player, materialTo)) {
SendMessage(player, "NoPerm", true);
SendNotification(player, "error", "NoPerm");
return;
}
DestroySide(player);
playersState[player.userID].upgradeCoroutine = ServerMgr.Instance.StartCoroutine(UpgradeMaterialTC(player, tc, materialFrom, materialTo));
NextTick(() => {
CreateUpgradeButton(player, tc.net.ID.Value);
}
);
return;
}
case "repairBase" : {
DestroySide(player);
RepairBaseMaterial(player);
EffectBTN(player);
return;
}
case "repairBaseMat" : {
if (IsBlocked(player)) return;
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
if (playersState[player.userID].repairCoroutine != null) {
DestroySide(player);
SendMessage(player, "AlreadyRepairing", true);
SendNotification(player, "error", "AlreadyRepairing");
return;
}
string material = arg.Args[1];
if (!ValidPermission(player, material)) {
SendMessage(player, "NoPerm", true);
SendNotification(player, "error", "NoPerm");
return;
}
DestroySide(player);
if (material == "deploy") {
playersState[player.userID].repairCoroutine = ServerMgr.Instance.StartCoroutine(RepairMaterialTCDeploy(player, tc, material));
}
else {
playersState[player.userID].repairCoroutine = ServerMgr.Instance.StartCoroutine(RepairMaterialTC(player, tc, material));
}
NextTick(() => {
CreateUpgradeButton(player, tc.net.ID.Value);
}
);
return;
}
case "skinBaseSelect" : {
DestroySide(player);
SkinBaseUpgrade(player);
EffectBTN(player);
return;
}
case "skinBaseStart" : {
if (IsBlocked(player)) return;
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
if (playersState[player.userID].skinCoroutine != null) {
DestroySide(player);
SendMessage(player, "AlreadySkining", true);
SendNotification(player, "error", "AlreadySkining");
return;
}
DestroySide(player);
if (ulong.TryParse(arg.Args[1], out var skinID)) {
var skinGrade = GetBuildingGradeFromSkin(skinID);
if (skinGrade == BuildingGrade.Enum.Metal && (GetNatID(skinID) != 0)) {
DestroySide(player);
SkinBaseUpgrade(player, true);
EffectBTN(player);
}
else {
playersState[player.userID].skinCoroutine = ServerMgr.Instance.StartCoroutine(SkiningBaseTC(player, tc, skinID));
}
}
NextTick(() => {
CreateUpgradeButton(player, tc.net.ID.Value);
}
);
return;
}
case "skinBaseSetColor" : {
if (IsBlocked(player)) return;
bool random = false;
DestroySide(player);
uint color = Convert.ToUInt32(arg.Args[1]);
ulong SkinID = ulong.Parse(arg.Args[2]);
if (color == 9999) {
random = true;
color = 1;
}
SetPlayerSkinID(player, BuildingGrade.Enum.Metal, SkinID, color);
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
if (playersState[player.userID].skinCoroutine != null) {
DestroySide(player);
SendMessage(player, "AlreadySkining", true);
SendNotification(player, "error", "AlreadySkining");
return;
}
DestroySide(player);
playersState[player.userID].skinCoroutine = ServerMgr.Instance.StartCoroutine(SkiningBaseTC(player, tc, SkinID, random));
NextTick(() => {
CreateUpgradeButton(player, tc.net.ID.Value);
}
);
return;
}
case "showWallpapersView" : {
DestroySide(player);
ChangeWallpaper(player);
EffectBTN(player);
return;
}
case "viewWallpaper" : {
DestroySide(player);
string material = arg.Args[1];
ShowWallpapers(player, material);
EffectBTN(player);
return;
}
case "changeWallpaper" : {
if (IsBlocked(player)) {
Puts($"[DEBUG] Player {player.userID} is blocked.");
return;
}
if (!playersState.TryGetValue(player.userID, out PlayerState value)) {
value = new PlayerState();
playersState.Add(player.userID, value);
}
if (playersState[player.userID].wallpaperCoroutine != null) {
DestroySide(player);
SendMessage(player, "AlreadyWallpaper", true);
SendNotification(player, "error", "AlreadyWallpaper");
return;
}
ulong wallpaperID = ulong.Parse(arg.Args[1]);
string material = arg.Args[2];
if (!ValidPermission(player, material)) {
SendMessage(player, "NoPerm", true);
SendNotification(player, "error", "NoPerm");
return;
}
DestroySide(player);
playersState[player.userID].wallpaperCoroutine = ServerMgr.Instance.StartCoroutine(WallpaperSkinProgress(player, tc, wallpaperID, material));
NextTick(() => {
CreateUpgradeButton(player, tc.net.ID.Value);
}
);
return;
}
}
}
#endregion
#region Init
private void Loaded() {
LoadData();
}
private void OnServerInitialized() {
if (ImageLibrary == null) {
Interface.Oxide.LogError("Missing ImageLibrary plugin; Download it at: https://umod.org/plugins/image-library");
Interface.Oxide.UnloadPlugin(Name);
return;
}
LoadPlayersState();
RegisterImages();
RegisterStaticPerms();
RegisterCustomPerms();
}
private void Unload() {
SaveData();
foreach (BasePlayer player in BasePlayer.activePlayerList) {
DestroyUI(player);
}
}
private void OnServerSave() {
SaveData();
}
private void OnNewSave(string filename) {
if (data != null && data.playerData != null) {
data.playerData.Clear();
SaveData();
}
}
#endregion
#region IEnumerators
private IEnumerator WallpaperSkinProgress(BasePlayer player, BuildingPrivlidge tc, ulong wallpaperID, string material) {
var grade = material switch {
"wood" => BuildingGrade.Enum.Wood, "stone" => BuildingGrade.Enum.Stone, "metal" => BuildingGrade.Enum.Metal, "hqm" => BuildingGrade.Enum.TopTier, _ => BuildingGrade.Enum.Twigs
}
;
var freq = GetPlayerFrequency(player, config.Features.EnableBaseWallpaperUpgrade);
float costModifier = GetPlayerCostModifers(player, config.Features.EnableBaseWallpaperUpgrade);
int count = 0;
bool hasNoCostPermission = HasPermission(player, PermWallpaperNoCost);
if (playersState[player.userID].buildingHash == null) {
playersState[player.userID].buildingHash = Pool.Get<HashSet<BuildingBlock>>();
}
else {
Pool.FreeUnmanaged(ref playersState[player.userID].buildingHash);
playersState[player.userID].buildingHash = Pool.Get<HashSet<BuildingBlock>>();
}
if (playersState[player.userID].buildingQueue == null) {
playersState[player.userID].buildingQueue = Pool.Get<Queue<BuildingBlock>>();
}
else {
Pool.FreeUnmanaged(ref playersState[player.userID].buildingQueue);
playersState[player.userID].buildingQueue = Pool.Get<Queue<BuildingBlock>>();
}
var processedEntities = playersState[player.userID].buildingHash;
var checkQueue = playersState[player.userID].buildingQueue;
var buildings = tc.GetBuilding().buildingBlocks.Where(block => block != null && block.IsValid() && !block.IsDestroyed && block.transform != null).ToList();
foreach (var block in buildings) {
checkQueue.Enqueue(block);
processedEntities.Add(block);
}
yield return CoroutineEx.waitForSeconds(0.15f);
while (checkQueue.Count > 0) {
if (IsBlocked(player)) {
Pool.FreeUnmanaged(ref checkQueue);
Pool.FreeUnmanaged(ref processedEntities);
playersState[player.userID].wallpaperCoroutine = null;
CheckForUIs(player);
yield break;
}
var block = checkQueue.Dequeue();
if (block.grade != grade || !block.ShortPrefabName.Contains("wall") || block.HasWallpaper() && block.wallpaperID == wallpaperID || block.SecondsSinceAttacked < 30f) {
var nearbyEntities1 = FindEntities<BuildingBlock>(block.transform.position, DistanceThreshold);
foreach (var nearbyBlock in nearbyEntities1) {
if (!processedEntities.Contains(nearbyBlock)) {
checkQueue.Enqueue(nearbyBlock);
processedEntities.Add(nearbyBlock);
}
}
Pool.FreeUnmanaged(ref nearbyEntities1);
continue;
}
if (!hasNoCostPermission && !HasResoucesWallpaper(player, tc, costModifier)) {
SendMessage(player, "NoResources", true);
SendNotification(player, "error", "NoResources");
Pool.FreeUnmanaged(ref checkQueue);
Pool.FreeUnmanaged(ref processedEntities);
playersState[player.userID].wallpaperCoroutine = null;
CheckForUIs(player);
yield break;
}
if (!hasNoCostPermission) {
TakeFromInv(tc.inventory.itemList, "cloth", (int)(10 * costModifier));
}
block.RemoveWallpaper(0);
block.SetWallpaper(wallpaperID);
if (CheckWallpaper(block)) {
block.RemoveWallpaper(1);
block.SetWallpaper(wallpaperID, 1);
}
block.SendNetworkUpdate();
count++;
if (playersState[player.userID].ShowEffect) {
Effect.server.Run("assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab", block.transform.position);
Effect.server.Run("assets/prefabs/deployable/research tab
// ... [Code preview truncated due to length. Full source in attached file] ...