C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Build Tools", "Puntofila.exe", "1.0.0")]
public class BuildTools : RustPlugin
{
#region Fields
[PluginReference] private Plugin ImageLibrary, NoEscape, Clans, Friends, Notify, UINotify, RaidZone;
private static BuildTools _instance;
private enum Types
{
None = -1,
Remove = 5,
Wood = 1,
Stone = 2,
Metal = 3,
TopTier = 4
}
private const string PermAll = "buildtools.all";
private const string PermFree = "buildtools.free";
#endregion
#region Config
private static Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Remove Commands")]
public string[] RemoveCommands = { "remove" };
[JsonProperty(PropertyName = "Upgrade Commands")]
public string[] UpgradeCommands = { "up", "building.upgrade" };
[JsonProperty(PropertyName = "Work with Notify?")]
public bool UseNotify = true;
[JsonProperty(PropertyName = "Setting Modes", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<Mode> Modes = new List<Mode>
{
new Mode { Type = Types.Remove, Permission = string.Empty },
new Mode { Type = Types.Wood, Permission = string.Empty },
new Mode { Type = Types.Stone, Permission = string.Empty },
new Mode { Type = Types.Metal, Permission = string.Empty },
new Mode { Type = Types.TopTier, Permission = string.Empty }
};
[JsonProperty(PropertyName = "Upgrade Settings")]
public UpgradeSettings Upgrade = new UpgradeSettings
{
ActionTime = 30,
Cooldown = 0,
VipCooldown = new Dictionary<string, int>
{
["buildtool.vip"] = 0,
["buildtool.premium"] = 0
},
AfterWipe = 0,
VipAfterWipe = new Dictionary<string, int>
{
["buildtool.vip"] = 0,
["buildtool.premium"] = 0
}
};
[JsonProperty(PropertyName = "Remove Settings")]
public RemoveSettings Remove = new RemoveSettings
{
ActionTime = 30,
Cooldown = 0,
VipCooldown = new Dictionary<string, int>
{
["buildtool.vip"] = 0,
["buildtool.premium"] = 0
},
AfterWipe = 0,
VipAfterWipe = new Dictionary<string, int>
{
["buildtool.vip"] = 0,
["buildtool.premium"] = 0
},
Condition = new ConditionSettings
{
Default = true,
Percent = false,
PercentValue = 0
},
ReturnItem = true,
ReturnPercent = 100,
BlockedList = new List<string>
{
"shortname 1",
"shortname 2",
"shortname 3"
}
};
[JsonProperty(PropertyName = "Block Settings")]
public BlockSettings Block = new BlockSettings
{
UseNoEscape = true,
UseClans = true,
UseFriends = true,
UseCupboard = true
};
}
private class ConditionSettings
{
[JsonProperty(PropertyName = "Default (from game)")]
public bool Default;
[JsonProperty(PropertyName = "Use percent?")]
public bool Percent;
[JsonProperty(PropertyName = "Percent (value)")]
public float PercentValue;
}
private class BlockSettings
{
[JsonProperty(PropertyName = "Work with NoEscape?")]
public bool UseNoEscape;
[JsonProperty(PropertyName = "Work with Clans? (clan members will be able to delete/upgrade)")]
public bool UseClans;
[JsonProperty(PropertyName = "Work with Friends? (friends will be able to delete/upgrade)")]
public bool UseFriends;
[JsonProperty(PropertyName = "Can those authorized in the cupboard delete/upgrade?")]
public bool UseCupboard;
[JsonProperty(PropertyName = "Is an upgrade/remove cupbaord required?")]
public bool NeedCupboard;
}
private abstract class TotalSettings
{
[JsonProperty(PropertyName = "Time of action")]
public int ActionTime;
[JsonProperty(PropertyName = "Cooldown (default | 0 - disable)")]
public int Cooldown;
[JsonProperty(PropertyName = "Cooldowns", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> VipCooldown;
[JsonProperty(PropertyName = "Block After Wipe (default | 0 - disable)")]
public int AfterWipe;
[JsonProperty(PropertyName = "Block After Wipe", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> VipAfterWipe;
public int GetCooldown(BasePlayer player)
{
int min = Cooldown;
foreach (var check in VipCooldown)
{
if (player.IPlayer.HasPermission(check.Key) && check.Value < min)
min = check.Value;
}
return min;
}
public int GetWipeCooldown(BasePlayer player)
{
int min = AfterWipe;
foreach (var check in VipAfterWipe)
{
if (player.IPlayer.HasPermission(check.Key) && check.Value < min)
min = check.Value;
}
return min;
}
}
private class UpgradeSettings : TotalSettings { }
private class RemoveSettings : TotalSettings
{
[JsonProperty(PropertyName = "Blocked items to remove (prefab)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> BlockedList;
[JsonProperty(PropertyName = "Return Item")]
public bool ReturnItem;
[JsonProperty(PropertyName = "Returnable Item Percentage")]
public float ReturnPercent;
[JsonProperty(PropertyName = "Can friends remove? (Friends)")]
public bool CanFriends;
[JsonProperty(PropertyName = "Can clanmates remove? (Clans)")]
public bool CanClan;
[JsonProperty(PropertyName = "Can teammates remove?")]
public bool CanTeams;
[JsonProperty(PropertyName = "Require a cupboard")]
public bool RequireCupboard;
[JsonProperty(PropertyName = "Remove by cupboard? (those who are authorized in the cupboard can remove)")]
public bool RemoveByCupboard;
[JsonProperty(PropertyName = "Condition Settings")]
public ConditionSettings Condition;
}
private class Mode
{
[JsonProperty(PropertyName = "Type (Remove/Wood/Stone/Metal/TopTier)")]
[JsonConverter(typeof(StringEnumConverter))]
public Types Type;
[JsonProperty(PropertyName = "Permission (ex: buildtools.1)")]
public string Permission;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
SaveConfig();
}
catch (Exception ex)
{
PrintError("Your configuration file contains an error. Using default configuration values.");
LoadDefaultConfig();
Debug.LogException(ex);
}
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
protected override void LoadDefaultConfig()
{
_config = new Configuration();
}
#endregion
#region Data
private PluginData _data;
private void SaveData()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
}
private void LoadData()
{
try
{
_data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(Name);
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (_data == null) _data = new PluginData();
}
private class PluginData
{
public Dictionary<ulong, PlayerData> Players = new Dictionary<ulong, PlayerData>();
}
private class PlayerData
{
public DateTime LastUpgrade = new DateTime(1970, 1, 1, 0, 0, 0);
public DateTime LastRemove = new DateTime(1970, 1, 1, 0, 0, 0);
public int LeftTime(bool remove, int cooldown)
{
DateTime time = remove ? LastRemove : LastUpgrade;
return (int)time.AddSeconds(cooldown).Subtract(DateTime.UtcNow).TotalSeconds;
}
public bool HasCooldown(bool remove, int cooldown)
{
DateTime time = remove ? LastRemove : LastUpgrade;
return DateTime.UtcNow.Subtract(time).TotalSeconds < cooldown;
}
public static bool HasWipeCooldown(int cooldown)
{
return DateTime.UtcNow.Subtract(SaveRestore.SaveCreatedTime.ToUniversalTime()).TotalSeconds < cooldown;
}
public static int WipeLeftTime(int cooldown)
{
return (int)SaveRestore.SaveCreatedTime.ToUniversalTime().AddSeconds(cooldown).Subtract(DateTime.UtcNow).TotalSeconds;
}
}
private PlayerData GetPlayerData(ulong userId)
{
PlayerData playerData;
if (!_data.Players.TryGetValue(userId, out playerData))
_data.Players.Add(userId, playerData = new PlayerData());
return playerData;
}
#endregion
#region Toast Notifications
private void ShowToast(BasePlayer player, string text, int type = 0)
{
if (player == null || !player.IsConnected) return;
player.Command("gametip.showtoast", type, text);
}
#endregion
#region Hooks
private void Init()
{
_instance = this;
LoadData();
RegisterPermissions();
AddCovalenceCommand(_config.UpgradeCommands, nameof(CmdUpgrade));
AddCovalenceCommand(_config.RemoveCommands, nameof(CmdRemove));
}
private void Unload()
{
BuildComponent[] builds = _components.Values.ToArray();
foreach (BuildComponent build in builds)
{
if (build != null)
build.Kill();
}
SaveData();
_config = null;
_instance = null;
}
private object OnHammerHit(BasePlayer player, HitInfo info)
{
if (player == null || info == null) return null;
BaseCombatEntity entity = info.HitEntity as BaseCombatEntity;
if (entity == null || entity.OwnerID == 0) return null;
BuildComponent build = GetBuild(player);
if (build == null) return null;
Mode mode = build.GetMode();
if (mode == null) return null;
if (!player.CanBuild())
{
SendNotify(player, BuildingBlocked, 1);
return true;
}
if (_config.Block.UseNoEscape && NoEscape != null && NoEscape.IsLoaded && IsRaidBlocked(player))
{
SendNotify(player, mode.Type == Types.Remove ? RemoveRaidBlocked : UpgradeRaidBlocked, 1);
return true;
}
BuildingPrivlidge cupboard = entity.GetBuildingPrivilege();
if (cupboard == null && _config.Block.NeedCupboard)
{
SendNotify(player, CupboardRequired, 1);
return true;
}
if (entity.OwnerID != player.userID)
{
bool any = (_config.Block.UseFriends && Friends != null && Friends.IsLoaded && IsFriends(player.OwnerID, entity.OwnerID)) ||
(_config.Block.UseClans && Clans != null && Clans.IsLoaded && IsClanMember(player.OwnerID, entity.OwnerID)) ||
(_config.Block.UseCupboard && (cupboard == null || cupboard.IsAuthed(player)));
if (!any)
{
SendNotify(player, mode.Type == Types.Remove ? CantRemove : CantUpgrade, 1);
return true;
}
}
if (mode.Type == Types.Remove)
{
if (_config.Remove.BlockedList.Contains(entity.name) || entity is MiniCopter || entity is BaseBoat)
{
SendNotify(player, CantRemove, 1);
return true;
}
}
else
{
BuildingBlock block = entity as BuildingBlock;
if (block != null && (int)block.grade >= (int)mode.Type) return true;
}
build.DoIt(entity);
return true;
}
private void OnEntityBuilt(Planner plan, GameObject go)
{
BasePlayer player = plan.GetOwnerPlayer();
if (player == null) return;
BuildingBlock block = go.ToBaseEntity() as BuildingBlock;
if (block == null) return;
BuildComponent build = GetBuild(player);
if (build == null) return;
Mode mode = build.GetMode();
if (mode == null || mode.Type == Types.Remove) return;
build.DoIt(block);
}
#endregion
#region Commands
[ConsoleCommand("repairall")]
private void CmdRepair(ConsoleSystem.Arg args)
{
BasePlayer player = args.Player();
if (player == null) return;
if (!player.IsAdmin) return;
BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
if (cupboard == null)
{
SendNotify(player, NoCupboard, 1);
return;
}
List<BuildingBlock> entities = BaseNetworkable.serverEntities.OfType<BuildingBlock>()
.Where(x => !(x is BasePlayer) && x.GetBuildingPrivilege() == cupboard).ToList();
List<AutoTurret> turrets = BaseNetworkable.serverEntities.OfType<AutoTurret>().Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
List<SamSite> samsites = BaseNetworkable.serverEntities.OfType<SamSite>().Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
if (entities.Count == 0) return;
foreach (BuildingBlock block in entities)
{
block.SetHealthToMax();
block.StartBeingRotatable();
block.SendNetworkUpdate();
}
foreach (AutoTurret turret in turrets)
{
turret.SetHealth(1000);
turret.SendNetworkUpdate();
}
foreach (SamSite samsite in samsites)
{
samsite.SetHealth(1000);
samsite.SendNetworkUpdate();
}
}
private void CmdRemove(IPlayer cov, string command, string[] args)
{
BasePlayer player = cov.Object as BasePlayer;
if (player == null) return;
Mode mode = _config.Modes.Find(x => x.Type == Types.Remove);
if (mode == null || (!string.IsNullOrEmpty(mode.Permission) && !cov.HasPermission(mode.Permission)))
{
SendNotify(player, NoPermission, 1);
return;
}
if (args.Length > 0 && args[0] == "all")
{
if (!cov.HasPermission(PermAll))
{
SendNotify(player, NoPermission, 1);
return;
}
BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
if (cupboard == null)
{
SendNotify(player, NoCupboard, 1);
return;
}
PlayerData data = GetPlayerData(player.userID);
int cooldown = _config.Remove.GetCooldown(player);
if (cooldown > 0 && data.HasCooldown(false, cooldown))
{
SendNotify(player, RemoveCanThrough, 1, data.LeftTime(false, cooldown));
return;
}
int blockWipe = _config.Remove.GetWipeCooldown(player);
if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
{
SendNotify(player, RemoveCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
return;
}
List<BaseCombatEntity> entities = BaseNetworkable.serverEntities.OfType<BaseCombatEntity>()
.Where(x => !(x is BasePlayer) && x.GetBuildingPrivilege() == cupboard).ToList();
if (entities.Count == 0 || entities.Any(x => !CanRemove(player, x))) return;
ServerMgr.Instance.StartCoroutine(StartRemove(player, entities));
SendNotify(player, SuccessfullyRemove, 0);
return;
}
AddOrGetBuild(player).Init(mode);
}
private void CmdUpgrade(IPlayer cov, string command, string[] args)
{
BasePlayer player = cov.Object as BasePlayer;
if (player == null) return;
if (args.Length == 0)
{
AddOrGetBuild(player).GoNext();
return;
}
switch (args[0])
{
case "all":
{
if (!cov.HasPermission(PermAll))
{
SendNotify(player, NoPermission, 1);
return;
}
Types upgradeType;
if (args.Length < 2 || ParseType(args[1], out upgradeType) == Types.None)
{
cov.Reply($"Error syntax! Use: /{command} {args[0]} [wood/stone/metal/toptier]");
return;
}
BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
if (cupboard == null)
{
SendNotify(player, NoCupboard, 1);
return;
}
if (!player.CanBuild())
{
SendNotify(player, BuildingBlocked, 1);
return;
}
if (_config.Block.UseNoEscape && NoEscape != null && NoEscape.IsLoaded && IsRaidBlocked(player))
{
SendNotify(player, UpgradeRaidBlocked, 1);
return;
}
PlayerData data = GetPlayerData(player.userID);
int cooldown = _config.Upgrade.GetCooldown(player);
if (cooldown > 0 && data.HasCooldown(false, cooldown))
{
SendNotify(player, UpgradeCanThrough, 1, data.LeftTime(false, cooldown));
return;
}
int blockWipe = _config.Upgrade.GetWipeCooldown(player);
if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
{
SendNotify(player, UpgradeCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
return;
}
BuildingGrade.Enum grade = GetEnum(upgradeType);
List<BuildingBlock> buildingBlocks = BaseNetworkable.serverEntities.OfType<BuildingBlock>()
.Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
if (buildingBlocks.Count == 0) return;
if (!cov.HasPermission(PermFree))
{
if (!CanAffordUpgrade(buildingBlocks, grade, player))
{
SendNotify(player, NotEnoughResources, 1);
return;
}
PayForUpgrade(buildingBlocks, grade, player);
}
ServerMgr.Instance.StartCoroutine(StartUpgrade(player, buildingBlocks, grade));
SendNotify(player, SuccessfullyUpgrade, 0);
break;
}
default:
{
Types type;
if (ParseType(args[0], out type) != Types.None)
{
List<Mode> modes = GetPlayerModes(player);
if (modes == null) return;
Mode mode = modes.Find(x => x.Type == type);
if (mode == null || (!string.IsNullOrEmpty(mode.Permission) && !cov.HasPermission(mode.Permission)))
{
SendNotify(player, NoPermission, 1);
return;
}
BuildComponent build = AddOrGetBuild(player);
build.Init(mode);
}
else
{
AddOrGetBuild(player).GoNext();
}
break;
}
}
}
[ConsoleCommand("UI_Builder")]
private void CmdConsoleBuilding(ConsoleSystem.Arg arg)
{
BasePlayer player = arg.Player();
if (player == null || !arg.HasArgs()) return;
switch (arg.Args[0])
{
case "mode":
{
int index;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out index)) return;
List<Mode> modes = GetPlayerModes(player);
if (modes == null || index >= modes.Count) return;
Mode mode = modes[index];
if (mode == null) return;
AddOrGetBuild(player)?.Init(mode);
break;
}
case "close":
{
GetBuild(player)?.Kill();
break;
}
}
}
#endregion
#region Component
private readonly Dictionary<BasePlayer, BuildComponent> _components = new Dictionary<BasePlayer, BuildComponent>();
private BuildComponent GetBuild(BasePlayer player)
{
BuildComponent build;
if (_components.TryGetValue(player, out build))
return build;
return null;
}
private BuildComponent AddOrGetBuild(BasePlayer player)
{
BuildComponent build;
if (_components.TryGetValue(player, out build))
return build;
build = player.gameObject.AddComponent<BuildComponent>();
return build;
}
private class BuildComponent : FacepunchBehaviour
{
private BasePlayer _player;
private Mode _mode;
private float _startTime;
private bool _started = true;
private float _cooldown;
private void Awake()
{
_player = GetComponent<BasePlayer>();
_instance._components[_player] = this;
enabled = false;
}
public void Init(Mode mode)
{
if (mode == null)
mode = GetPlayerModes(_player).FirstOrDefault();
_mode = mode;
_startTime = Time.time;
_cooldown = _mode.Type == Types.Remove ? _config.Remove.ActionTime : _config.Upgrade.ActionTime;
enabled = true;
_started = true;
}
private void FixedUpdate()
{
if (!_started) return;
float timeLeft = Time.time - _startTime;
if (timeLeft > _cooldown)
{
Kill();
return;
}
int remaining = Mathf.RoundToInt(_startTime + _cooldown - Time.time);
TimeSpan t = TimeSpan.FromSeconds(remaining);
string action;
if (_mode.Type == Types.Remove)
action = "УДАЛЕНИЕ";
else
action = _instance.Msg(_instance.Msg(_player, $"{_mode.Type}"));
string text = string.Format("{1} сек - {2}", t.Minutes, t.Seconds, action);
_instance.ShowToast(_player, text, 0);
}
public void DoIt(BaseCombatEntity entity)
{
if (entity == null) return;
switch (_mode.Type)
{
case Types.Remove:
{
if (!CanRemove(_player, entity)) return;
PlayerData data = _instance.GetPlayerData(_player.userID);
int cooldown = _config.Remove.GetCooldown(_player);
if (cooldown > 0 && data.HasCooldown(true, cooldown))
{
_instance.SendNotify(_player, RemoveCanThrough, 1, data.LeftTime(true, cooldown));
return;
}
int blockWipe = _config.Remove.GetWipeCooldown(_player);
if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
{
_instance.SendNotify(_player, RemoveCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
return;
}
RemoveEntity(_player, entity);
data.LastRemove = DateTime.UtcNow;
break;
}
default:
{
BuildingBlock block = entity as BuildingBlock;
if (block == null) return;
PlayerData data = _instance.GetPlayerData(_player.userID);
int cooldown = _config.Upgrade.GetCooldown(_player);
if (cooldown > 0 && data.HasCooldown(false, cooldown))
{
_instance.SendNotify(_player, UpgradeCanThrough, 1, data.LeftTime(false, cooldown));
return;
}
int blockWipe = _config.Upgrade.GetWipeCooldown(_player);
if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
{
_instance.SendNotify(_player, UpgradeCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
return;
}
BuildingGrade.Enum enumGrade = GetEnum(_mode.Type);
ConstructionGrade grade = block.blockDefinition.GetGrade(enumGrade, 0);
if (grade == null || !block.CanChangeToGrade(enumGrade, 0, _player) ||
Interface.CallHook("OnStructureUpgrade", block, _player, enumGrade) != null ||
block.SecondsSinceAttacked < 30.0)
return;
if (!_player.IPlayer.HasPermission(PermFree))
{
if (!block.CanAffordUpgrade(enumGrade, 0, _player))
{
_instance.SendNotify(_player, NotEnoughResources, 0);
return;
}
block.PayForUpgrade(grade, _player);
}
UpgradeBuildingBlock(block, enumGrade);
Effect.server.Run("assets/bundled/prefabs/fx/build/promote_" + enumGrade.ToString().ToLower() + ".prefab", block, 0U, Vector3.zero, Vector3.zero);
data.LastUpgrade = DateTime.UtcNow;
break;
}
}
_startTime = Time.time;
}
public void GoNext()
{
List<Mode> modes = GetPlayerModes(_player);
if (modes == null) return;
if (_mode == null)
{
_mode = modes.FindAll(x => x.Type != Types.Remove).FirstOrDefault();
Init(_mode);
return;
}
int i = 0;
for (; i < modes.Count; i++)
{
if (modes[i] == _mode)
break;
}
i++;
_mode = modes.Count <= i ? modes[0] : modes[i];
Init(_mode);
}
public Mode GetMode() => _mode;
private void OnDestroy()
{
CancelInvoke();
if (_instance != null)
_instance._components.Remove(_player);
Destroy(this);
}
public void Kill()
{
enabled = false;
_started = false;
DestroyImmediate(this);
}
}
#endregion
#region Utils
private void RegisterPermissions()
{
permission.RegisterPermission(PermAll, this);
permission.RegisterPermission(PermFree, this);
foreach (Mode mode in _config.Modes)
{
if (!string.IsNullOrEmpty(mode.Permission) && !permission.PermissionExists(mode.Permission))
permission.RegisterPermission(mode.Permission, this);
}
}
private static string FixNames(string name)
{
switch (name)
{
case "wall.external.high.wood": return "wall.external.high";
case "electric.windmill.small": return "generator.wind.scrap";
case "graveyardfence": return "wall.graveyard.fence";
case "coffinstorage": return "coffin.storage";
}
return name;
}
private static List<Mode> GetPlayerModes(BasePlayer player)
{
List<Mode> result = new List<Mode>();
foreach (Mode mode in _config.Modes)
{
if (string.IsNullOrEmpty(mode.Permission) || player.IPlayer.HasPermission(mode.Permission))
result.Add(mode);
}
return result;
}
private bool IsRaidBlocked(BasePlayer player)
{
if (RaidZone == null) return false;
object result = RaidZone.Call("IsBlock", player);
return result is bool && (bool)result;
}
private bool IsClanMember(ulong playerID, ulong targetID)
{
if (Clans == null) return false;
object result = Clans.Call("HasFriend", playerID, targetID);
return result is bool && (bool)result;
}
private bool IsFriends(ulong playerID, ulong friendId)
{
if (Friends == null) return false;
object result = Friends.Call("AreFriends", playerID, friendId);
return result is bool && (bool)result;
}
private static bool IsTeammates(ulong player, ulong friend)
{
RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance.FindPlayersTeam(player);
return team != null && team.members.Contains(friend);
}
private static BuildingGrade.Enum GetEnum(Types type)
{
switch (type)
{
case Types.Wood: return BuildingGrade.Enum.Wood;
case Types.Stone: return BuildingGrade.Enum.Stone;
case Types.Metal: return BuildingGrade.Enum.Metal;
case Types.TopTier: return BuildingGrade.Enum.TopTier;
default: return BuildingGrade.Enum.None;
}
}
private static void RemoveEntity(BasePlayer player, BaseCombatEntity entity)
{
if (_config.Remove.ReturnItem)
GiveRefund(entity, player);
entity.Die();
}
private static bool CanRemove(BasePlayer player, BaseEntity entity)
{
if (entity.OwnerID == 0)
{
_instance.SendNotify(player, CantRemove, 1);
return false;
}
StorageContainer storageContainer = entity.GetComponent<StorageContainer>();
if (storageContainer != null && storageContainer.inventory.itemList.Count > 0)
{
_instance.SendNotify(player, CRStorageNotEmpty, 1);
return false;
}
BaseCombatEntity combat = entity.GetComponent<BaseCombatEntity>();
if (combat != null && combat.SecondsSinceAttacked < 30f)
{
_instance.SendNotify(player, CRDamaged, 1);
return false;
}
if (Interface.Call("CanRemove", player, entity) != null)
{
_instance.SendNotify(player, CRBeBlocked, 1);
return false;
}
if (_config.Block.NeedCupboard && entity.GetBuildingPrivilege() == null)
{
_instance.SendNotify(player, CRBuildingBlock, 1);
return false;
}
if (_config.Block.UseNoEscape && _instance.NoEscape != null && _instance.NoEscape.IsLoaded && _instance.IsRaidBlocked(player))
{
_instance.SendNotify(player, RemoveRaidBlocked, 1);
return false;
}
if (player.userID != entity.OwnerID)
{
if (_config.Remove.RemoveByCupboard) return true;
if (_config.Remove.CanClan && _instance.IsClanMember(player.userID, entity.OwnerID)) return true;
if (_config.Remove.CanFriends && _instance.IsFriends(player.userID, entity.OwnerID)) return true;
if (_config.Remove.CanTeams && IsTeammates(player.userID, entity.OwnerID)) return true;
_instance.SendNotify(player, CRNotAccess, 1);
return false;
}
return true;
}
private static void GiveRefund(BaseCombatEntity entity, BasePlayer player)
{
string shortPrefabName = Regex.Replace(entity.ShortPrefabName, "\\.deployed|_deployed", "");
shortPrefabName = FixNames(shortPrefabName);
Item item = ItemManager.CreateByName(shortPrefabName);
if (item != null)
{
HandleCondition(ref item, player, entity);
player.inventory.GiveItem(item);
return;
}
List<ItemAmount> buildCost = entity.BuildCost();
if (buildCost == null) return;
foreach (ItemAmount value in buildCost)
{
int amount = _config.Remove.ReturnPercent < 100
? Convert.ToInt32(value.amount * (_config.Remove.ReturnPercent / 100f))
: Convert.ToInt32(value.amount);
Item x = ItemManager.Create(value.itemDef, amount);
if (x == null) continue;
HandleCondition(ref x, player, entity);
player.GiveItem(x);
}
}
private static void HandleCondition(ref Item item, BasePlayer player, BaseCombatEntity entity)
{
if (_config.Remove.Condition.Default && entity.pickup.setConditionFromHealth && item.hasCondition)
item.conditionNormalized = Mathf.Clamp01(entity.healthFraction - entity.pickup.subtractCondition);
if (_config.Remove.Condition.Percent)
item.LoseCondition(item.maxCondition * (_config.Remove.Condition.PercentValue / 100f));
}
private static void UpgradeBuildingBlock(BuildingBlock block, BuildingGrade.Enum @enum)
{
if (block == null || block.IsDestroyed) return;
block.SetGrade(@enum);
block.SetHealthToMax();
block.StartBeingRotatable();
block.SendNetworkUpdate();
block.UpdateSkin();
block.ResetUpkeepTime();
block.UpdateSurroundingEntities();
BuildingManager.server.GetBuilding(block.buildingID)?.Dirty();
}
private bool CanAffordUpgrade(List<BuildingBlock> blocks, BuildingGrade.Enum @enum, BasePlayer player)
{
foreach (BuildingBlock block in blocks)
{
ConstructionGrade grade = block.blockDefinition.GetGrade(@enum, 0);
if (grade == null) continue;
foreach (ItemAmount itemAmount in grade.costToBuild)
{
if (player.inventory.GetAmount(itemAmount.itemid) < itemAmount.amount)
return false;
}
}
return true;
}
private static void PayForUpgrade(List<BuildingBlock> blocks, BuildingGrade.Enum @enum, BasePlayer player)
{
List<Item> collect = new List<Item>();
foreach (BuildingBlock block in blocks)
{
ConstructionGrade grade = block.blockDefinition.GetGrade(@enum, 0);
if (grade == null) continue;
foreach (ItemAmount itemAmount in grade.costToBuild)
{
player.inventory.Take(collect, itemAmount.itemid, (int)itemAmount.amount);
player.Command("note.inv " + itemAmount.itemid + " " + (float)((int)itemAmount.amount * -1.0));
}
}
foreach (Item obj in collect)
obj.Remove();
}
private IEnumerator StartUpgrade(BasePlayer player, List<BuildingBlock> blocks, BuildingGrade.Enum @enum)
{
for (int i = 0; i < blocks.Count; i++)
{
BuildingBlock block = blocks[i];
if (block == null || block.IsDestroyed) continue;
UpgradeBuildingBlock(block, @enum);
if (i % 10 == 0) yield return CoroutineEx.waitForFixedUpdate;
}
}
private IEnumerator StartRemove(BasePlayer player, List<BaseCombatEntity> entities)
{
for (int i = 0; i < entities.Count; i++)
{
BaseCombatEntity entity = entities[i];
if (entity == null || entity.IsDestroyed) continue;
RemoveEntity(player, entity);
if (i % 10 == 0) yield return CoroutineEx.waitForFixedUpdate;
}
}
private static Types ParseType(string arg, out Types type)
{
Types upgradeType;
if (Enum.TryParse(arg, true, out upgradeType))
{
type = upgradeType;
return type;
}
int value;
if (int.TryParse(arg, out value) && value > 0 && value < 6)
{
type = (Types)value;
return type;
}
type = Types.None;
return type;
}
#endregion
#region Lang
private const string
CRNotAccess = "CRNotAccess",
CRBuildingBlock = "CRBuildingBlock",
CRBeBlocked = "CRBeBlocked",
CRStorageNotEmpty = "CRStorageNotEmpty",
CRDamaged = "CRDamaged",
SuccessfullyRemove = "SuccessfullyRemove",
UpgradeTitle = "UpgradeTitle",
RemoveTitle = "RemoveTitle",
UpgradeCanThrough = "UpgradeCanThrough",
RemoveCanThrough = "RemoveCanThrough",
NoPermission = "NoPermission",
SuccessfullyUpgrade = "SuccessfullyUpgrade",
NoCupboard = "NoCupboard",
CupboardRequired = "CupboardRequired",
RemoveRaidBlocked = "RemoveRaidBlocked",
UpgradeRaidBlocked = "UpgradeRaidBlocked",
BuildingBlocked = "BuildingBlocked",
CantUpgrade = "CantUpgrade",
CantRemove = "CantRemove",
NotEnoughResources = "NotEnoughResources",
UpgradeTo = "UpgradeTo";
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
[NotEnoughResources] = "Not enough resources to upgrade!",
[CantRemove] = "You can remove this entity.",
[CantUpgrade] = "You cannot upgrade this entity.",
[BuildingBlocked] = "You are building blocked",
[UpgradeRaidBlocked] = "You cannot upgrade buildings <color=#81B67A>during a raid!</color>!",
[RemoveRaidBlocked] = "You cannot upgrade or remove <color=#81B67A>during a raid!</color>!",
[CupboardRequired] = "A Cupboard is required!",
[NoCupboard] = "No cupboard found!",
[SuccessfullyUpgrade] = "You have successfully upgraded a building",
[NoPermission] = "You do not have permission to use this mode!",
[UpgradeCanThrough] = "You can upgrade the building in: {0}s",
[RemoveCanThrough] = "You can remove the building in: {0}s",
[RemoveTitle] = "Remove",
[UpgradeTitle] = "Upgrade to {0}",
[SuccessfullyRemove] = "You have successfully removed a building",
[CRDamaged] = "Can't remove: Server has disabled damaged objects from being removed.",
[CRStorageNotEmpty] = "Can't remove: The entity storage is not empty.",
[CRBeBlocked] = "Can't remove: An external plugin blocked the usage.",
[CRBuildingBlock] = "Can't remove: Missing cupboard",
[CRNotAccess] = "Can't remove: You don't have any rights to remove this.",
[UpgradeTo] = "Upgrade to {0}",
["Wood"] = "wood",
["Stone"] = "stone",
["Metal"] = "metal",
["TopTier"] = "HQM"
}, this);
}
private string Msg(string key, string userid = null, params object[] obj)
{
return string.Format(lang.GetMessage(key, this, userid), obj);
}
private string Msg(BasePlayer player, string key, params object[] obj)
{
return string.Format(lang.GetMessage(key, this, player.UserIDString), obj);
}
private void Reply(BasePlayer player, string key, params object[] obj)
{
player.ChatMessage(Msg(player, key, obj));
}
private void SendNotify(BasePlayer player, string key, int type, params object[] obj)
{
if (_config.UseNotify && (Notify != null || UINotify != null))
Interface.Oxide.CallHook("SendNotify", player, type, Msg(player, key, obj));
else
Reply(player, key, obj);
}
#endregion
}
}