Still requiring wood and fuel on regular building items
Mentioned this on last update but nothing was changed, mentioning it again.

that is true

Is anything going to be done with this? 

This is utilizing the boat's construction
We need a update for this plz

Can we please get an update on this? 

Merged post

Here is a fix. I had someone fix it, everyone should thank RickySpanish for the fix, becuase the OG wouldn't fix.

Make sure to delete you old config first and remove the plugin, then add this. works like a charm.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
using VLB;
using Random = UnityEngine.Random;

namespace Oxide.Plugins
{
[Info("Remover Tool", "Reneb/Fuji/Arainrr/Tryhard", "4.3.46", ResourceId = 651)]
[Description("Building and entity removal tool")]
public class RemoverTool : RustPlugin
{
#region Fields

[PluginReference]
private readonly Plugin Friends, ServerRewards, Clans, Economics, ImageLibrary, BuildingOwners, RustTranslationAPI, NoEscape;

private const string ECONOMICS_KEY = "economics";
private const string SERVER_REWARDS_KEY = "serverrewards";

private const string PERMISSION_ALL = "removertool.all";
private const string PERMISSION_ADMIN = "removertool.admin";
private const string PERMISSION_NORMAL = "removertool.normal";
private const string PERMISSION_TARGET = "removertool.target";
private const string PERMISSION_EXTERNAL = "removertool.external";
private const string PERMISSION_OVERRIDE = "removertool.override";
private const string PERMISSION_STRUCTURE = "removertool.structure";

private const string PREFAB_ITEM_DROP = "assets/prefabs/misc/item drop/item_drop.prefab";

private const int LAYER_ALL = 1 << 0 | 1 << 8 | 1 << 21;
private const int LAYER_TARGET = ~(1 << 2 | 1 << 3 | 1 << 4 | 1 << 10 | 1 << 18 | 1 << 28 | 1 << 29);

private static RemoverTool _instance;
private static BUTTON _removeButton;
private static RemoveMode _removeMode;

private readonly object _false = false;
private bool _configChanged;
private bool _removeOverride;
private Coroutine _removeAllCoroutine;
private Coroutine _removeStructureCoroutine;
private Coroutine _removeExternalCoroutine;
private Coroutine _removePlayerEntityCoroutine;

private StringBuilder _debugStringBuilder;
private Hash<ulong, float> _entitySpawnedTimes;
private readonly Hash<ulong, float> _cooldownTimes = new Hash<ulong, float>();

private enum RemoveMode
{
None,
NoHeld,
MeleeHit,
SpecificTool
}

private enum RemoveType
{
None,
All,
Admin,
Normal,
External,
Structure
}

private enum PlayerEntityRemoveType
{
All,
Cupboard,
Building
}

#endregion Fields

#region Oxide Hooks

private void Init()
{
_instance = this;
permission.RegisterPermission(PERMISSION_ALL, this);
permission.RegisterPermission(PERMISSION_ADMIN, this);
permission.RegisterPermission(PERMISSION_NORMAL, this);
permission.RegisterPermission(PERMISSION_TARGET, this);
permission.RegisterPermission(PERMISSION_OVERRIDE, this);
permission.RegisterPermission(PERMISSION_EXTERNAL, this);
permission.RegisterPermission(PERMISSION_STRUCTURE, this);

Unsubscribe(nameof(OnHammerHit));
Unsubscribe(nameof(OnEntitySpawned));
Unsubscribe(nameof(OnEntityKill));
Unsubscribe(nameof(OnPlayerAttack));
Unsubscribe(nameof(OnActiveItemChanged));
Unsubscribe(nameof(OnRaidBlock));
Unsubscribe(nameof(OnCombatBlock));

foreach (var perm in _configData.permission.Keys)
{
if (!permission.PermissionExists(perm, this))
{
permission.RegisterPermission(perm, this);
}
}
cmd.AddChatCommand(_configData.chat.command, this, nameof(CmdRemove));
}

private void OnServerInitialized()
{
Initialize();
UpdateConfig();
LoadConfig();
_removeMode = RemoveMode.None;
if (_configData.removerMode.noHeldMode)
{
_removeMode = RemoveMode.NoHeld;
}
if (_configData.removerMode.meleeHitMode)
{
_removeMode = RemoveMode.MeleeHit;
}
if (_configData.removerMode.specificToolMode)
{
_removeMode = RemoveMode.SpecificTool;
}
if (_removeMode == RemoveMode.MeleeHit)
{
BaseMelee baseMelee;
ItemDefinition itemDefinition;
if (string.IsNullOrEmpty(_configData.removerMode.meleeHitItemShortname) ||
(itemDefinition = ItemManager.FindItemDefinition(_configData.removerMode.meleeHitItemShortname)) == null ||
(baseMelee = itemDefinition.GetComponent<ItemModEntity>()?.entityPrefab.Get()?.GetComponent<BaseMelee>()) == null)
{
PrintError($"{_configData.removerMode.meleeHitItemShortname} is not an item shortname for a melee tool");
_removeMode = RemoveMode.None;
}
else
{
Subscribe(baseMelee is Hammer ? nameof(OnHammerHit) : nameof(OnPlayerAttack));
}
}

if (_configData.noEscape.useRaidBlocker)
{
Subscribe(nameof(OnRaidBlock));
}
if (_configData.noEscape.useCombatBlocker)
{
Subscribe(nameof(OnCombatBlock));
}

if (_configData.global.entityTimeLimit)
{
_entitySpawnedTimes = new Hash<ulong, float>();
Subscribe(nameof(OnEntitySpawned));
Subscribe(nameof(OnEntityKill));
}
if (_configData.global.logToFile)
{
_debugStringBuilder = new StringBuilder();
}

if (_removeMode == RemoveMode.MeleeHit && _configData.removerMode.meleeHitEnableInHand ||
_removeMode == RemoveMode.SpecificTool && _configData.removerMode.specificToolEnableInHand)
{
Subscribe(nameof(OnActiveItemChanged));
}

if (!Enum.TryParse(_configData.global.removeButton, true, out _removeButton) || !Enum.IsDefined(typeof(BUTTON), _removeButton))
{
PrintError($"{_configData.global.removeButton} is an invalid button. The remove button has been changed to 'FIRE_PRIMARY'.");
_removeButton = BUTTON.FIRE_PRIMARY;
_configData.global.removeButton = _removeButton.ToString();
SaveConfig();
}
if (ImageLibrary != null)
{
foreach (var image in _configData.imageUrls)
{
AddImageToLibrary(image.Value, image.Key);
}
if (_configData.ui.showCrosshair)
{
AddImageToLibrary(_configData.ui.crosshairImageUrl, UINAME_CROSSHAIR);
}
}
}

private void Unload()
{
// if (_configChanged)
// {
// SaveConfig();
// }
SaveDebug();
if (_removeAllCoroutine != null)
{
ServerMgr.Instance.StopCoroutine(_removeAllCoroutine);
}
if (_removeStructureCoroutine != null)
{
ServerMgr.Instance.StopCoroutine(_removeStructureCoroutine);
}
if (_removeExternalCoroutine != null)
{
ServerMgr.Instance.StopCoroutine(_removeExternalCoroutine);
}
if (_removePlayerEntityCoroutine != null)
{
ServerMgr.Instance.StopCoroutine(_removePlayerEntityCoroutine);
}
foreach (var player in BasePlayer.activePlayerList)
{
player.GetComponent<ToolRemover>()?.DisableTool();
}
_configData = null;
_instance = null;
}

private void OnServerSave()
{
if (_configChanged)
{
_configChanged = false;
timer.Once(Random.Range(0f, 60f), SaveConfig);
}
if (_configData.global.logToFile)
{
timer.Once(Random.Range(0f, 60f), SaveDebug);
}
if (_configData.global.entityTimeLimit && _entitySpawnedTimes != null)
{
var currentTime = Time.realtimeSinceStartup;
foreach (var entry in _entitySpawnedTimes.ToArray())
{
if (currentTime - entry.Value > _configData.global.limitTime)
{
_entitySpawnedTimes.Remove(entry.Key);
}
}
}
}

private void OnEntitySpawned(BaseEntity entity)
{
if (entity == null || entity.net == null)
{
return;
}
// if (!CanEntityBeSaved(entity)) return;
_entitySpawnedTimes[entity.net.ID.Value] = Time.realtimeSinceStartup;
}

private void OnEntityKill(BaseEntity entity)
{
if (entity == null || entity.net == null)
{
return;
}
_entitySpawnedTimes.Remove(entity.net.ID.Value);
}

private object OnPlayerAttack(BasePlayer player, HitInfo info)
{
return OnHammerHit(player, info);
}

private object OnHammerHit(BasePlayer player, HitInfo info)
{
if (player == null || info.HitEntity == null)
{
return null;
}
var toolRemover = player.GetComponent<ToolRemover>();
if (toolRemover == null)
{
return null;
}
if (!IsMeleeTool(player))
{
return null;
}
toolRemover.HitEntity = info.HitEntity;
return _false;
}

private void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem)
{
if (newItem == null)
{
return;
}
if (player == null || !player.userID.IsSteamId())
{
return;
}
if (IsToolRemover(player))
{
return;
}
if (_removeMode == RemoveMode.MeleeHit && IsMeleeTool(newItem))
{
ToggleRemove(player, RemoveType.Normal);
return;
}
if (_removeMode == RemoveMode.SpecificTool && IsSpecificTool(newItem))
{
ToggleRemove(player, RemoveType.Normal);
}
}

#endregion Oxide Hooks

#region Initializing

private readonly HashSet<Construction> _constructions = new HashSet<Construction>();
private readonly Dictionary<string, int> _itemShortNameToItemId = new Dictionary<string, int>();
private readonly Dictionary<string, string> _prefabNameToStructure = new Dictionary<string, string>();
private readonly Dictionary<string, string> _shortPrefabNameToDeployable = new Dictionary<string, string>();

private void Initialize()
{
foreach (var itemDefinition in ItemManager.GetItemDefinitions())
{
if (!_itemShortNameToItemId.ContainsKey(itemDefinition.shortname))
{
_itemShortNameToItemId.Add(itemDefinition.shortname, itemDefinition.itemid);
}
var deployablePrefab = itemDefinition.GetComponent<ItemModDeployable>()?.entityPrefab?.resourcePath;
if (string.IsNullOrEmpty(deployablePrefab))
{
continue;
}
var shortPrefabName = Utility.GetFileNameWithoutExtension(deployablePrefab);
if (!string.IsNullOrEmpty(shortPrefabName) && !_shortPrefabNameToDeployable.ContainsKey(shortPrefabName))
{
_shortPrefabNameToDeployable.Add(shortPrefabName, itemDefinition.shortname);
}
}
foreach (var entry in PrefabAttribute.server.prefabs)
{
var construction = entry.Value.Find<Construction>().FirstOrDefault();
if (construction != null && construction.deployable == null && !string.IsNullOrEmpty(construction.info.name.english))
{
_constructions.Add(construction);
if (!_prefabNameToStructure.ContainsKey(construction.fullName))
{
_prefabNameToStructure.Add(construction.fullName, GetBuildingBlockName(construction));
}
}
}
}

private static string GetBuildingBlockName(Construction construction)
{
if (construction.fullName.Contains("building boat"))
return "Boat " + construction.info.name.english;
return construction.info.name.english;
}

#endregion Initializing

#region Methods

private static string GetRemoveTypeName(RemoveType removeType)
{
return _configData.removeType[removeType].displayName;
}

private static void DropItemContainer(ItemContainer itemContainer, Vector3 position, Quaternion rotation)
{
itemContainer?.Drop(PREFAB_ITEM_DROP, position, rotation, 0);
}

private static bool IsExternalWall(StabilityEntity stabilityEntity)
{
return stabilityEntity.ShortPrefabName.Contains("external");
}

private static bool CanEntityBeDisplayed(BaseEntity entity, BasePlayer player)
{
var stash = entity as StashContainer;
return stash == null || !stash.IsHidden() || stash.PlayerInRange(player);
}

private static bool CanEntityBeSaved(BaseEntity entity)
{
if (entity is BuildingBlock)
{
return true;
}
EntitySettings entitySettings;
if (_configData.remove.entity.TryGetValue(entity.ShortPrefabName, out entitySettings) && entitySettings.enabled)
{
return true;
}
return false;
}

private static bool HasEntityEnabled(BaseEntity entity)
{
var buildingBlock = entity as BuildingBlock;
if (buildingBlock != null)
{
bool valid;
if (_configData.remove.validConstruction.TryGetValue(buildingBlock.grade, out valid) && valid)
{
return true;
}
}
EntitySettings entitySettings;
if (_configData.remove.entity.TryGetValue(entity.ShortPrefabName, out entitySettings) && entitySettings.enabled)
{
return true;
}
return false;
}

private static bool IsRemovableEntity(BaseEntity entity)
{
if (_instance._shortPrefabNameToDeployable.ContainsKey(entity.ShortPrefabName)
|| _instance._prefabNameToStructure.ContainsKey(entity.PrefabName)
|| _configData.remove.entity.ContainsKey(entity.ShortPrefabName))
{
var baseCombatEntity = entity as BaseCombatEntity;
if (baseCombatEntity != null)
{
if (baseCombatEntity.IsDead())
{
return false;
}
if (baseCombatEntity.pickup.itemTarget != null)
{
return true;
}
}
return true;
}
return false;
}

private static string GetEntityImage(string name)
{
if (_instance.ImageLibrary == null)
{
return null;
}
if (_configData.imageUrls.ContainsKey(name))
{
return GetImageFromLibrary(name);
}
if (_instance._itemShortNameToItemId.ContainsKey(name))
{
return GetImageFromLibrary(name);
}
return null;
}

private static string GetItemImage(string shortname)
{
if (_instance.ImageLibrary == null)
{
return null;
}
switch (shortname.ToLower())
{
case ECONOMICS_KEY:
return GetImageFromLibrary(ECONOMICS_KEY);

case SERVER_REWARDS_KEY:
return GetImageFromLibrary(SERVER_REWARDS_KEY);
}
return GetEntityImage(shortname);
}

private static void TryFindEntityName(BasePlayer player, BaseEntity entity, out string displayName, out string imageName)
{
var target = entity as BasePlayer;
if (target != null)
{
imageName = target.userID.IsSteamId() ? target.UserIDString : target.ShortPrefabName;
displayName = $"{target.displayName} ({target.ShortPrefabName})";
return;
}
EntitySettings entitySettings;
if (_configData.remove.entity.TryGetValue(entity.ShortPrefabName, out entitySettings))
{
imageName = entity.ShortPrefabName;
displayName = _instance.GetDeployableDisplayName(player, entity.ShortPrefabName, entitySettings.displayName);
return;
}

string structureName;
if (_instance._prefabNameToStructure.TryGetValue(entity.PrefabName, out structureName))
{
BuildingBlocksSettings buildingBlockSettings;
if (_configData.remove.buildingBlock.TryGetValue(structureName, out buildingBlockSettings))
{
imageName = structureName;
displayName = _instance.GetConstructionDisplayName(player, entity.PrefabName, buildingBlockSettings.displayName);
return;
}
}

imageName = entity.ShortPrefabName;
displayName = entity.ShortPrefabName;
}

private static string GetDisplayNameByCurrencyName(string language, string currencyName, long skinId)
{
var itemDefinition = ItemManager.FindItemDefinition(currencyName);
if (itemDefinition != null)
{
var translationKey = $"{itemDefinition.shortname}_{skinId}";
var translationValue = GetCurrencyDisplayName(translationKey, itemDefinition.displayName.english, true);
if (skinId <= 0 || string.IsNullOrEmpty(translationValue))
{
var displayName = _instance.GetItemDisplayName(language, itemDefinition.shortname);
if (!string.IsNullOrEmpty(displayName))
{
return displayName;
}
return itemDefinition.displayName.english;
}
return GetCurrencyDisplayName(translationKey, itemDefinition.displayName.english);
}
return GetCurrencyDisplayName(currencyName, currencyName);
}

private static string GetCurrencyDisplayName(string currencyName, string defaultName = null, bool readOnly = false)
{
string displayName;
if (_configData.remove.displayNames.TryGetValue(currencyName, out displayName))
{
return displayName;
}
if (!readOnly)
{
_configData.remove.displayNames.Add(currencyName, defaultName);
_instance._configChanged = true;
}
return defaultName;
}

private static PermissionSettings GetPermissionSettings(BasePlayer player)
{
var priority = 0;
PermissionSettings permissionSettings = null;
foreach (var entry in _configData.permission)
{
if (entry.Value.priority >= priority && _instance.permission.UserHasPermission(player.UserIDString, entry.Key))
{
priority = entry.Value.priority;
permissionSettings = entry.Value;
}
}
return permissionSettings ?? new PermissionSettings();
}

private static Vector2 GetAnchor(string anchor)
{
var array = anchor.Split(' ');
return new Vector2(float.Parse(array[0]), float.Parse(array[1]));
}

private static bool AddImageToLibrary(string url, string shortname, ulong skin = 0)
{
return (bool)_instance.ImageLibrary.Call("AddImage", url, shortname.ToLower(), skin);
}

private static string GetImageFromLibrary(string shortname, ulong skin = 0, bool returnUrl = false)
{
return string.IsNullOrEmpty(shortname) ? null : (string)_instance.ImageLibrary.Call("GetImage", shortname.ToLower(), skin, returnUrl);
}

#endregion Methods

#region NoEscape

private void OnRaidBlock(BasePlayer player)
{
if (_configData.noEscape.useRaidBlocker)
{
// Print(player, Lang("RaidBlocked", player.UserIDString));
player.GetComponent<ToolRemover>()?.DisableTool(false);
}
}

private void OnCombatBlock(BasePlayer player)
{
if (_configData.noEscape.useCombatBlocker)
{
// Print(player, Lang("CombatBlocked", player.UserIDString));
player.GetComponent<ToolRemover>()?.DisableTool(false);
}
}

private bool IsPlayerBlocked(BasePlayer player, out string reason)
{
if (NoEscape != null)
{
if (_configData.noEscape.useRaidBlocker && IsRaidBlocked(player.UserIDString))
{
reason = Lang("RaidBlocked", player.UserIDString);
return true;
}
if (_configData.noEscape.useCombatBlocker && IsCombatBlocked(player.UserIDString))
{
reason = Lang("CombatBlocked", player.UserIDString);
return true;
}
}

reason = null;
return false;
}

private bool IsRaidBlocked(string playerID)
{
return (bool)NoEscape.Call("IsRaidBlocked", playerID);
}

private bool IsCombatBlocked(string playerID)
{
return (bool)NoEscape.Call("IsCombatBlocked", playerID);
}

#endregion NoEscape

#region UI

private static class UI
{
public static CuiElementContainer CreateElementContainer(string parent, string panelName, string backgroundColor, string anchorMin, string anchorMax, string offsetMin = "", string offsetMax = "", bool cursor = false)
{
return new CuiElementContainer
{
{
new CuiPanel
{
Image = { Color = backgroundColor },
RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax, OffsetMin = offsetMin, OffsetMax = offsetMax },
CursorEnabled = cursor
},
parent, panelName
}
};
}

public static void CreatePanel(ref CuiElementContainer container, string panelName, string backgroundColor, string anchorMin, string anchorMax, bool cursor = false)
{
container.Add(new CuiPanel
{
Image = { Color = backgroundColor },
RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax },
CursorEnabled = cursor
}, panelName);
}

