C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
#if CARBON
using Carbon.Modules;
using Carbon.Extensions;
using Carbon;
#endif
using HarmonyLib;
using System;
using System.Globalization;
using System.Net;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using ProtoBuf;
using UnityEngine;
using Newtonsoft.Json;
using Facepunch;
using Rust;
namespace Oxide.Plugins {
[Info("BetterTC", "ninco90", "1.5.6")]
internal class BetterTC : RustPlugin {
#if CARBON
private ImageDatabaseModule imageDb;
#endif
#region Fields
[PluginReference]
private Plugin ImageLibrary, NoEscape, RaidBlock, TiersMode, Notify, UINotify, TCLevels;
string[] incompatiblePlugins = {
"BuildingSkin", "BuildingSkins", "XBuildingSkinMenu", "IQGradeRemove"
}
;
private const string InstanceId = "com.ninco90.BetterTC";
public static BetterTC self;
private const string fxnoresources = "assets/bundled/prefabs/fx/ore_break.prefab";
private const string fxfinish = "assets/prefabs/deployable/research table/effects/research-success.prefab";
private const string fxspray = "assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab";
private const string fxreskin = "assets/prefabs/tools/spraycan/reskineffect.prefab";
private const string fxwall = "assets/prefabs/building/wall.external.high.stone/effects/wall-external-stone-deploy.prefab";
private const string fxcloth = "assets/prefabs/wallpaper/effects/place.prefab";
//old assets/bundled/prefabs/fx/impacts/blunt/cloth/cloth1.prefab
private const string fxrepair = "assets/prefabs/deployable/modular car lift/effects/modular-car-lift-repair.prefab";
private const string fxerror = "assets/prefabs/weapons/toolgun/effects/repairerror.prefab";
private const string permadmin = "bettertc.admin";
private const string permupgrade = "bettertc.upgrade";
private const string permupgradenocost = "bettertc.upgrade.nocost";
private const string permrepair = "bettertc.repair";
private const string permrepairnocost = "bettertc.repair.nocost";
private const string permreskin = "bettertc.reskin";
private const string permreskinnocost = "bettertc.reskin.nocost";
private const string permwallpaper = "bettertc.wallpaper";
private const string permwallpapernocost = "bettertc.wallpaper.nocost";
private const string permwallpapercustom = "bettertc.wallpaper.custom";
private const string permlist = "bettertc.authlist";
private const string permdelauth = "bettertc.deleteauth";
private const string permtcskin = "bettertc.tcskinchange";
private const string permtcskindeployed = "bettertc.tcskindeployed";
private const string permupskin = "bettertc.upskin";
private const string permupwall = "bettertc.upwall";
private const string upgrade_0 = "upgrade.base";
private const string upgrade_1 = "upgrade.windows";
private const string upgrade_2 = "upgrade.item";
private const string upgrade_3 = "upgrade.subitem";
private const string buttons_0 = "buttons.cup";
private const string color_0 = "color.base";
private const string color_1 = "color.windows";
private const string color_2 = "color.item";
private const string color_3 = "color.subitem";
private const string tcskin_0 = "color.base";
private const string tcskin_1 = "color.windows";
private const string tcskin_2 = "color.item";
private const string tcskin_3 = "color.subitem";
private const string authlist_0 = "authlist.base";
private const string authlist_1 = "authlist.windows";
private const string authlist_2 = "authlist.item";
private const string authlist_3 = "authlist.subitem";
private ulong hammerWallpaperSkin = 3494416562;
private const string apiUrl = "https://cdn.rustspain.com/plugins/bettertc/bettertc.json";
private Dictionary<BuildingPrivlidge, TCConfig> BuildingCupboard = new Dictionary<BuildingPrivlidge, TCConfig>();
private int maxGradeTier;
private Dictionary<ulong, TCSkin> playerSelectedSkins = new Dictionary<ulong, TCSkin>();
string[] skins = {
"cupboard.tool", "cupboard.tool.retro", "cupboard.tool.shockbyte"
}
;
int[] skins2 = {
-97956382, 1488606552, 1174957864
}
;
bool incompatibleFound = false;
private Dictionary<int, string> WallPrefabs = new Dictionary<int, string> {
{
0, "assets/prefabs/building/wall.external.high.wood/wall.external.high.wood.prefab"
}
, {
10303, "assets/prefabs/building/wall.external.high.legacy/wall.external.high.legacy.prefab"
}
, {
1, "assets/prefabs/building/wall.external.high.stone/wall.external.high.stone.prefab"
}
, {
10304, "assets/prefabs/building/wall.external.high.adobe/wall.external.high.adobe.prefab"
}
, {
2, "assets/prefabs/misc/xmas/icewalls/wall.external.high.ice.prefab"
}
,
}
;
private Dictionary<int, string> GatePrefabs = new Dictionary<int, string> {
{
0, "assets/prefabs/building/gates.external.high/gates.external.high.wood/gates.external.high.wood.prefab"
}
, {
10303, "assets/prefabs/building/gates.external.high.legacy/gates.external.high.legacy.prefab"
}
, {
1, "assets/prefabs/building/gates.external.high/gates.external.high.stone/gates.external.high.stone.prefab"
}
, {
10304, "assets/prefabs/building/gates.external.high.adobe/gates.external.high.adobe.prefab"
}
, {
2, "assets/prefabs/building/gates.external.high/gates.external.high.stone/gates.external.high.stone.prefab"
}
,
}
;
string[] colors = {
"", "0.25 0.56 0.75 1", "0.25 0.72 0.31 1", "0.65 0.28 0.85 1", "0.48 0.15 0.08 1", "0.92 0.46 0.06 1", "0.87 0.87 0.87 1", "0.18 0.18 0.16 1", "0.42 0.33 0.27 1", "0.17 0.21 0.33 1", "0.16 0.34 0.17 1", "0.83 0.29 0.16 1", "0.85 0.53 0.38 1", "0.90 0.67 0.15 1", "0.34 0.32 0.31 1", "0.08 0.33 0.37 1", "0.68 0.61 0.56 1"
}
;
public enum TCSkin {
Default, Retro, Shockbyte
}
private enum WallMaterialType {
Wood, Stone, Unknown
}
#endregion
#region Hooks
void Init() {
Unsubscribe(nameof(OnEntitySpawned));
}
private void OnServerInitialized() {
LoadData();
self = this;
if (!permission.PermissionExists(permadmin, this)) permission.RegisterPermission(permadmin, this);
if (!permission.PermissionExists(permupgrade, this)) permission.RegisterPermission(permupgrade, this);
if (!permission.PermissionExists(permupgradenocost, this)) permission.RegisterPermission(permupgradenocost, this);
if (!permission.PermissionExists(permrepair, this)) permission.RegisterPermission(permrepair, this);
if (!permission.PermissionExists(permrepairnocost, this)) permission.RegisterPermission(permrepairnocost, this);
if (!permission.PermissionExists(permreskin, this)) permission.RegisterPermission(permreskin, this);
if (!permission.PermissionExists(permreskinnocost, this)) permission.RegisterPermission(permreskinnocost, this);
if (!permission.PermissionExists(permwallpaper, this)) permission.RegisterPermission(permwallpaper, this);
if (!permission.PermissionExists(permwallpapernocost, this)) permission.RegisterPermission(permwallpapernocost, this);
if (!permission.PermissionExists(permwallpapercustom, this)) permission.RegisterPermission(permwallpapercustom, this);
if (!permission.PermissionExists(permlist, this)) permission.RegisterPermission(permlist, this);
if (!permission.PermissionExists(permdelauth, this)) permission.RegisterPermission(permdelauth, this);
if (!permission.PermissionExists(permtcskin, this)) permission.RegisterPermission(permtcskin, this);
if (!permission.PermissionExists(permtcskindeployed, this)) permission.RegisterPermission(permtcskindeployed, this);
if (!permission.PermissionExists(permupskin, this)) permission.RegisterPermission(permupskin, this);
if (!permission.PermissionExists(permupwall, this)) permission.RegisterPermission(permupwall, this);
foreach (var check in config.FrequencyUpgrade) {
if (!permission.PermissionExists(check.Key, this)) permission.RegisterPermission(check.Key, this);
}
Dictionary<string, string> imageListCraft = new Dictionary<string, string>();
foreach (var recipe in config.itemsList) {
if (!permission.PermissionExists(recipe.permission, this)) permission.RegisterPermission(recipe.permission, this);
if (recipe.img != "" && !imageListCraft.ContainsKey(recipe.img)) imageListCraft.Add(recipe.img, recipe.img);
}
imageListCraft.Add("color_0", "https://cdn.rustspain.com/plugins/bettertc/colours/0.png");
imageListCraft.Add("lock5", "https://cdn.rustspain.com/plugins/bettertc/lock5.png");
imageListCraft.Add("upgrade2", "https://cdn.rustspain.com/plugins/bettertc/upgrade.png");
imageListCraft.Add("nowp", "https://cdn.rustspain.com/plugins/bettertc/no.png");
#if CARBON
if (imageDb == null) imageDb = Carbon.Base.BaseModule.GetModule<ImageDatabaseModule>();
if (imageDb != null) {
foreach (var kvp in imageListCraft) {
imageDb.Queue(kvp.Key, kvp.Value);
}
}
#else
ImageLibrary?.Call("ImportImageList", Title, imageListCraft, 0UL, true, null);
#endif
ApplyHarmonyPatches();
foreach (var tc in BaseNetworkable.serverEntities.OfType<BuildingPrivlidge>()) {
if (tc == null) {
continue;
}
UpdateBlockedItems(tc);
}
Subscribe(nameof(OnEntitySpawned));
if (config.autoCheck) GetNewItems(null);
incompatibleFound = incompatiblePlugins.Any(plugin => plugins.Exists(plugin));
}
private void Unload() {
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, buttons_0);
CuiHelper.DestroyUi(player, upgrade_0);
CuiHelper.DestroyUi(player, color_0);
CuiHelper.DestroyUi(player, tcskin_0);
CuiHelper.DestroyUi(player, authlist_0);
}
foreach (var cup in BuildingCupboard) {
if (cup.Value.workupgrade != null) ServerMgr.Instance.StopCoroutine(cup.Value.workupgrade);
if (cup.Value.workrepair != null) ServerMgr.Instance.StopCoroutine(cup.Value.workrepair);
if (cup.Value.workreskin != null) ServerMgr.Instance.StopCoroutine(cup.Value.workreskin);
if (cup.Value.workwallpaper != null) ServerMgr.Instance.StopCoroutine(cup.Value.workwallpaper);
if (cup.Value.workupwall != null) ServerMgr.Instance.StopCoroutine(cup.Value.workupwall);
}
//if (_harmony != null) _harmony.UnpatchAll(InstanceId);
}
private void OnEntitySpawned(BuildingPrivlidge tc) {
if (tc == null) return;
if (tc.skinID == 0) UpdateBlockedItems(tc);
}
private void OnEntityBuilt(Planner plan, GameObject go) {
if(plan == null || go == null || !(go.ToBaseEntity() is BuildingPrivlidge)) return;
BasePlayer player = plan.GetOwnerPlayer();
BuildingPrivlidge tc = go.ToBaseEntity() as BuildingPrivlidge;
if (!HasPermission(player.UserIDString, permtcskindeployed)) return;
TCSkin selectedSkin = TCSkin.Retro;
if (playerSelectedSkins.TryGetValue(player.userID, out TCSkin storedSkin)) {
selectedSkin = storedSkin;
}
string expectedShortName = GetShortNameForSkin(selectedSkin);
if (tc.ShortPrefabName != expectedShortName) TCSkinReplace(tc, player, selectedSkin);
}
object OnHammerHit(BasePlayer player, HitInfo info) {
if (info == null || info.HitEntity == null) return null;
if (!IsUsingWallpaperHammer(player)) return null;
BuildingBlock block = info.HitEntity as BuildingBlock;
if (block == null) return null;
if (!IsFloorOrFoundation(block)) return null;
RotateWallpaper(block);
return null;
}
private string GetShortNameForSkin(TCSkin skin) => skin switch {
TCSkin.Retro => "cupboard.tool.retro.deployed", TCSkin.Shockbyte => "cupboard.tool.shockbyte.deployed", _ => "cupboard.tool.deployed"
}
;
private void OnLootEntity(BasePlayer player, BuildingPrivlidge cup) {
if (player == null || cup == null) return;
if (!BuildingCupboard.ContainsKey(cup)) {
BuildingCupboard.Add(cup, new TCConfig() {
grade = BuildingGrade.Enum.Wood, skinid = 0, color = false, colour = 0, work = false, repair = false, reskin = false, upwall = false, effect = true, downgrade = false, wallpaperid = 1, wpbothsides = false
}
);
}
ShowButtonTC(player, cup);
}
private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity) {
if (player == null) return;
CuiHelper.DestroyUi(player, buttons_0);
CuiHelper.DestroyUi(player, upgrade_0);
CuiHelper.DestroyUi(player, authlist_0);
}
private void OnRaidBlockStarted(BasePlayer player) => OnRaidBlock(player);
private void OnRaidBlock(BasePlayer player, Vector3 pos) => OnRaidBlock(player);
private void OnRaidBlock(BasePlayer player) {
if(player == null || player.userID == null) return;
foreach (var cup in BuildingCupboard) {
if (cup.Value.player == player.userID) {
if (cup.Value.workupgrade != null) {
ServerMgr.Instance.StopCoroutine(cup.Value.workupgrade);
}
if (cup.Value.workrepair != null) {
ServerMgr.Instance.StopCoroutine(cup.Value.workrepair);
}
if (cup.Value.workreskin != null) {
ServerMgr.Instance.StopCoroutine(cup.Value.workreskin);
}
if (cup.Value.workwallpaper != null) {
ServerMgr.Instance.StopCoroutine(cup.Value.workwallpaper);
}
if (cup.Value.workupwall != null) {
ServerMgr.Instance.StopCoroutine(cup.Value.workupwall);
}
cup.Value.workupgrade = null;
cup.Value.workrepair = null;
cup.Value.workreskin = null;
cup.Value.workwallpaper = null;
cup.Value.workupwall = null;
break;
}
}
}
#endregion
#region Function
private IEnumerator UpdateCost(BasePlayer player, BuildingPrivlidge cup) {
var set = cup.GetBuilding().buildingBlocks;
List<ulong> playerTeamMembers = new List<ulong>();
if (config.teamupdate) {
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(player.userID);
if (playerTeam == null) {
playerTeamMembers.Add(player.userID);
}
else {
playerTeamMembers = playerTeam?.members?.ToList() ?? new List<ulong>();
}
}
Dictionary<ItemDefinition, int> totalCost = new Dictionary<ItemDefinition, int>();
for (var index = 0; index < set.Count; index++) {
var block = set[index];
if (cup == null) yield break;
var grade = BuildingCupboard[cup].grade;
if (!config.teamupdate || playerTeamMembers.Contains(block.OwnerID)) {
if (grade == block.grade) continue;
bool canDowngrade = config.downgrade && BuildingCupboard[cup].downgrade;
bool isOwner = player.userID == block.OwnerID;
bool shouldOnlyOwnerDowngrade = config.onlyowner && !isOwner;
bool shouldOnlyOwnerUpgrade = config.onlyownerup && !isOwner;
if ((!canDowngrade || shouldOnlyOwnerDowngrade) && (grade < block.grade)) continue;
if (shouldOnlyOwnerUpgrade && (grade > block.grade)) continue;
List<ItemAmount> upgradeCost = block.blockDefinition.GetGrade(grade, 0).CostToBuild();
foreach (var item in upgradeCost) {
if (totalCost.ContainsKey(item.itemDef)) {
totalCost[item.itemDef] += (int)item.amount;
}
else {
totalCost[item.itemDef] = (int)item.amount;
}
}
}
}
string costMessage = "";
foreach (var cost in totalCost) {
costMessage += $"{cost.Value} x {cost.Key.displayName.english}\n";
}
CreateGameTip(cup, totalCost.Count == 0 ? Lang("NoUpgradeAvailable", player.UserIDString) : Lang("TotalCostUP", player.UserIDString, costMessage), player, fxfinish, 10);
//Puts("Cost Upgrade: " + (totalCost.Count == 0 ? Lang("NoUpgradeAvailable", player.UserIDString) : Lang("TotalCostUP", player.UserIDString, costMessage)) + " TC: " + player.transform.position);
playerTeamMembers.Clear();
totalCost.Clear();
yield return 0;
}
private IEnumerator RepairProgress(BasePlayer player, BuildingPrivlidge cup) {
var building = cup.GetBuilding();
yield return CoroutineEx.waitForSeconds(0.15f);
var cd = Frequency(player.UserIDString, config.FrequencyRepair);
var cost = ResourcesRepair(player.UserIDString);
bool show = true;
bool warned = false;
var allEntities = new List<BaseCombatEntity>();
allEntities.AddRange(building.buildingBlocks);
if (config.Deployables) allEntities.AddRange(building.decayEntities);
foreach (var entity in allEntities) {
if (!BuildingCupboard[cup].repair) {
show = false;
break;
}
if (entity.SecondsSinceAttacked < config.repairCooldown) {
if (!warned) {
warned = true;
float remaining = config.repairCooldown - entity.SecondsSinceAttacked;
CreateGameTip(cup, Lang("RepairBlockedRecentDamage", player.UserIDString, entity.ShortPrefabName, remaining.ToString("0.0")), player, fxnoresources, 10, "warning");
}
continue;
}
if (!RepairBlock(player, entity, cup, cost, !(entity is BuildingBlock))) continue;
yield return CoroutineEx.waitForSeconds(cd);
}
BuildingCupboard[cup].repair = false;
BuildingCupboard[cup].workrepair = null;
if (show) CreateGameTip(cup, Lang("RepairFinish", player.UserIDString), player, fxfinish, 10);
yield return 0;
}
private bool RepairBlock(BasePlayer player, BaseCombatEntity entity, BuildingPrivlidge cup, float cost, bool deployed) {
if (entity == null || !entity.IsValid() || entity.IsDestroyed || entity.transform == null) return false;
if (!entity.repair.enabled || entity.health == entity.MaxHealth()) return false;
if (Interface.CallHook("OnStructureRepair", entity, player) != null) return false;
var missingHealth = entity.MaxHealth() - entity.health;
var healthPercentage = missingHealth / entity.MaxHealth();
if (missingHealth <= 0f || healthPercentage <= 0f) {
entity.OnRepairFailed(null, string.Empty);
return false;
}
var itemAmounts = entity.RepairCost(healthPercentage);
if (itemAmounts.Sum(x => x.amount) <= 0f) {
entity.health += missingHealth;
entity.SendNetworkUpdate();
entity.OnRepairFinished(player);
return true;
}
if (!HasPermission(player.UserIDString, permrepairnocost)) {
foreach (var amount in itemAmounts) {
amount.amount *= cost;
}
if (itemAmounts.Any(ia => cup.inventory.GetAmount(ia.itemid, false) < (int)ia.amount)) {
entity.OnRepairFailed(null, string.Empty);
CreateGameTip(cup, Lang("NoResourcesRepair", player.UserIDString), player, fxnoresources, 10, "danger");
BuildingCupboard[cup].repair = false;
return false;
}
foreach (var amount in itemAmounts) {
cup.inventory.Take(null, amount.itemid, (int)amount.amount);
}
}
if (config.playfx && BuildingCupboard[cup].effect && deployed) {
Effect.server.Run(fxrepair, entity.transform.position);
}
entity.health += missingHealth;
entity.SendNetworkUpdate();
if (entity.health < entity.MaxHealth()) {
entity.OnRepair();
}
else {
entity.OnRepairFinished(player);
}
return true;
}
private IEnumerator UpdateProgress(BasePlayer player, BuildingPrivlidge cup) {
var set = cup.GetBuilding().buildingBlocks;
yield return CoroutineEx.waitForSeconds(0.15f);
var cd = Frequency(player.UserIDString, config.FrequencyUpgrade);
bool show = true;
List<ulong> playerTeamMembers = new List<ulong>();
if (config.teamupdate) {
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(player.userID);
if (playerTeam == null) {
playerTeamMembers.Add(player.userID);
}
else {
playerTeamMembers = playerTeam?.members?.ToList() ?? new List<ulong>();
}
}
for (var index = 0; index < set.Count; index++) {
var block = set[index];
if (cup == null) yield break;
if (!BuildingCupboard[cup].work) {
show = false;
break;
}
var grade = BuildingCupboard[cup].grade;
if (!config.teamupdate || playerTeamMembers.Contains(block.OwnerID)) {
if (grade == block.grade) continue;
if (!incompatibleFound) {
if (Interface.CallHook("OnStructureUpgrade", block, player, grade) != null) {
BuildingCupboard[cup].work = false;
ShowButtonTC(player, cup);
CreateGameTip(cup, Lang("UpgradeBlock", player.UserIDString), player, fxnoresources, 10, "danger");
show = false;
break;
}
}
bool canDowngrade = config.downgrade && BuildingCupboard[cup].downgrade;
bool isOwner = player.userID == block.OwnerID;
bool shouldOnlyOwnerDowngrade = config.onlyowner && !isOwner;
bool shouldOnlyOwnerUpgrade = config.onlyownerup && !isOwner;
if ((!canDowngrade || shouldOnlyOwnerDowngrade) && (grade < block.grade)) continue;
if (shouldOnlyOwnerUpgrade && (grade > block.grade)) continue;
UpgradeBlock(cup, block, grade, player);
yield return CoroutineEx.waitForSeconds(cd);
}
}
BuildingCupboard[cup].work = false;
BuildingCupboard[cup].workupgrade = null;
if (show) {
if (playerTeamMembers.Count == 1) {
CreateGameTip(cup, Lang("UpgradeFinishNoPlayer", player.UserIDString), player, fxfinish, 10);
}
else {
CreateGameTip(cup, Lang("UpgradeFinish", player.UserIDString), player, fxfinish, 10);
}
/*foreach (ulong member in playerTeamMembers){
Puts("SteamID " + member);
}*/
}
playerTeamMembers.Clear();
yield return 0;
}
private void UpgradeBlock(BuildingPrivlidge cup, BuildingBlock block, BuildingGrade.Enum grade, BasePlayer player) {
if (!HasPermission(player.UserIDString, permupgradenocost) && !CanUpgrade(player, cup, block, grade)) {
BuildingCupboard[cup].work = false;
CreateGameTip(cup, Lang("NoResourcesUpgrade", player.UserIDString), player, fxnoresources, 10, "danger");
return;
}
if (CheckBlock(block)) return;
if (!HasPermission(player.UserIDString, permupgradenocost)) {
var list = block.blockDefinition.GetGrade(grade, 0).CostToBuild();
for (var index = 0; index < list.Count; index++) {
var check = list[index];
TakeResources(cup.inventory.itemList, check.itemDef.shortname, (int)check.amount);
}
}
ulong skin = Convert.ToUInt32(BuildingCupboard[cup].skinid);
block.skinID = skin;
if (config.playfx && BuildingCupboard[cup].effect) {
var effect = "assets/bundled/prefabs/fx/build/promote_toptier.prefab";
if(grade == BuildingGrade.Enum.Wood) {
effect = "assets/bundled/prefabs/fx/build/frame_place.prefab";
block.ClientRPC<int, ulong>(null, "DoUpgradeEffect", (int)BuildingGrade.Enum.Wood, skin);
}
else if(grade == BuildingGrade.Enum.Stone) {
effect = "assets/bundled/prefabs/fx/build/promote_stone.prefab";
block.ClientRPC<int, ulong>(null, "DoUpgradeEffect", (int)BuildingGrade.Enum.Stone, skin);
}
else if(grade == BuildingGrade.Enum.Metal) {
effect = "assets/bundled/prefabs/fx/build/promote_metal.prefab";
block.ClientRPC<int, ulong>(null, "DoUpgradeEffect", (int)BuildingGrade.Enum.Metal, skin);
}
else {
block.ClientRPC<int, ulong>(null, "DoUpgradeEffect", (int)BuildingGrade.Enum.TopTier, skin);
}
Effect.server.Run(effect, block.transform.position);
}
block.SetGrade(grade);
block.UpdateSkin();
block.SetHealthToMax();
if(BuildingCupboard[cup].color) block.SetCustomColour(BuildingCupboard[cup].colour);
block.SendNetworkUpdateImmediate();
}
private IEnumerator ReskinProgress(BasePlayer player, BuildingPrivlidge cup) {
var set = cup.GetBuilding().buildingBlocks;
yield return CoroutineEx.waitForSeconds(0.15f);
var cd = Frequency(player.UserIDString, config.FrequencyReskin);
bool show = true;
for (var index = 0; index < set.Count; index++) {
var block = set[index];
if (cup == null) yield break;
if(!BuildingCupboard[cup].reskin) {
show = false;
break;
}
var grade = BuildingCupboard[cup].grade;
if (grade != block.grade) continue;
if (Convert.ToUInt32(BuildingCupboard[cup].skinid) == block.skinID && BuildingCupboard[cup].colour == block.customColour) continue;
ReskinBlock(cup, block, grade, player);
yield return CoroutineEx.waitForSeconds(cd);
}
BuildingCupboard[cup].reskin = false;
BuildingCupboard[cup].workreskin = null;
if(show) CreateGameTip(cup, Lang("ReskinFinish", player.UserIDString), player, fxfinish, 10);
yield return 0;
}
private void ReskinBlock(BuildingPrivlidge cup, BuildingBlock block, BuildingGrade.Enum grade, BasePlayer player) {
if (!HasPermission(player.UserIDString, permreskinnocost) && !CanUpgrade(player, cup, block, grade)) {
BuildingCupboard[cup].reskin = false;
CreateGameTip(cup, Lang("NoResourcesReskin", player.UserIDString), player, fxnoresources, 10, "danger");
return;
}
if (CheckBlock(block)) return;
if (!HasPermission(player.UserIDString, permreskinnocost)) {
var list = block.blockDefinition.GetGrade(grade, 0).CostToBuild();
for (var index = 0; index < list.Count; index++) {
var check = list[index];
TakeResources(cup.inventory.itemList, check.itemDef.shortname, (int)check.amount);
}
}
ulong skin = Convert.ToUInt32(BuildingCupboard[cup].skinid);
block.skinID = skin;
block.UpdateSkin();
if(BuildingCupboard[cup].color) block.SetCustomColour(BuildingCupboard[cup].colour);
block.SendNetworkUpdateImmediate();
if (config.playfx && BuildingCupboard[cup].effect) {
Effect.server.Run(fxspray, block.transform.position);
Effect.server.Run(fxreskin, block.transform.position);
}
}
private IEnumerator ReskinProgressWall(BasePlayer player, BuildingPrivlidge cup) {
if (cup == null || player == null || !BuildingCupboard.ContainsKey(cup)) yield break;
Vector3 center = cup.transform.position;
float radius = config.upwalldis;
float delay = Frequency(player.UserIDString, config.FrequencyReskin);
var grade = BuildingCupboard[cup].grade;
bool show = false;
List<ulong> validOwners = new List<ulong> {
player.userID
}
;
if (player.currentTeam != 0) {
RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
if (team != null) validOwners.AddRange(team.members);
}
List<BaseEntity> nearbyWalls = Pool.GetList<BaseEntity>();
Vis.Entities(center, radius, nearbyWalls, LayerMask.GetMask("Construction"));
for (int i = 0; i < nearbyWalls.Count; i++) {
if (!BuildingCupboard[cup].upwall) {
show = false;
break;
}
BaseEntity wall = nearbyWalls[i];
if (wall == null || wall.ShortPrefabName == null) continue;
if (!wall.ShortPrefabName.Contains("wall.external") && !wall.ShortPrefabName.Contains("gates.external.high")) continue;
if (!validOwners.Contains(wall.OwnerID)) continue;
string targetPrefab = GetTargetPrefab(wall.ShortPrefabName, BuildingCupboard[cup].skinid);
if (targetPrefab == wall.PrefabName) continue;
if (config.samewallgrade) {
WallMaterialType currentType = GetWallType(wall.ShortPrefabName);
WallMaterialType targetType = GetWallType(targetPrefab);
if (!CanChangeWall(currentType, targetType)) continue;
}
ReskinWall(cup, wall, player);
yield return CoroutineEx.waitForSeconds(delay);
show = true;
}
Pool.FreeList(ref nearbyWalls);
BuildingCupboard[cup].upwall = false;
BuildingCupboard[cup].workupwall = null;
if (show) CreateGameTip(cup, Lang("ReskinWallFinish", player.UserIDString), player, fxfinish, 10);
yield return 0;
}
private void ReskinWall(BuildingPrivlidge cup, BaseEntity wall, BasePlayer player) {
/*if (!HasPermission(player.UserIDString, permreskinnocost)){
BuildingCupboard[cup].upwall = false;
CreateGameTip(cup, Lang("NoResourcesReskin", player.UserIDString), player, fxnoresources, 10, "danger");
return;
}*/
var pos = wall.transform.position;
var rot = wall.transform.rotation;
var skinid = BuildingCupboard[cup].skinid;
var ownerID = wall.OwnerID;
string newPrefab = GetTargetPrefab(wall.ShortPrefabName, BuildingCupboard[cup].skinid);
var newEntity = GameManager.server.CreateEntity(newPrefab, pos, rot, true);
if (newEntity == null) {
Puts("Error Spawn Wall.");
return;
}
if (newEntity.ShortPrefabName == "wall.external.high.legacy") {
newEntity.Invoke("PopulateVariants", 0f);
}
newEntity.skinID = 0;
newEntity.OwnerID = ownerID;
newEntity.Spawn();
BaseCombatEntity baseCombatEntity2 = newEntity as BaseCombatEntity;
if (baseCombatEntity2 != null) {
baseCombatEntity2.SetHealth(wall.Health());
baseCombatEntity2.lastAttackedTime = 0;
}
CopyLock(wall, newEntity);
wall.Kill();
if (config.playfx && BuildingCupboard[cup].effect) {
Effect.server.Run(fxspray, pos);
Effect.server.Run(fxwall, pos);
}
}
private bool IsFoundation(BuildingBlock block) {
return block.ShortPrefabName.Contains("foundation");
}
bool IsTriangle(BuildingBlock block) {
return block.ShortPrefabName.Contains("triangle");
}
private bool IsFloorOrFoundation(BuildingBlock block) {
return block.ShortPrefabName.Contains("floor") || block.ShortPrefabName.Contains("foundation");
}
private bool IsUsingWallpaperHammer(BasePlayer player) {
Item activeItem = player.GetActiveItem();
if (activeItem == null) return false;
return activeItem.info.shortname == "hammer" && activeItem.skin == hammerWallpaperSkin;
}
private void RotateWallpaper(BuildingBlock block) {
ulong currentWallpaperID = block.HasWallpaper(0) ? block.wallpaperID : block.wallpaperID2;
if (currentWallpaperID == 0) return;
int side = block.HasWallpaper(0) ? 0 : 1;
float currentRotation = (side == 0) ? block.wallpaperRotation : block.wallpaperRotation2;
float rotationIncrement = IsTriangle(block) ? 120f : 90f;
float newRotation = (currentRotation + rotationIncrement) % 360f;
block.SetWallpaper(currentWallpaperID, side, newRotation);
}
private IEnumerator WallpaperProgress(BasePlayer player, BuildingPrivlidge cup, string category) {
var set = cup.GetBuilding().buildingBlocks;
yield return CoroutineEx.waitForSeconds(0.15f);
var cd = Frequency(player.UserIDString, config.FrequencyWallpaper);
bool show = true;
List<ulong> playerTeamMembers = new List<ulong>();
if (config.teamupdate) {
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(player.userID);
if (playerTeam == null) {
playerTeamMembers.Add(player.userID);
}
else {
playerTeamMembers = playerTeam?.members?.ToList() ?? new List<ulong>();
}
}
var grade = BuildingCupboard[cup].grade;
for (var index = 0; index < set.Count; index++) {
var block = set[index];
if (cup == null) yield break;
if (!BuildingCupboard[cup].work) {
show = false;
break;
}
ulong wallpaperid = BuildingCupboard[cup].wallpaperid;
bool isCeiling = category == "Ceiling";
bool isFloor = category == "Floor";
ulong currentId = isCeiling ? block.wallpaperID2 : block.wallpaperID;
float currentHealth = isCeiling ? block.wallpaperHealth2 : block.wallpaperHealth;
if (currentId == wallpaperid && currentHealth != -1) continue;
if (!config.teamupdate || playerTeamMembers.Contains(block.OwnerID)) {
if (wallpaperid == block.wallpaperID && block.wallpaperHealth != -1) continue;
if (grade != block.grade && !BuildingCupboard[cup].wallpall) continue;
if (category == "Wall" && (!block.ShortPrefabName.Contains("wall") || block.ShortPrefabName.Contains("wall.frame"))) continue;
if (category == "Floor" && !(block.ShortPrefabName.Contains("floor") || block.ShortPrefabName.Contains("foundation"))) continue;
if (category == "Ceiling" && !(block.ShortPrefabName.Contains("floor") || block.ShortPrefabName.Contains("roof"))) continue;
if (Convert.ToUInt32(BuildingCupboard[cup].skinid) != block.skinID && !BuildingCupboard[cup].wallpall) continue;
WallpaperBlock(cup, block, player, category);
yield return CoroutineEx.waitForSeconds(cd);
}
}
BuildingCupboard[cup].work = false;
BuildingCupboard[cup].workwallpaper = null;
if (show) {
if (playerTeamMembers.Count == 1) {
CreateGameTip(cup, Lang("WallpaperFinishNoPlayer", player.UserIDString), player, fxfinish, 10);
}
else {
CreateGameTip(cup, Lang("WallpaperFinish", player.UserIDString), player, fxfinish, 10);
}
}
playerTeamMembers.Clear();
yield return 0;
}
private void WallpaperBlock(BuildingPrivlidge cup, BuildingBlock block, BasePlayer player, string category) {
if (!HasPermission(player.UserIDString, permwallpapernocost) && !CanWallpaper(player, cup)) {
BuildingCupboard[cup].work = false;
CreateGameTip(cup, Lang("NoResourcesWallpaper", player.UserIDString), player, fxnoresources, 10, "danger");
return;
}
if (CheckBlock(block)) return;
ulong wallpaperID = Convert.ToUInt32(BuildingCupboard[cup].wallpaperid);
const float wallpaperFixedRotation = 0f;
if (wallpaperID == 1) {
block.RemoveWallpaper(0);
block.RemoveWallpaper(1);
}
else {
if (!HasPermission(player.UserIDString, permupgradenocost)) {
TakeResources(cup.inventory.itemList, "cloth", config.wallresource);
}
if (category == "Wall") {
block.SetWallpaper(wallpaperID, 0, 0f);
if (config.bothsides && BuildingCupboard[cup].wpbothsides) block.SetWallpaper(wallpaperID, 1);
}
if (category == "Floor") {
if (IsFoundation(block)) {
block.SetWallpaper(wallpaperID, 0);
}
else {
block.SetWallpaper(wallpaperID, 1);
}
}
else if (category == "Ceiling") {
block.SetWallpaper(wallpaperID, 0);
}
}
if (!config.wallpaperdamage) {
if (block.wallpaperProtection == null) block.wallpaperProtection = ScriptableObject.CreateInstance<ProtectionProperties>();
if (block.wallpaperProtection.amounts.Length < 26) block.wallpaperProtection.amounts = new float[26];
for (int i = 0; i < block.wallpaperProtection.amounts.Length; i++) {
block.wallpaperProtection.amounts[i] = float.MaxValue;
}
}
if (config.playfx && BuildingCupboard[cup].effect) {
Effect.server.Run(fxcloth, block.transform.position);
}
}
private bool CanUpgrade(BasePlayer player, BuildingPrivlidge cup, BuildingBlock block, BuildingGrade.Enum grade) {
var list = block.blockDefinition.GetGrade(grade, 0).CostToBuild();
for (var index = 0; index < list.Count; index++) {
ItemAmount itemAmount = list[index];
if (cup.inventory.GetAmount(itemAmount.itemid, false) < (double) itemAmount.amount) return false;
}
return true;
}
private bool CanWallpaper(BasePlayer player, BuildingPrivlidge cup) {
if (cup.inventory.GetAmount(-858312878, false) < (double) config.wallresource) return false;
return true;
}
private bool Unlock(int maxGradeTier, string requiredGrade) {
if (maxGradeTier == 1 && requiredGrade == "wood") return true;
if (maxGradeTier == 2 && (requiredGrade == "wood" || requiredGrade == "stone")) return true;
if (maxGradeTier == 3 && (requiredGrade == "wood" || requiredGrade == "stone" || requiredGrade == "metal")) return true;
if (maxGradeTier == 4) return true;
return false;
}
private static void TakeResources(IEnumerable<Item> itemList, string name, int takeitems) {
if (takeitems == 0) return;
var list = Facepunch.Pool.Get<List<Item>>();
var num1 = 0;
foreach (var obj in itemList) {
if (obj.info.shortname != name) continue;
var num2 = takeitems - num1;
if (num2 <= 0) continue;
if (obj.amount > num2) {
obj.MarkDirty();
obj.amount -= num2;
break;
}
if (obj.amount <= num2) {
num1 += obj.amount;
list.Add(obj);
}
if (num1 == takeitems) break;
}
foreach (var obj in list) obj.Remove();
Facepunch.Pool.FreeUnmanaged(ref list);
}
private void TCSkinReplace(BuildingPrivlidge tc, BasePlayer player, TCSkin skin) {
string prefabPath = skin switch {
TCSkin.Retro => "assets/prefabs/deployable/tool cupboard/retro/cupboard.tool.retro.deployed.prefab", TCSkin.Shockbyte => "assets/prefabs/deployable/tool cupboard/shockbyte/cupboard.tool.shockbyte.deployed.prefab", _ => "assets/prefabs/deployable/tool cupboard/cupboard.tool.deployed.prefab"
}
;
BaseEntity tcskin = GameManager.server.CreateEntity(prefabPath, tc.transform.position, tc.transform.rotation, true) as BaseEntity;
tcskin.OwnerID = tc.OwnerID;
tcskin.skinID = 1337;
tcskin.Spawn();
NextTick(() => {
var Building = tcskin as BuildingPrivlidge;
if (Building == null) return;
foreach (var authorized in tc.authorizedPlayers) {
Building.authorizedPlayers.Add(new PlayerNameID {
userid = authorized.userid, username = authorized.username
}
);
}
Building.AttachToBuilding(tc.buildingID);
Building.BuildingDirty();
Building.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
UpdateBlockedItems(Building);
if (tc.inventory != null && Building.inventory != null) {
foreach (var item in tc.inventory.itemList.ToList()) {
var newItem = ItemManager.CreateByItemID(item.info.itemid, item.amount, item.skin);
if (newItem != null) {
newItem.condition = item.condition;
newItem.maxCondition = item.maxCondition;
newItem.MoveToContainer(Building.inventory);
}
}
}
CopyLock(tc, Building);
string effectPath = skin switch {
TCSkin.Retro => "assets/prefabs/deployable/tool cupboard/retro/effects/tool-cupboard-retro-deploy.prefab", TCSkin.Shockbyte => "assets/prefabs/deployable/tool cupboard/effects/tool-cupboard-deploy.prefab", _ => "assets/prefabs/deployable/tool cupboard/effects/tool-cupboard-deploy.prefab"
}
;
Effect.server.Run(effectPath, tcskin.transform.position);
tc.inventory.Clear();
tc.Kill();
}
);
}
private bool CheckTeam(ulong owner, ulong player) => RelationshipManager.ServerInstance.FindPlayersTeam(owner)?.members?.Contains(player) ?? false;
private bool CheckBlock(BuildingBlock block) => block.blockDefinition.checkVolumeOnUpgrade && DeployVolume.Check(block.transform.position, block.transform.rotation, PrefabAttribute.server.FindAll<DeployVolume>(block.prefabID), ~(1 << block.gameObject.layer));
private void CopyLock(BaseEntity fromEntity, BaseEntity toEntity) {
if (fromEntity == null || toEntity == null) return;
if (!fromEntity.HasSlot(BaseEntity.Slot.Lock) || !toEntity.HasSlot(BaseEntity.Slot.Lock)) return;
var originalLock = fromEntity.GetSlot(BaseEntity.Slot.Lock);
if (originalLock is CodeLock originalCodeLock) {
var codeLock = GameManager.server.CreateEntity(originalCodeLock.PrefabName) as CodeLock;
if (cod
// ... [Code preview truncated due to length. Full source in attached file] ...