public static void CreateLabel(ref CuiElementContainer container, string panelName, string textColor, string text, int fontSize, string anchorMin, string anchorMax, TextAnchor align = TextAnchor.MiddleCenter, float fadeIn = 0f)
{
container.Add(new CuiLabel
{
Text = { Color = textColor, FontSize = fontSize, Align = align, Text = text, FadeIn = fadeIn },
RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax }
}, panelName);
}

public static void CreateImage(ref CuiElementContainer container, string panelName, string image, string anchorMin, string anchorMax, string color = "1 1 1 1")
{
container.Add(new CuiElement
{
Name = CuiHelper.GetGuid(),
Parent = panelName,
Components =
{
new CuiRawImageComponent { Color = color, Png = image },
new CuiRectTransformComponent { AnchorMin = anchorMin, AnchorMax = anchorMax }
}
});
}

public static void CreateImage(ref CuiElementContainer container, string panelName, int itemId, ulong skinId, string anchorMin, string anchorMax)
{
container.Add(new CuiPanel
{
Image = { ItemId = itemId, SkinId = skinId },
RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax },
CursorEnabled = false
}, panelName);
}
}

[Flags]
private enum UiEntry
{
None = 0,
Entity = 1,
Price = 1 << 1,
Refund = 1 << 2,
Auth = 1 << 3
}

private const string UINAME_MAIN = "RemoverToolUI_Main";
private const string UINAME_TIMELEFT = "RemoverToolUI_TimeLeft";
private const string UINAME_ENTITY = "RemoverToolUI_Entity";
private const string UINAME_PRICE = "RemoverToolUI_Price";
private const string UINAME_REFUND = "RemoverToolUI_Refund";
private const string UINAME_AUTH = "RemoverToolUI_Auth";
private const string UINAME_CROSSHAIR = "RemoverToolUI_Crosshair";

private static void CreateCrosshairUI(BasePlayer player)
{
if (_instance.ImageLibrary == null)
{
return;
}
var image = GetImageFromLibrary(UINAME_CROSSHAIR);
if (string.IsNullOrEmpty(image))
{
return;
}
var container = UI.CreateElementContainer("Hud", UINAME_CROSSHAIR, "0 0 0 0", _configData.ui.crosshairAnchorMin, _configData.ui.crosshairAnchorMax, _configData.ui.crosshairOffsetMin, _configData.ui.crosshairOffsetMax);
UI.CreateImage(ref container, UINAME_CROSSHAIR, image, "0 0", "1 1", _configData.ui.crosshairColor);
CuiHelper.DestroyUi(player, UINAME_CROSSHAIR);
CuiHelper.AddUi(player, container);
}

private static void CreateMainUI(BasePlayer player, RemoveType removeType)
{
var container = UI.CreateElementContainer("Hud", UINAME_MAIN, _configData.ui.removerToolBackgroundColor, _configData.ui.removerToolAnchorMin, _configData.ui.removerToolAnchorMax, _configData.ui.removerToolOffsetMin, _configData.ui.removerToolOffsetMax);
UI.CreatePanel(ref container, UINAME_MAIN, _configData.ui.removeBackgroundColor, _configData.ui.removeAnchorMin, _configData.ui.removeAnchorMax);
UI.CreateLabel(ref container, UINAME_MAIN, _configData.ui.removeTextColor, _instance.Lang("RemoverToolType", player.UserIDString, GetRemoveTypeName(removeType)), _configData.ui.removeTextSize, _configData.ui.removeTextAnchorMin, _configData.ui.removeTextAnchorMax, TextAnchor.MiddleLeft);
CuiHelper.DestroyUi(player, UINAME_MAIN);
CuiHelper.AddUi(player, container);
}

private static void UpdateTimeLeftUI(BasePlayer player, RemoveType removeType, int timeLeft, int currentRemoved, int maxRemovable)
{
var container = UI.CreateElementContainer(UINAME_MAIN, UINAME_TIMELEFT, _configData.ui.timeLeftBackgroundColor, _configData.ui.timeLeftAnchorMin, _configData.ui.timeLeftAnchorMax);
UI.CreateLabel(ref container, UINAME_TIMELEFT, _configData.ui.timeLeftTextColor, _instance.Lang("TimeLeft", player.UserIDString, timeLeft, removeType == RemoveType.Normal || removeType == RemoveType.Admin ? maxRemovable == 0 ? $"{currentRemoved} / {_instance.Lang("Unlimit", player.UserIDString)}" : $"{currentRemoved} / {maxRemovable}" : currentRemoved.ToString()), _configData.ui.timeLeftTextSize, _configData.ui.timeLeftTextAnchorMin, _configData.ui.timeLeftTextAnchorMax, TextAnchor.MiddleLeft);
CuiHelper.DestroyUi(player, UINAME_TIMELEFT);
CuiHelper.AddUi(player, container);
}

private static void UpdateEntityUI(BasePlayer player, BaseEntity targetEntity, RemovableEntityInfo? info)
{
var container = UI.CreateElementContainer(UINAME_MAIN, UINAME_ENTITY, _configData.ui.entityBackgroundColor, _configData.ui.entityAnchorMin, _configData.ui.entityAnchorMax);

string displayName, imageName;
TryFindEntityName(player, targetEntity, out displayName, out imageName);
if (info.HasValue && !string.IsNullOrEmpty(info.Value.DisplayName.Value))
{
displayName = info.Value.DisplayName.Value;
}
UI.CreateLabel(ref container, UINAME_ENTITY, _configData.ui.entityTextColor, displayName, _configData.ui.entityTextSize, _configData.ui.entityTextAnchorMin, _configData.ui.entityTextAnchorMax, TextAnchor.MiddleLeft);
if (_configData.ui.entityImageEnabled)
{
var imageAnchorMin = _configData.ui.entityImageAnchorMin;
var imageAnchorMax = _configData.ui.entityImageAnchorMax;
if (info.HasValue && !string.IsNullOrEmpty(info.Value.ImageId.Value))
{
var image = info.Value.ImageId.Value;
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_ENTITY, image, imageAnchorMin, imageAnchorMax);
}
}
else if (!string.IsNullOrEmpty(imageName))
{
string shortname;
int itemId;
if (_instance._shortPrefabNameToDeployable.TryGetValue(imageName, out shortname) && _instance._itemShortNameToItemId.TryGetValue(shortname, out itemId))
{
UI.CreateImage(ref container, UINAME_ENTITY, itemId, targetEntity.skinID, imageAnchorMin, imageAnchorMax);
}
else
{
var image = GetEntityImage(imageName);
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_ENTITY, image, imageAnchorMin, imageAnchorMax);
}
}
}
}
CuiHelper.DestroyUi(player, UINAME_ENTITY);
CuiHelper.AddUi(player, container);
}

private static void UpdatePriceUI(BasePlayer player, BaseEntity targetEntity, RemovableEntityInfo? info, bool usePrice)
{
Dictionary<string, CurrencyInfo> price = null;
if (usePrice)
{
price = _instance.GetPrice(targetEntity, info);
}
var container = UI.CreateElementContainer(UINAME_MAIN, UINAME_PRICE, _configData.ui.priceBackgroundColor, _configData.ui.priceAnchorMin, _configData.ui.priceAnchorMax);
UI.CreateLabel(ref container, UINAME_PRICE, _configData.ui.priceTextColor, _instance.Lang("Price", player.UserIDString), _configData.ui.priceTextSize, _configData.ui.priceTextAnchorMin, _configData.ui.priceTextAnchorMax, TextAnchor.MiddleLeft);
if (price == null || price.Count == 0)
{
UI.CreateLabel(ref container, UINAME_PRICE, _configData.ui.price2TextColor, _instance.Lang("Free", player.UserIDString), _configData.ui.price2TextSize, _configData.ui.price2TextAnchorMin, _configData.ui.price2TextAnchorMax, TextAnchor.MiddleLeft);
}
else
{
var anchorMin = _configData.ui.Price2TextAnchorMin;
var anchorMax = _configData.ui.Price2TextAnchorMax;
var x = (anchorMax.y - anchorMin.y) / price.Count;
var textSize = _configData.ui.price2TextSize - price.Count;
var language = _instance.lang.GetLanguage(player.UserIDString);

var i = 0;
foreach (var entry in price)
{
var externalItemInfo = info?.Price[entry.Key];
var displayText = !externalItemInfo.HasValue || string.IsNullOrEmpty(externalItemInfo.Value.DisplayName.Value)
? $"{GetDisplayNameByCurrencyName(language, entry.Key, entry.Value.SkinId)} <color=#00B5FF>x{entry.Value.Amount}</color>"
: $"{externalItemInfo.Value.DisplayName.Value} x{externalItemInfo.Value.Amount.Value}";

UI.CreateLabel(ref container, UINAME_PRICE, _configData.ui.price2TextColor, displayText, textSize, $"{anchorMin.x} {anchorMin.y + i * x}", $"{anchorMax.x} {anchorMin.y + (i + 1) * x}", TextAnchor.MiddleLeft);
if (_configData.ui.imageEnabled)
{
var imageAnchorMin = $"{anchorMax.x - _configData.ui.rightDistance - x * _configData.ui.imageScale} {anchorMin.y + i * x}";
var imageAnchorMax = $"{anchorMax.x - _configData.ui.rightDistance} {anchorMin.y + (i + 1) * x}";
if (externalItemInfo.HasValue && !string.IsNullOrEmpty(externalItemInfo.Value.ImageId.Value))
{
var image = externalItemInfo.Value.ImageId.Value;
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_PRICE, image, imageAnchorMin, imageAnchorMax);
}
}
else
{
int itemId;
if (_instance._itemShortNameToItemId.TryGetValue(entry.Key, out itemId))
{
UI.CreateImage(ref container, UINAME_PRICE, itemId, entry.Value.SkinId >= 0 ? (ulong)entry.Value.SkinId : 0, imageAnchorMin, imageAnchorMax);
}
else
{
var image = GetItemImage(entry.Key);
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_PRICE, image, imageAnchorMin, imageAnchorMax);
}
}
}
}
i++;
}
}
CuiHelper.DestroyUi(player, UINAME_PRICE);
CuiHelper.AddUi(player, container);
}

private static void UpdateRefundUI(BasePlayer player, BaseEntity targetEntity, RemovableEntityInfo? info, bool useRefund)
{
Dictionary<string, CurrencyInfo> refund = null;
if (useRefund)
{
refund = _instance.GetRefund(targetEntity, info);
}
var container = UI.CreateElementContainer(UINAME_MAIN, UINAME_REFUND, _configData.ui.refundBackgroundColor, _configData.ui.refundAnchorMin, _configData.ui.refundAnchorMax);
UI.CreateLabel(ref container, UINAME_REFUND, _configData.ui.refundTextColor, _instance.Lang("Refund", player.UserIDString), _configData.ui.refundTextSize, _configData.ui.refundTextAnchorMin, _configData.ui.refundTextAnchorMax, TextAnchor.MiddleLeft);

if (refund == null || refund.Count == 0)
{
UI.CreateLabel(ref container, UINAME_REFUND, _configData.ui.refund2TextColor, _instance.Lang("Nothing", player.UserIDString), _configData.ui.refund2TextSize, _configData.ui.refund2TextAnchorMin, _configData.ui.refund2TextAnchorMax, TextAnchor.MiddleLeft);
}
else
{
var anchorMin = _configData.ui.Refund2TextAnchorMin;
var anchorMax = _configData.ui.Refund2TextAnchorMax;
var x = (anchorMax.y - anchorMin.y) / refund.Count;
var textSize = _configData.ui.refund2TextSize - refund.Count;
var language = _instance.lang.GetLanguage(player.UserIDString);

var i = 0;
foreach (var entry in refund)
{
var externalItemInfo = info?.Refund[entry.Key];
var displayText = !externalItemInfo.HasValue || string.IsNullOrEmpty(externalItemInfo.Value.DisplayName.Value)
? $"{GetDisplayNameByCurrencyName(language, entry.Key, entry.Value.SkinId)} <color=#00B5FF>x{entry.Value.Amount}</color>"
: $"{externalItemInfo.Value.DisplayName.Value} x{externalItemInfo.Value.Amount.Value}";

UI.CreateLabel(ref container, UINAME_REFUND, _configData.ui.refund2TextColor, displayText, textSize, $"{anchorMin.x} {anchorMin.y + i * x}", $"{anchorMax.x} {anchorMin.y + (i + 1) * x}", TextAnchor.MiddleLeft);
if (_configData.ui.imageEnabled)
{
var imageAnchorMin = $"{anchorMax.x - _configData.ui.rightDistance - x * _configData.ui.imageScale} {anchorMin.y + i * x}";
var imageAnchorMax = $"{anchorMax.x - _configData.ui.rightDistance} {anchorMin.y + (i + 1) * x}";
if (externalItemInfo.HasValue && !string.IsNullOrEmpty(externalItemInfo.Value.ImageId.Value))
{
var image = externalItemInfo.Value.ImageId.Value;
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_REFUND, image, imageAnchorMin, imageAnchorMax);
}
}
else
{
int itemId;
if (_instance._itemShortNameToItemId.TryGetValue(entry.Key, out itemId))
{
UI.CreateImage(ref container, UINAME_REFUND, itemId, entry.Value.SkinId >= 0 ? (ulong)entry.Value.SkinId : 0, imageAnchorMin, imageAnchorMax);
}
else
{
var image = GetItemImage(entry.Key);
if (!string.IsNullOrEmpty(image))
{
UI.CreateImage(ref container, UINAME_REFUND, image, imageAnchorMin, imageAnchorMax);
}
}
}
}
i++;
}
}
CuiHelper.DestroyUi(player, UINAME_REFUND);
CuiHelper.AddUi(player, container);
}

private static void UpdateAuthorizationUI(BasePlayer player, RemoveType removeType, BaseEntity targetEntity, RemovableEntityInfo? info, bool shouldPay)
{
string reason;
var color = _instance.CanRemoveEntity(player, removeType, targetEntity, info, shouldPay, out reason) ? _configData.ui.allowedBackgroundColor : _configData.ui.refusedBackgroundColor;
var container = UI.CreateElementContainer(UINAME_MAIN, UINAME_AUTH, color, _configData.ui.authorizationsAnchorMin, _configData.ui.authorizationsAnchorMax);
UI.CreateLabel(ref container, UINAME_AUTH, _configData.ui.authorizationsTextColor, reason, _configData.ui.authorizationsTextSize, _configData.ui.authorizationsTextAnchorMin, _configData.ui.authorizationsTextAnchorMax, TextAnchor.MiddleLeft);
CuiHelper.DestroyUi(player, UINAME_AUTH);
CuiHelper.AddUi(player, container);
}

private static void DestroyAllUI(BasePlayer player)
{
CuiHelper.DestroyUi(player, UINAME_CROSSHAIR);
CuiHelper.DestroyUi(player, UINAME_MAIN);
}

private static void DestroyUiEntry(BasePlayer player, UiEntry uiEntry)
{
switch (uiEntry)
{
case UiEntry.Entity:
CuiHelper.DestroyUi(player, UINAME_ENTITY);
return;

case UiEntry.Price:
CuiHelper.DestroyUi(player, UINAME_PRICE);
return;

case UiEntry.Refund:
CuiHelper.DestroyUi(player, UINAME_REFUND);
return;

case UiEntry.Auth:
CuiHelper.DestroyUi(player, UINAME_AUTH);
return;
}
}

#endregion UI

#region ToolRemover Component

#region Tool Helpers

private static bool IsSpecificTool(BasePlayer player)
{
var heldItem = player.GetActiveItem();
return IsSpecificTool(heldItem);
}

private static bool IsSpecificTool(Item heldItem)
{
if (heldItem != null && heldItem.info.shortname == _configData.removerMode.specificToolShortName)
{
if (_configData.removerMode.specificToolSkin < 0)
{
return true;
}
return heldItem.skin == (ulong)_configData.removerMode.specificToolSkin;
}
return false;
}

private static bool IsMeleeTool(BasePlayer player)
{
var heldItem = player.GetActiveItem();
return IsMeleeTool(heldItem);
}

private static bool IsMeleeTool(Item heldItem)
{
if (heldItem != null && heldItem.info.shortname == _configData.removerMode.meleeHitItemShortname)
{
if (_configData.removerMode.meleeHitModeSkin < 0)
{
return true;
}
return heldItem.skin == (ulong)_configData.removerMode.meleeHitModeSkin;
}
return false;
}

#endregion Tool Helpers

private class ToolRemover : FacepunchBehaviour
{
private const float MinInterval = 0.2f;

public int CurrentRemoved { get; set; }
public BaseEntity HitEntity { get; set; }
public bool CanOverride { get; private set; }
public BasePlayer Player { get; private set; }
public RemoveType RemoveType { get; private set; }

private bool _resetTime;
private bool _shouldPay;
private bool _shouldRefund;
private int _removeTime;
private int _maxRemovable;
private float _distance;
private float _removeInterval;

private int _timeLeft;
private float _lastRemove;
private ItemId _currentItemId;
private bool _disableInHand;

private Item _lastHeldItem;
private BaseEntity _targetEntity;
private UiEntry _activeUiEntries;

private void Awake()
{
Player = GetComponent<BasePlayer>();
_currentItemId = Player.svActiveItemID;
_disableInHand = _removeMode == RemoveMode.MeleeHit && _configData.removerMode.meleeHitDisableInHand
|| _removeMode == RemoveMode.SpecificTool && _configData.removerMode.specificToolDisableInHand;
if (_disableInHand)
{
_lastHeldItem = Player.GetActiveItem();
}
if (_removeMode == RemoveMode.NoHeld)
{
UnEquip();
}
}

public void Init(RemoveType removeType, int removeTime, int maxRemovable, float distance, float removeInterval, bool shouldPay, bool shouldRefund, bool resetTime, bool canOverride)
{
RemoveType = removeType;
CanOverride = canOverride;

_distance = distance;
_resetTime = resetTime;
_removeTime = _timeLeft = removeTime;
_removeInterval = Mathf.Max(MinInterval, removeInterval);
if (RemoveType == RemoveType.Normal)
{
_maxRemovable = maxRemovable;
_shouldPay = shouldPay && _configData.remove.priceEnabled;
_shouldRefund = shouldRefund && _configData.remove.refundEnabled;
_instance.PrintDebug($"{Player.displayName}({Player.userID}) have Enabled the remover tool.");
Interface.CallHook("OnRemoverToolActivated", Player);
}
else
{
_maxRemovable = CurrentRemoved = 0;
_shouldPay = _shouldRefund = false;
}

DestroyAllUI(Player);
if (_configData.ui.showCrosshair)
{
CreateCrosshairUI(Player);
}

if (_configData.ui.enabled)
{
CreateMainUI(Player, RemoveType);
}

CancelInvoke(RemoveUpdate);
InvokeRepeating(RemoveUpdate, 0f, 1f);
}

private void RemoveUpdate()
{
if (_configData.ui.enabled)
{
_targetEntity = GetTargetEntity();
UpdateTimeLeftUI(Player, RemoveType, _timeLeft, CurrentRemoved, _maxRemovable);

var info = RemoveType == RemoveType.Normal ? GetRemovableEntityInfo(_targetEntity, Player) : null;
var canShow = (info.HasValue || _targetEntity != null) && CanEntityBeDisplayed(_targetEntity, Player);
if (HandleUiEntry(UiEntry.Entity, canShow))
{
UpdateEntityUI(Player, _targetEntity, info);
}
if (RemoveType == RemoveType.Normal)
{
if (_configData.ui.authorizationEnabled)
{
if (HandleUiEntry(UiEntry.Auth, canShow))
{
UpdateAuthorizationUI(Player, RemoveType, _targetEntity, info, _shouldPay);
}
}
if (_configData.ui.priceEnabled || _configData.ui.refundEnabled)
{
canShow = canShow && (info.HasValue || HasEntityEnabled(_targetEntity));
if (_configData.ui.priceEnabled)
{
if (HandleUiEntry(UiEntry.Price, canShow))
{
UpdatePriceUI(Player, _targetEntity, info, _shouldPay);
}
}
if (_configData.ui.refundEnabled)
{
if (HandleUiEntry(UiEntry.Refund, canShow))
{
UpdateRefundUI(Player, _targetEntity, info, _shouldRefund);
}
}
}
}
}

if (_timeLeft-- <= 0)
{
DisableTool();
}
}

private BaseEntity GetTargetEntity()
{
BaseEntity target = null;
List<RaycastHit> hitInfos = Pool.Get<List<RaycastHit>>();
GamePhysics.TraceAll(Player.eyes.HeadRay(), 0f, hitInfos, _distance, LAYER_TARGET);
foreach (var hitInfo in hitInfos)
{
var hitEntity = hitInfo.GetEntity();
if (hitEntity != null)
{
if (target == null)
{
target = hitEntity;
}
else if (hitEntity.GetParentEntity() == target)
{
target = hitEntity;
break;
}
}
}
Pool.FreeUnmanaged(ref hitInfos);
return target;
// RaycastHit hitInfo;
// if (Physics.Raycast(Player.eyes.HeadRay(), out hitInfo, _distance, LAYER_TARGET))
// {
// return hitInfo.GetEntity();
// }
// return null;
}

private void Update()
{
if (Player == null || !Player.IsConnected || !Player.CanInteract())
{
DisableTool();
return;
}
if (Player.svActiveItemID != _currentItemId)
{
if (_disableInHand)
{
var heldItem = Player.GetActiveItem();
if (_removeMode == RemoveMode.MeleeHit && IsMeleeTool(_lastHeldItem) && !IsMeleeTool(heldItem) ||
_removeMode == RemoveMode.SpecificTool && IsSpecificTool(_lastHeldItem) && !IsSpecificTool(heldItem))
{
DisableTool();
return;
}
_lastHeldItem = heldItem;
}
if (_removeMode == RemoveMode.NoHeld)
{
if (Player.svActiveItemID.IsValid)
{
if (_configData.removerMode.noHeldDisableInHand)
{
DisableTool();
return;
}
UnEquip();
}
}
_currentItemId = Player.svActiveItemID;
}
if (Time.realtimeSinceStartup - _lastRemove >= _removeInterval)
{
if (_removeMode == RemoveMode.MeleeHit)
{
if (HitEntity == null)
{
return;
}
_targetEntity = HitEntity;
HitEntity = null;
}
else
{
if (!Player.serverInput.IsDown(_removeButton))
{
return;
}
if (_removeMode == RemoveMode.SpecificTool && !IsSpecificTool(Player))
{
//rt.Print(player,rt.Lang("UsageOfRemove",player.UserIDString));
return;
}
_targetEntity = GetTargetEntity();
}
if (_instance.TryRemove(Player, _targetEntity, RemoveType, _shouldPay, _shouldRefund))
{
if (_resetTime)
{
_timeLeft = _removeTime;
}
if (RemoveType == RemoveType.Normal || RemoveType == RemoveType.Admin)
{
CurrentRemoved++;
}
if (_configData.global.startCooldownOnRemoved && RemoveType == RemoveType.Normal)
{
_instance._cooldownTimes[Player.userID] = Time.realtimeSinceStartup;
}
}
_lastRemove = Time.realtimeSinceStartup;
}
if (RemoveType == RemoveType.Normal && _maxRemovable > 0 && CurrentRemoved >= _maxRemovable)
{
_instance.Print(Player, _instance.Lang("EntityLimit", Player.UserIDString, _maxRemovable));
DisableTool(false);
}
;
}

private void UnEquip()
{
// Player.lastReceivedTick.activeItem = 0;
var activeItem = Player.GetActiveItem();
if (activeItem?.GetHeldEntity() is HeldEntity)
{
var slot = activeItem.position;
activeItem.SetParent(null);
Player.Invoke(() =>
{
if (activeItem == null || !activeItem.IsValid())
{
return;
}
if (Player.inventory.containerBelt.GetSlot(slot) == null)
{
activeItem.position = slot;
activeItem.SetParent(Player.inventory.containerBelt);
}
else
{
Player.GiveItem(activeItem);
}
}, 0.2f);
}
}

private bool HandleUiEntry(UiEntry uiEntry, bool canShow)
{
if (canShow)
{
_activeUiEntries |= uiEntry;
return true;
}

if (_activeUiEntries.HasFlag(uiEntry))
{
_activeUiEntries &= ~uiEntry;
DestroyUiEntry(Player, uiEntry);
}
return false;
}

public void DisableTool(bool showMessage = true)
{
if (showMessage)
{
if (_instance != null && Player != null && Player.IsConnected)
{
if (_configData != null && _configData.chat.showMessageWhenEnabledOrDisabled)
{
_instance.Print(Player, _instance.Lang("ToolDisabled", Player.UserIDString));
}
}
}

if (RemoveType == RemoveType.Normal)
{
if (_instance != null && Player != null)
{
_instance.PrintDebug($"{Player.displayName}({Player.userID}) have Disabled the remover tool.");
}
Interface.CallHook("OnRemoverToolDeactivated", Player);
}
DestroyAllUI(Player);
Destroy(this);
}

private void OnDestroy()
{
if (_instance != null && RemoveType == RemoveType.Normal)
{
if (_configData != null && !_configData.global.startCooldownOnRemoved)
{
_instance._cooldownTimes[Player.userID] = Time.realtimeSinceStartup;
}
}
}
}

#endregion ToolRemover Component

#region TryRemove

private bool TryRemove(BasePlayer player, BaseEntity targetEntity, RemoveType removeType, bool shouldPay, bool shouldRefund)
{
if (targetEntity == null)
{
Print(player, Lang("NotFoundOrFar", player.UserIDString));
return false;
}
if (targetEntity.IsDestroyed)
{
Print(player, Lang("InvalidEntity", player.UserIDString));
return false;
}
if (removeType != RemoveType.Normal)
{
var result = Interface.CallHook("CanAdminRemove", player, targetEntity, removeType.ToString());
if (result != null)
{
Print(player, result is string ? (string)result : Lang("BeBlocked", player.UserIDString));
return false;
}
switch (removeType)
{
case RemoveType.Admin:
{
var target = targetEntity as BasePlayer;
if (target != null)
{
if (target.userID.IsSteamId() && target.IsConnected)
{
target.Kick("From RemoverTool Plugin");
return true;
}
}
DoRemove(targetEntity, _configData.removeType[RemoveType.Admin].gibs ? BaseNetworkable.DestroyMode.Gib : BaseNetworkable.DestroyMode.None);
return true;
}
case RemoveType.All:
{
if (_removeAllCoroutine != null)
{
Print(player, Lang("AlreadyRemoveAll", player.UserIDString));
return false;
}
_removeAllCoroutine = ServerMgr.Instance.StartCoroutine(RemoveAll(targetEntity, player));
Print(player, Lang("StartRemoveAll", player.UserIDString));
return true;
}
case RemoveType.External:
{
var stabilityEntity = targetEntity as StabilityEntity;
if (stabilityEntity == null || !IsExternalWall(stabilityEntity))
{
Print(player, Lang("NotExternalWall", player.UserIDString));
return false;
}
if (_removeExternalCoroutine != null)
{
Print(player, Lang("AlreadyRemoveExternal", player.UserIDString));
return false;
}
_removeExternalCoroutine = ServerMgr.Instance.StartCoroutine(RemoveExternal(stabilityEntity, player));
Print(player, Lang("StartRemoveExternal", player.UserIDString));
return true;
}
case RemoveType.Structure:
{
var decayEntity = targetEntity as DecayEntity;
if (decayEntity == null)
{
Print(player, Lang("NotStructure", player.UserIDString));
return false;
}
if (_removeStructureCoroutine != null)
{
Print(player, Lang("AlreadyRemoveStructure", player.UserIDString));
return false;
}
_removeStructureCoroutine = ServerMgr.Instance.StartCoroutine(RemoveStructure(decayEntity, player));
Print(player, Lang("StartRemoveStructure", player.UserIDString));
return true;
}
}
}

var info = GetRemovableEntityInfo(targetEntity, player);

string reason;
if (!CanRemoveEntity(player, removeType, targetEntity, info, shouldPay, out reason))
{
Print(player, reason);
return false;
}

DropContainerEntity(targetEntity);

if (shouldPay)
{
var flag = TryPay(player, targetEntity, info);
if (!flag)
{
Print(player, Lang("CantPay", player.UserIDString));
return false;
}
}

if (shouldRefund)
{
GiveRefund(player, targetEntity, info);
}

DoNormalRemove(player, targetEntity, _configData.removeType[RemoveType.Normal].gibs);
return true;
}

private bool CanRemoveEntity(BasePlayer player, RemoveType removeType, BaseEntity targetEntity, RemovableEntityInfo? info, bool shouldPay, out string reason)
{
if (removeType != RemoveType.Normal)
{
reason = null;
return true;
}
if (targetEntity == null || !CanEntityBeDisplayed(targetEntity, player))
{
reason = Lang("NotFoundOrFar", player.UserIDString);
return false;
}
if (targetEntity.IsDestroyed)
{
reason = Lang("InvalidEntity", player.UserIDString);
return false;
}
if (!info.HasValue)
{
if (!IsRemovableEntity(targetEntity))
{
reason = Lang("InvalidEntity", player.UserIDString);
return false;
}
if (!HasEntityEnabled(targetEntity))
{
reason = Lang("EntityDisabled", player.UserIDString);
return false;
}
}
var result = Interface.CallHook("canRemove", player, targetEntity);
if (result != null)
{
reason = result is string ? (string)result : Lang("BeBlocked", player.UserIDString);
return false;
}
if (!_configData.damagedEntity.enabled && IsDamagedEntity(targetEntity))
{
reason = Lang("DamagedEntity", player.UserIDString);
return false;
}
if (IsPlayerBlocked(player, out reason))
{
return false;
}
if (_configData.global.entityTimeLimit && IsEntityTimeLimit(targetEntity))
{
reason = Lang("EntityTimeLimit", player.UserIDString, _configData.global.limitTime);
return false;
}
if (!_configData.container.removeNotEmptyStorage)
{
var storageContainer = targetEntity as StorageContainer;
if (storageContainer != null && storageContainer.inventory?.itemList?.Count > 0)
{
reason = Lang("StorageNotEmpty", player.UserIDString);
return false;
}
}
if (!_configData.container.removeNotEmptyIoEntity)
{
var containerIOEntity = targetEntity as ContainerIOEntity;
if (containerIOEntity != null && containerIOEntity.inventory?.itemList?.Count > 0)
{
reason = Lang("StorageNotEmpty", player.UserIDString);
return false;
}
}
if (shouldPay && !CanPay(player, targetEntity, info))
{
reason = Lang("NotEnoughCost", player.UserIDString);
return false;
}
if (!HasAccess(player, targetEntity))
{
reason = Lang("NotRemoveAccess", player.UserIDString);
return false;
}
reason = Lang("CanRemove", player.UserIDString);
return true;
}

private bool HasAccess(BasePlayer player, BaseEntity targetEntity)
{
if (_configData.global.useBuildingOwners && BuildingOwners != null)
{
var buildingBlock = targetEntity as BuildingBlock;
if (buildingBlock != null)
{
var result = BuildingOwners?.Call("FindBlockData", buildingBlock) as string;
if (result != null)
{
var ownerID = ulong.Parse(result);
if (AreFriends(ownerID, player.userID))
{
return true;
}
}
}
}
//var 1 = configData.globalS.excludeTwigs && (targetEntity as BuildingBlock)?.grade == BuildingGrade.Enum.Twigs;
if (_configData.global.useEntityOwners)
{
if (AreFriends(targetEntity.OwnerID, player.userID))
{
if (!_configData.global.useToolCupboards)
{
return true;
}
if (HasTotalAccess(player, targetEntity))
{
return true;
}
}

return false;
}
if (_configData.global.useToolCupboards)
{
if (HasTotalAccess(player, targetEntity))
{
return true;
}
}
return false;
}

private static bool HasTotalAccess(BasePlayer player, BaseEntity targetEntity)
{
if (player.IsBuildingBlocked(targetEntity.WorldSpaceBounds()))
{
return false;
}
if (_configData.global.useBuildingLocks && !CanOpenAllLocks(player, targetEntity))
{
//reason = Lang("Can'tOpenAllLocks", player.UserIDString);
return false;
}
return true;
}

private static bool CanOpenAllLocks(BasePlayer player, BaseEntity targetEntity)
{
var decayEntities = Pool.Get<List<DecayEntity>>();
var building = targetEntity.GetBuildingPrivilege()?.GetBuilding() ?? (targetEntity as DecayEntity)?.GetBuilding();
if (building != null)
{
decayEntities.AddRange(building.decayEntities);
}
/*else//An entity placed outside
{
Vis.Entities(targetEntity.transform.position, 9f, decayEntities, Layers.Mask.Construction | Layers.Mask.Deployed);
}*/
foreach (var decayEntity in decayEntities)
{
if ((decayEntity is Door || decayEntity is BoxStorage) && decayEntity.OwnerID.IsSteamId())
{
var lockEntity = decayEntity.GetSlot(BaseEntity.Slot.Lock) as BaseLock;
if (lockEntity != null && !OnTryToOpen(player, lockEntity))
{
Pool.FreeUnmanaged(ref decayEntities);
return false;
}
}
}
Pool.FreeUnmanaged(ref decayEntities);
return true;
}

private static bool OnTryToOpen(BasePlayer player, BaseLock baseLock)
{
var codeLock = baseLock as CodeLock;
if (codeLock != null)
{
var obj = Interface.CallHook("CanUseLockedEntity", player, codeLock);
if (obj is bool)
{
return (bool)obj;
}
if (!codeLock.IsLocked())
{
return true;
}
// Make no sound during the check
if (codeLock.whitelistPlayers.Contains(player.userID) || codeLock.guestPlayers.Contains(player.userID))
{
return true;
}
return false;
}
var keyLock = baseLock as KeyLock;
if (keyLock != null)
{
return keyLock.OnTryToOpen(player);
}

return false;
}

private static bool IsDamagedEntity(BaseEntity entity)
{
var baseCombatEntity = entity as BaseCombatEntity;
if (baseCombatEntity == null || !baseCombatEntity.repair.enabled)
{
return false;
}
if (_configData.damagedEntity.excludeBuildingBlocks && (baseCombatEntity is BuildingBlock || baseCombatEntity is SimpleBuildingBlock))
{
return false;
}
if (_configData.damagedEntity.excludeQuarries && !(baseCombatEntity is BuildingBlock))
{
// Quarries
if (baseCombatEntity.repair.itemTarget == null || baseCombatEntity.repair.itemTarget.Blueprint == null)
{
return false;
}
}

if (baseCombatEntity.healthFraction * 100f >= _configData.damagedEntity.percentage)
{
return false;
}
return true;
}

private static bool IsEntityTimeLimit(BaseEntity entity)
{
if (entity.net == null)
{
return true;
}
float spawnedTime;
if (_instance._entitySpawnedTimes.TryGetValue(entity.net.ID.Value, out spawnedTime))
{
return Time.realtimeSinceStartup - spawnedTime > _configData.global.limitTime;
}
return true;
}

private static void DropContainerEntity(BaseEntity targetEntity)
{
var itemContainerEntity = targetEntity as IItemContainerEntity;
if (itemContainerEntity != null && itemContainerEntity.inventory?.itemList?.Count > 0)
{
bool dropContainer = false, dropItems = false;
var storageContainer = targetEntity as StorageContainer;
if (storageContainer != null)
{
dropContainer = _configData.container.dropContainerStorage;
dropItems = _configData.container.dropItemsStorage;
}
else
{
var containerIoEntity = targetEntity as ContainerIOEntity;
if (containerIoEntity != null)
{
dropContainer = _configData.container.dropContainerIoEntity;
dropItems = _configData.container.dropItemsIoEntity;
}
}
if (dropContainer || dropItems)
{
if (Interface.CallHook("OnDropContainerEntity", targetEntity) == null)
{
if (dropContainer)
{
DropItemContainer(itemContainerEntity.inventory, itemContainerEntity.GetDropPosition(), itemContainerEntity.Transform.rotation);
}
else if (dropItems)
{
itemContainerEntity.DropItems();
}
}
}
}
}

#region AreFriends

private bool AreFriends(ulong playerID, ulong friendID)
{
if (!playerID.IsSteamId())
{
return false;
}
if (playerID == friendID)
{
return true;
}
if (_configData.global.useTeams && SameTeam(playerID, friendID))
{
return true;
}
if (_configData.global.useFriends && HasFriend(playerID, friendID))
{
return true;
}
if (_configData.global.useClans && SameClan(playerID, friendID))
{
return true;
}
return false;
}

private static bool SameTeam(ulong playerID, ulong friendID)
{
if (!RelationshipManager.TeamsEnabled())
{
return false;
}
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(playerID);
if (playerTeam == null)
{
return false;
}
var friendTeam = RelationshipManager.ServerInstance.FindPlayersTeam(friendID);
if (friendTeam == null)
{
return false;
}
return playerTeam == friendTeam;
}

private bool HasFriend(ulong playerID, ulong friendID)
{
if (Friends == null)
{
return false;
}
return (bool)Friends.Call("HasFriend", playerID, friendID);
}

private bool SameClan(ulong playerID, ulong friendID)
{
if (Clans == null)
{
return false;
}
//Clans
var isMember = Clans.Call("IsClanMember", playerID.ToString(), friendID.ToString());
if (isMember != null)
{
return (bool)isMember;
}
//Rust:IO Clans
var playerClan = Clans.Call("GetClanOf", playerID);
if (playerClan == null)
{
return false;
}
var friendClan = Clans.Call("GetClanOf", friendID);
if (friendClan == null)
{
return false;
}
return (string)playerClan == (string)friendClan;
}

#endregion AreFriends

#endregion TryRemove

#region Pay

private Dictionary<string, CurrencyInfo> GetPrice(BaseEntity targetEntity, RemovableEntityInfo? info)
{
if (info.HasValue)
{
return info.Value.Price.ValueName2Currency;
}
var buildingBlock = targetEntity as BuildingBlock;
if (buildingBlock != null)
{
var entityName = _prefabNameToStructure[buildingBlock.PrefabName];
BuildingBlocksSettings buildingBlockSettings;
if (_configData.remove.buildingBlock.TryGetValue(entityName, out buildingBlockSettings))
{
BuildingGradeSettings buildingGradeSettings;
if (buildingBlockSettings.buildingGrade.TryGetValue(buildingBlock.grade, out buildingGradeSettings))
{
if (buildingGradeSettings.priceDict != null)
{
return buildingGradeSettings.priceDict;
}
if (buildingGradeSettings.pricePercentage > 0f)
{
var currentGrade = buildingBlock.currentGrade;
if (currentGrade != null)
{
var price = new Dictionary<string, CurrencyInfo>();
var costToBuild = buildingBlock.blockDefinition.GetGrade(buildingBlock.grade, buildingBlock.skinID).CostToBuild();
foreach (var itemAmount in costToBuild)
{
var amount = Mathf.RoundToInt(itemAmount.amount * buildingGradeSettings.pricePercentage / 100);
if (amount <= 0)
{
continue;
}
price.Add(itemAmount.itemDef.shortname, new CurrencyInfo(amount));
}

return price;
}
}
else if (buildingGradeSettings.pricePercentage < 0f)
{
var currentGrade = buildingBlock.currentGrade;
if (currentGrade != null)
{
return buildingBlock.blockDefinition.GetGrade(buildingBlock.grade, buildingBlock.skinID).CostToBuild().ToDictionary(x => x.itemDef.shortname, y => new CurrencyInfo(Mathf.RoundToInt(y.amount)));
}
}
}
}
}
else
{
EntitySettings entitySettings;
if (_configData.remove.entity.TryGetValue(targetEntity.ShortPrefabName, out entitySettings))
{
return entitySettings.priceDict;
}
}
return null;
}

private bool TryPay(BasePlayer player, BaseEntity targetEntity, RemovableEntityInfo? info)
{
var price = GetPrice(targetEntity, info);
if (price == null || price.Count == 0)
{
return true;
}
var collect = Pool.Get<List<Item>>();
try
{
foreach (var entry in price)
{
if (entry.Value.Amount <= 0)
{
continue;
}
int itemId;
if (_itemShortNameToItemId.TryGetValue(entry.Key, out itemId))
{
var take = TakeInventory(player, itemId, entry.Value, collect);
player.Command("note.inv", itemId, -take);
}
else if (!CheckOrPay(targetEntity, player, entry.Key, entry.Value, false))
{
return false;
}
}
}
catch (Exception e)
{
PrintError($"{player} couldn't pay to remove entity. Error: {e}");
return false;
}
finally
{
foreach (var item in collect)
{
item.Remove();
}
Pool.FreeUnmanaged(ref collect);
}
return true;
}

private bool CanPay(BasePlayer player, BaseEntity targetEntity, RemovableEntityInfo? info)
{
var price = GetPrice(targetEntity, info);
if (price == null || price.Count == 0)
{
return true;
}
foreach (var entry in price)
{
if (entry.Value.Amount <= 0)
{
continue;
}
int itemId;
if (_itemShortNameToItemId.TryGetValue(entry.Key, out itemId))
{
var amount = GetInventoryAmount(player, itemId, entry.Value);
if (amount < entry.Value.Amount)
{
return false;
}
}
else if (!CheckOrPay(targetEntity, player, entry.Key, entry.Value, true))
{
return false;
}
}
return true;
}

private bool CheckOrPay(BaseEntity targetEntity, BasePlayer player, string itemName, CurrencyInfo currencyInfo, bool check)
{
if (currencyInfo.Amount <= 0)
{
return true;
}
switch (itemName.ToLower())
{
case ECONOMICS_KEY:
if (Economics == null)
{
return false;
}
if (check)
{
var balance = Economics.Call("Balance", player.userID);
if (balance == null)
{
return false;
}
if ((double)balance < currencyInfo.Amount)
{
return false;
}
}
else
{
var withdraw = Economics.Call("Withdraw", player.userID, (double)currencyInfo.Amount);
if (withdraw == null || !(bool)withdraw)
{
return false;
}
}
return true;

case SERVER_REWARDS_KEY:
if (ServerRewards == null)
{
return false;
}
if (check)
{
var points = ServerRewards.Call("CheckPoints", player.userID);
if (points == null)
{
return false;
}

if ((int)points < currencyInfo.Amount)
{
return false;
}
}
else
{
var takePoints = ServerRewards.Call("TakePoints", player.userID, currencyInfo.Amount);
if (takePoints == null || !(bool)takePoints)
{
return false;
}
}
return true;

default:
{
var result = Interface.CallHook("OnRemovableEntityCheckOrPay", targetEntity, player, itemName, currencyInfo.Amount, currencyInfo.SkinId, check);
if (result is bool)
{
return (bool)result;
}
}

return true;
}
}

private static

Merged post

https://drive.google.com/file/d/1rZUtWGYs5O1CEuc8DHpn6nG-pbyvJe3K/view?usp=sharing

 

Ignore my last message since I couldnt paste it all. Use this link to download