C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
#region License (GPL v2)
/*
Loot Protection - Prevent access to player containers
Copyright (c) 2020 RFC1920 <desolationoutpostpve@gmail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License v2.0.This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.Optionally you can also view the license at <http://www.gnu.org/licenses/>.*/
#endregion License (GPL v2)
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Oxide.Plugins {
[Info("Loot Protection", "RFC1920", "1.0.42")]
[Description("Prevent access to player containers, locks, etc.")]
internal class LootProtect : RustPlugin {
#region vars
private Dictionary<string, List<Share>> sharing = new Dictionary<string, List<Share>>();
private Dictionary<string, long> lastConnected = new Dictionary<string, long>();
private Dictionary<ulong, ulong> lootingBackpack = new Dictionary<ulong, ulong>();
private const string permLootProtAdmin = "lootprotect.admin";
private const string permLootProtAll = "lootprotect.all";
private const string permLootProtShare = "lootprotect.share";
private const string permLootProtected = "lootprotect.player";
private ConfigData configData;
private bool newsave;
[PluginReference]
private readonly Plugin ZoneManager, Friends, Clans, RustIO, NextGenPVE;
private readonly string logfilename = "log";
private bool dolog;
private bool logtofile;
private bool enabled = true;
public class Share {
public string name;
public uint netid;
public ulong sharewith;
}
#endregion vars
#region Message
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
private void Message(IPlayer player, string key, params object[] args) => player.Message(Lang(key, player.Id, args));
private void LMessage(IPlayer player, string key, params object[] args) => player.Reply(Lang(key, player.Id, args));
#endregion Message
#region init
private void Init() {
LoadConfigVariables();
AddCovalenceCommand("lp", "CmdLootProt");
AddCovalenceCommand("share", "CmdShare");
AddCovalenceCommand("unshare", "CmdUnShare");
AddCovalenceCommand("bshare", "CmdShareBuilding");
AddCovalenceCommand("bunshare", "CmdUnShareBuilding");
permission.RegisterPermission(permLootProtected, this);
permission.RegisterPermission(permLootProtAdmin, this);
permission.RegisterPermission(permLootProtAll, this);
permission.RegisterPermission(permLootProtShare, this);
if (configData.Options.useSchedule) RunSchedule(true);
}
private void OnServerInitialized() => LoadData();
private void Unload() => SaveData();
private void OnHammerHit(BasePlayer player, HitInfo hit) {
if (!configData.Options.useHammerForShareStatus) return;
BaseEntity ent = hit.HitEntity;
if (ent != null && sharing.ContainsKey(ent.OwnerID.ToString())) {
string ename = ent.ShortPrefabName;
if (ename.Equals("cupboard.tool.deployed")) {
player.SendConsoleCommand("bshare ?");
}
else {
player.SendConsoleCommand("share ?");
}
}
}
private void OnUserConnected(IPlayer player) {
if (!sharing.ContainsKey(player.Id)) {
sharing.Add(player.Id, new List<Share>());
SaveData();
}
OnUserDisconnected(player);
}
private void OnUserDisconnected(IPlayer player) {
long lc = 0;
lastConnected.TryGetValue(player.Id, out lc);
if (lc > 0) {
lastConnected[player.Id] = ToEpochTime(DateTime.UtcNow);
}
else {
lastConnected.Add(player.Id, ToEpochTime(DateTime.UtcNow));
}
SaveData();
}
// Call out from Backpacks plugin
private void OnBackpackOpened(BasePlayer looter, ulong OwnerId, ItemContainer _itemContainer) {
if (!lootingBackpack.ContainsKey(looter.userID)) lootingBackpack.Add(looter.userID, OwnerId);
}
private void OnBackpackClosed(BasePlayer looter, ulong OwnerId, ItemContainer _itemContainer) {
if (lootingBackpack.ContainsKey(looter.userID)) lootingBackpack.Remove(looter.userID);
}
private void OnNewSave() {
newsave = true;
}
private void SaveData() {
Interface.Oxide.DataFileSystem.WriteObject(Name + "/sharing", sharing);
Interface.Oxide.DataFileSystem.WriteObject(Name + "/lastconnected", lastConnected);
}
private void LoadData() {
if (newsave) {
newsave = false;
lastConnected = new Dictionary<string, long>();
sharing = new Dictionary<string, List<Share>>();
SaveData();
return;
}
else {
lastConnected = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, long>>(Name + "/lastconnected");
sharing = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, List<Share>>>(Name + "/sharing");
}
if (sharing == null) {
sharing = new Dictionary<string, List<Share>>();
SaveData();
}
}
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["checkinglocal"]
= "[LootProtect] Checking {0} local entities", ["enabled"] = "LootProtect enabled.", ["disabled"] = "LootProtect disabled.", ["status"] = "LootProtect enable is set to {0}.", ["logging"] = "Logging set to {0}", ["all"] = "all", ["friends"] = "friends", ["nonefound"] = "No entity found.", ["settings"] = "{0} Settings:\n{1}", ["shared"] = "{0} shared with {1}.", ["sharedf"] = "{0} shared with friends.", ["removeshare"] = "Sharing removed.", ["removesharefor"] = "Sharing removed for {0} entities.", ["shareinfo"] = "Share info for {0}", ["lpshareinfo"] = "[LootProtect] Share info for {0}", ["notauthorized"] = "You don't have permission to use this command.",
}
, this);
}
private void RunSchedule(bool refresh = false) {
TimeSpan ts = new TimeSpan();
if (configData.Options.useRealTime) {
ts = new TimeSpan((int)DateTime.Now.DayOfWeek, 0, 0, 0).Add(DateTime.Now.TimeOfDay);
}
else {
try {
ts = TOD_Sky.Instance.Cycle.DateTime.TimeOfDay;
}
catch {
DoLog("TOD_Sky failure...");
refresh = true;
}
}
Schedule parsed;
bool doenable = false;
if (ParseSchedule(configData.Schedule, out parsed)) {
foreach (int x in parsed.day) {
DoLog($"Schedule day == {x} {parsed.dayName[0]} {parsed.starthour} to {parsed.endhour}");
if (ts.Days == x) {
DoLog($"Day matched.Comparing {ts.Hours}:{ts.Minutes.ToString().PadLeft(2, '0')} to start time {parsed.starthour}:{parsed.startminute} and end time {parsed.endhour}:{parsed.endminute}");
if (ts.Hours >= Convert.ToInt32(parsed.starthour) && ts.Hours <= Convert.ToInt32(parsed.endhour)) {
// Hours matched for activating ruleset, check minutes
DoLog("Hours matched", 1);
if (ts.Hours == Convert.ToInt32(parsed.starthour) && ts.Minutes >= Convert.ToInt32(parsed.startminute)) {
DoLog("Matched START hour and minute.", 2);
doenable = true;
}
else if (ts.Hours == Convert.ToInt32(parsed.endhour) && ts.Minutes <= Convert.ToInt32(parsed.endminute)) {
DoLog("Matched END hour and minute.", 2);
doenable = true;
}
else if (ts.Hours > Convert.ToInt32(parsed.starthour) && ts.Hours < Convert.ToInt32(parsed.endhour)) {
DoLog("Between start and end hours.", 2);
doenable = true;
}
else {
DoLog("Minute mismatch for START OR END.", 2);
doenable = false;
}
}
else {
DoLog("Hours NOT matched", 1);
doenable = false;
}
}
}
}
enabled = doenable;
timer.Once(configData.Options.useRealTime ? 30f : 5f, () => RunSchedule(refresh));
}
#endregion init
#region commands
[Command("unshare")]
private void CmdUnShare(IPlayer iplayer, string command, string[] args) {
if (iplayer == null) return;
if (!iplayer.HasPermission(permLootProtShare) && !iplayer.HasPermission(permLootProtAdmin)) {
Message(iplayer, "notauthorized");
return;
}
string debug = string.Join(",", args);
DoLog($"{command} {debug}");
if (!sharing.ContainsKey(iplayer.Id)) {
sharing.Add(iplayer.Id, new List<Share>());
}
if (args.Length == 0) {
BasePlayer player = iplayer.Object as BasePlayer;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 2.2f)) {
BaseEntity ent = hit.GetEntity();
if (ent != null) {
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) return;
List<Share> repl = new List<Share>();
foreach (Share x in sharing[iplayer.Id]) {
if (x.netid != (uint)ent.net.ID.Value) {
repl.Add(x);
}
else {
DoLog($"Removing {ent.net.ID} from sharing list...");
}
}
sharing[iplayer.Id] = repl;
SaveData();
LoadData();
Message(iplayer, "removeshare");
}
}
}
}
[Command("share")]
private void CmdShare(IPlayer iplayer, string command, string[] args) {
if (iplayer == null) return;
if (!iplayer.HasPermission(permLootProtShare) && !iplayer.HasPermission(permLootProtAdmin)) {
Message(iplayer, "notauthorized");
return;
}
string debug = string.Join(",", args);
DoLog($"{command} {debug}");
if (!sharing.ContainsKey(iplayer.Id)) {
sharing.Add(iplayer.Id, new List<Share>());
}
if (args.Length == 0) {
BasePlayer player = iplayer.Object as BasePlayer;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 2.2f)) {
BaseEntity ent = hit.GetEntity();
if (ent != null) {
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) return;
string ename = ent.ShortPrefabName;
sharing[iplayer.Id].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ename, sharewith = 0
}
);
SaveData();
Message(iplayer, "shared", ename, Lang("all"));
}
}
}
else if (args.Length == 1) {
if (args[0] == "?") {
BasePlayer player = iplayer.Object as BasePlayer;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 2.2f)) {
BaseEntity ent = hit.GetEntity();
string message = "";
if (ent != null) {
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) return;
// SHOW SHARED BY, KEEP IN MIND WHO OWNS BUT DISPLAY IF FRIEND, ETC...if (sharing.ContainsKey(ent.OwnerID.ToString()))
{
string ename = ent.ShortPrefabName;
message += $"{ename}({ent.net.ID}):\n";
foreach (Share x in sharing[ent.OwnerID.ToString()]) {
if (x.netid != (uint)ent.net.ID.Value) continue;
if (x.sharewith == 0) {
message += "\t" + Lang("all") + "\n";
}
else if (x.sharewith == 1) {
message += "\t" + Lang("friends") + "\n";
}
else {
message += $"\t{x.sharewith}\n";
}
}
Message(iplayer, "lpshareinfo", message);
}
}
else {
Message(iplayer, "nonefound");
}
}
}
else if (args[0] == "friends") {
if (!configData.Options.HonorRelationships) return;
BasePlayer player = iplayer.Object as BasePlayer;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 2.2f)) {
BaseEntity ent = hit.GetEntity();
if (ent != null) {
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) return;
string ename = ent.ShortPrefabName;
sharing[iplayer.Id].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ename, sharewith = 1
}
);
SaveData();
Message(iplayer, "sharedf", ename);
}
}
}
else {
BasePlayer sharewith = FindPlayerByName(args[0]);
BasePlayer player = iplayer.Object as BasePlayer;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 2.2f)) {
BaseEntity ent = hit.GetEntity();
if (ent != null) {
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) return;
string ename = ent.ShortPrefabName;
if (sharewith == null) {
if (!configData.Options.HonorRelationships) return;
sharing[iplayer.Id].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ename, sharewith = 1
}
);
}
else {
sharing[iplayer.Id].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ename, sharewith = sharewith.userID
}
);
}
SaveData();
Message(iplayer, "shared", ename, sharewith.displayName);
}
}
}
}
}
[Command("bunshare")]
private void CmdUnShareBuilding(IPlayer iplayer, string command, string[] args) {
if (iplayer == null) return;
if (!iplayer.HasPermission(permLootProtShare) && !iplayer.HasPermission(permLootProtAdmin)) {
Message(iplayer, "notauthorized");
return;
}
BasePlayer player = iplayer.Object as BasePlayer;
string debug = string.Join(",", args);
DoLog($"{command} {debug}");
if (!sharing.ContainsKey(iplayer.Id)) {
sharing.Add(iplayer.Id, new List<Share>());
}
int found = 0;
Collider[] hits = Physics.OverlapSphere(player.transform.position, configData.Options.BuildingShareRange, LayerMask.GetMask("Default", "Deployed"));
List<Share> repl = new List<Share>(sharing[iplayer.Id]);
DoLog($"Checking {hits.Length} local entities");
Message(iplayer, "checkinglocal", hits.Length.ToString());
for (int i = 0; i < hits.Length; i++) {
BaseEntity ent = hits[i].GetComponentInParent<BaseEntity>();
if (ent == null) continue;
// Skip actual TC
if (ent.ShortPrefabName.Equals("cupboard.tool.deployed")) {
continue;
}
if (ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID)) continue;
if (ent.GetBuildingPrivilege() == null) continue;
foreach (Share x in sharing[iplayer.Id]) {
if (x.netid == 0) continue;
if (x.netid == (uint)ent.net.ID.Value) {
found++;
if (repl.Contains(x)) repl.Remove(x);
DoLog($"Removing {ent.ShortPrefabName} ({ent.net.ID}) from sharing list...");
}
}
}
if (found > 0) {
sharing[iplayer.Id] = repl;
SaveData();
LoadData();
Message(iplayer, "removesharefor", found.ToString());
}
}
private void ShareBuilding(Vector3 position, ulong owner, float range = 0) {
if (range == 0) range = configData.Options.BuildingShareRange;
if (!sharing.ContainsKey(owner.ToString())) {
sharing.Add(owner.ToString(), new List<Share>());
SaveData();
}
Collider[] hits = Physics.OverlapSphere(position, range, LayerMask.GetMask("Default", "Deployed"));
List<string> excludestd = new List<string>() {
"cupboard.tool.deployed", "doorcloser", "rug.deployed", "shelves", "table.deployed", "spinner.wheel.deployed", "metal-ore", "sulfur-ore", "stone-ore", "loot_barrel_2", "loot-barrel-1", "trash-pile-1"
}
;
List<string> excludelights = new List<string>() {
"ceilinglight.deployed", "tunalight.deployed", "lantern.deployed"
}
;
DoLog($"Checking {hits.Length} local entities");
int count = 0;
List<ulong> populated = new List<ulong>();
for (int i = 0; i < hits.Length; i++) {
BaseEntity ent = hits[i].GetComponentInParent<BaseEntity>();
if (ent == null) continue;
if (string.IsNullOrEmpty(ent.ShortPrefabName)) continue;
if (owner > 0) {
ent.OwnerID = owner;
}
DoLog($"Checking {ent.ShortPrefabName}, owner: {ent.OwnerID}");
if (excludestd.Contains(ent.ShortPrefabName)) {
continue;
}
else if (excludelights.Contains(ent.ShortPrefabName) && !configData.Options.BShareIncludeLights) {
continue;
}
else if (ent.ShortPrefabName.Contains("sign") && !configData.Options.BShareIncludeSigns) {
continue;
}
else if (ent.ShortPrefabName.Contains("electric") && !configData.Options.BShareIncludeElectrical) {
continue;
}
count++;
if (populated.Contains((uint)ent.net.ID.Value)) continue;
populated.Add((uint)ent.net.ID.Value);
DoLog($"Adding {ent.ShortPrefabName} ({ent.net.ID}) to sharing list...");
//Message(iplayer, $"Sharing {ent.ShortPrefabName}");
// Entity under control of TC
sharing[owner.ToString()].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ent.ShortPrefabName, sharewith = 0
}
);
}
DoLog($"Shared {count} entities");
SaveData();
}
[Command("bshare")]
private void CmdShareBuilding(IPlayer iplayer, string command, string[] args) {
if (iplayer == null) return;
if (!iplayer.HasPermission(permLootProtShare) && !iplayer.HasPermission(permLootProtAdmin)) {
Message(iplayer, "notauthorized");
return;
}
BasePlayer player = iplayer.Object as BasePlayer;
string debug = string.Join(",", args);
DoLog($"{command} {debug}");
if (!sharing.ContainsKey(iplayer.Id)) {
sharing.Add(iplayer.Id, new List<Share>());
}
bool query = false;
if (args.Length == 1 && args[0] == "?") {
query = true;
}
string message = "";
Collider[] hits = Physics.OverlapSphere(player.transform.position, configData.Options.BuildingShareRange, LayerMask.GetMask("Default", "Deployed"));
List<string> excludestd = new List<string>() {
"cupboard.tool.deployed", "doorcloser", "rug.deployed", "shelves", "table.deployed", "spinner.wheel.deployed", "metal-ore", "sulfur-ore", "stone-ore", "loot_barrel_2", "loot-barrel-1", "trash-pile-1"
}
;
List<string> excludelights = new List<string>() {
"ceilinglight.deployed", "tunalight.deployed", "lantern.deployed"
}
;
DoLog($"Checking {hits.Length} local entities");
Message(iplayer, "checkinglocal", hits.Length.ToString());
int count = 0;
List<ulong> populated = new List<ulong>();
for (int i = 0; i < hits.Length; i++) {
BaseEntity ent = hits[i].GetComponentInParent<BaseEntity>();
if (ent == null) continue;
if (string.IsNullOrEmpty(ent.ShortPrefabName)) continue;
if (ent.OwnerID == 0) continue;
DoLog($"Checking {ent.ShortPrefabName}, owner: {ent.OwnerID}");
if (excludestd.Contains(ent.ShortPrefabName)) {
continue;
}
else if (excludelights.Contains(ent.ShortPrefabName) && !configData.Options.BShareIncludeLights) {
continue;
}
else if (ent.ShortPrefabName.Contains("sign") && !configData.Options.BShareIncludeSigns) {
continue;
}
else if (ent.ShortPrefabName.Contains("electric") && !configData.Options.BShareIncludeElectrical) {
continue;
}
// If player has lootprotect admin, allow the share.Otherwise, check ownership or friend relationship.if (!iplayer.HasPermission(permLootProtAdmin) && ent.OwnerID != player.userID && !IsFriend(player.userID, ent.OwnerID))
{
continue;
}
if (ent.GetBuildingPrivilege() == null) continue;
count++;
if (query) {
//foreach (Share x in sharing[ent.OwnerID.ToString()])
foreach (Share x in sharing[iplayer.Id]) {
if (x.netid != (uint)ent.net.ID.Value) continue;
message += $"{count}.{ent.ShortPrefabName}: ";
if (x.sharewith == 0) {
message += Lang("all") + "\n";
}
else {
message += $"{x.sharewith}\n";
}
}
continue;
}
if (populated.Contains((uint)ent.net.ID.Value)) continue;
populated.Add((uint)ent.net.ID.Value);
DoLog($"Adding {ent.ShortPrefabName} ({ent.net.ID}) to sharing list...");
//Message(iplayer, $"Sharing {ent.ShortPrefabName}");
// Entity under control of TC
sharing[iplayer.Id].Add(new Share {
netid = (uint)ent.net.ID.Value, name = ent.ShortPrefabName, sharewith = 0
}
);
}
if (query) {
if (!string.IsNullOrEmpty(message)) {
Message(iplayer, message);
}
return;
}
Message(iplayer, $"Shared {count} entities");
SaveData();
}
[Command("lp")]
private void CmdLootProt(IPlayer iplayer, string command, string[] args) {
if (iplayer == null) return;
if (!iplayer.HasPermission(permLootProtAdmin)) {
Message(iplayer, "notauthorized");
return;
}
string debug = string.Join(",", args);
DoLog($"{command} {debug}");
if (args.Length == 0) {
ShowStatus(iplayer);
return;
}
switch (args[0]) {
case "1" : case "e" : case "true" : case "enable" : enabled = true;
Message(iplayer, "enabled");
break;
case "0" : case "d" : case "false" : case "disable" : enabled = false;
Message(iplayer, "disabled");
break;
case "status" : ShowStatus(iplayer);
break;
case "l" : case "log" : case "logging" : dolog = !dolog;
Message(iplayer, "logging", dolog.ToString());
break;
}
}
#endregion commands
#region hooks
private object CanPickupEntity(BasePlayer player, BaseCombatEntity ent) {
if (player == null || ent == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} picking up {ent?.ShortPrefabName}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent) ? null : (object)false;
}
private object CanPickupLock(BasePlayer player, BaseLock ent) {
if (player == null || ent == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} picking up {ent?.ShortPrefabName}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
return CheckShare(ent, player.userID) ? null : (object)true;
}
private object CanUpdateSign(BasePlayer player, PhotoFrame sign) {
if (player == null || sign == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = sign.GetComponentInParent<BaseEntity>();
DoLog($"Player {player.displayName} painting PhotoFrame {ent?.ShortPrefabName}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)false;
}
private object CanUpdateSign(BasePlayer player, Signage sign) {
if (player == null || sign == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = sign.GetComponentInParent<BaseEntity>();
DoLog($"Player {player.displayName} painting SIGN {ent?.ShortPrefabName}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)false;
}
private object CanLootEntity(BasePlayer player, VendingMachine container) {
if (player == null || container == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = container.GetComponentInParent<BaseEntity>();
if (container.PlayerInfront(player)) {
DoLog($"Player {player.displayName} looting front of {ent?.ShortPrefabName} - allowed");
return null;
}
DoLog($"Player {player.displayName} looting VM {ent?.ShortPrefabName}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)true;
}
private object CanLootEntity(BasePlayer player, ContainerIOEntity container) {
if (player == null || container == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = container?.GetComponentInParent<BaseEntity>();
if (ent == null) return null;
DoLog($"Player {player.displayName} looting ContainerIOEntity {ent.ShortPrefabName} owned by {ent.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) {
DoLog("Admin Bypass");
return null;
}
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)true;
}
private object CanLootEntity(BasePlayer player, StorageContainer container) {
if (player == null || container == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = container?.GetComponentInParent<BaseEntity>();
if (ent == null) return null;
DoLog($"Player {player.displayName} looting StorageContainer {ent.ShortPrefabName} owned by {ent.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) {
DoLog("Admin Bypass");
return null;
}
if (CheckCupboardAccess(ent, player)) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, ent.OwnerID)) return null;
if (CheckShare(ent, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)true;
}
private bool CanLootPVP(BaseCombatEntity entity) {
object pve = NextGenPVE?.CallHook("IsInPVEZone", entity);
return pve != null && pve is bool && !(bool)pve ? configData.Options.allowLootingInPVPAreas : false;
}
private object CanLootEntity(BasePlayer player, DroppedItemContainer container) {
if (player == null || container == null) return null;
if (player.userID.IsSteamId() != true) return null;
BaseEntity ent = container.GetComponentInParent<BaseEntity>();
DoLog($"Player {player.displayName} looting DroppedItemContainer {ent?.ShortPrefabName}:{container.playerSteamID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (!container.OwnerID.IsSteamId()) return null;
if (CanAccess(ent?.ShortPrefabName, player.userID, container.playerSteamID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(ent as BaseCombatEntity) ? null : (object)true;
}
private object CanLootEntity(BasePlayer player, LootableCorpse corpse) {
if (player == null || corpse == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} looting corpse {corpse.name}:{corpse.playerSteamID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(corpse?.ShortPrefabName, player.userID, corpse.playerSteamID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(corpse) ? null : (object)true;
}
private object CanRenameBed(BasePlayer player, SleepingBag bag, string bedName) {
if (player == null || bag == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} renaming SleepingBag {bag.name}:{bag.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
return CanAccess(bag?.ShortPrefabName, player.userID, bag.OwnerID) ? null : (object)true;
}
private object CanAssignBed(BasePlayer player, SleepingBag bag, ulong targetPlayerId) {
if (player == null || bag == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} assigning SleepingBag {bag.name}:{bag.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
return CanAccess(bag?.ShortPrefabName, player.userID, bag.OwnerID) ? null : (object)true;
}
private object CanSetBedPublic(BasePlayer player, SleepingBag bag) {
if (player == null || bag == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} setting SleepingBag {bag.name}:{bag.OwnerID} public");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
return CanAccess(bag?.ShortPrefabName, player.userID, bag.OwnerID) ? null : (object)true;
}
private object CanLootPlayer(BasePlayer target, BasePlayer player) {
if (player == null || target == null) return null;
if (player.userID.IsSteamId() != true) return null;
if (player.userID == target.userID) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} looting Player {target.displayName}:{target.UserIDString}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(target?.ShortPrefabName, player.userID, target.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(target) ? null : (object)false;
}
private object OnOvenToggle(BaseOven oven, BasePlayer player) {
if (player == null || oven == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} toggling {oven?.ShortPrefabName}");
if (configData.Options.OverrideOven) return null;
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CheckCupboardAccess(oven, player)) return null;
if (CanAccess(oven?.ShortPrefabName, player.userID, oven.OwnerID)) return null;
return CheckShare(oven, player.userID) ? null : (object)true;
}
private object OnButtonPress(PressButton button, BasePlayer player) {
if (player == null || button == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} toggling button {button.ShortPrefabName}:{button.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (!button.OwnerID.IsSteamId()) return null;
return CanAccess(button?.ShortPrefabName, player.userID, button.OwnerID) ? null : (object)true;
}
private object CanLock(BasePlayer player, BaseLock baseLock) {
if (player == null || baseLock == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} toggling IOEntity {baseLock.ShortPrefabName}:{baseLock.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (!baseLock.OwnerID.IsSteamId()) return null;
return CanAccess(baseLock?.ShortPrefabName, player.userID, baseLock.OwnerID) ? null : (object)true;
}
private object CanChangeCode(BasePlayer player, CodeLock codeLock, string newCode, bool isGuestCode) {
if (player == null || codeLock == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} toggling IOEntity {codeLock.ShortPrefabName}:{codeLock.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (!codeLock.OwnerID.IsSteamId()) return null;
return CanAccess(codeLock?.ShortPrefabName, player.userID, codeLock.OwnerID) ? null : (object)true;
}
private object OnSwitchToggle(IOEntity entity, BasePlayer player) {
if (player == null || entity == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} toggling IOEntity {entity.ShortPrefabName}:{entity.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (!entity.OwnerID.IsSteamId()) return null;
return CanAccess(entity?.ShortPrefabName, player.userID, entity.OwnerID) ? null : (object)true;
}
private object CanTakeCutting(BasePlayer player, GrowableEntity plant) {
if (player == null || plant == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} looting plant cutting {plant.ShortPrefabName}:{plant.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(plant?.ShortPrefabName, player.userID, plant.OwnerID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(plant) ? null : (object)true;
}
private object OnRemoveDying(GrowableEntity plant, BasePlayer player) {
if (player == null || plant == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} looting dying plant {plant.ShortPrefabName}:{plant.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(plant?.ShortPrefabName, player.userID, plant.OwnerID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(plant) ? null : (object)true;
}
private object OnGrowableGather(GrowableEntity plant, BasePlayer player) {
if (player == null || plant == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName}:{player.UserIDString} looting plant {plant.ShortPrefabName}:{plant.OwnerID}");
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(plant?.ShortPrefabName, player.userID, plant.OwnerID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(plant) ? null : (object)true;
}
private object OnCupboardAuthorize(BuildingPrivlidge privilege, BasePlayer player) {
if (player == null || privilege == null) return null;
if (player.userID.IsSteamId() != true) return null;
DoLog($"Player {player.displayName} attempting to authenticate to a TC.");
if (configData.Options.OverrideTC) return null;
if ((player.IsAdmin || permission.UserHasPermission(player?.UserIDString, permLootProtAdmin)) && configData.Options.AdminBypass) return null;
if (CanAccess(privilege?.ShortPrefabName, player.userID, privilege.OwnerID)) return null;
if (CheckShare(privilege, player.userID)) return null;
return configData.Options.useNextGenPVE && CanLootPVP(privilege) ? null : (object)true;
}
#endregion hooks
#region helpers
// Accept external zone config from DynamicPVP
private bool AddOrUpdateMapping(string key, string rulesetname) {
if (configData.DisabledZones == null || configData.DisabledZones?.Length == 0) {
List<string> newzones = new List<string> {
key
}
;
configData.DisabledZones = newzones.ToArray();
SaveConfig(configData);
return true;
}
if (!configData.DisabledZones.Contains(key)) {
List<string> newzones = new List<string> {
configData.DisabledZones.ToArray()[0], key
}
;
configData.DisabledZones = newzones.ToArray();
SaveConfig(configData);
return true;
}
return false;
}
// Accept external zone config from DynamicPVP
private bool RemoveMapping(string key) {
if (configData.DisabledZones == null || configData.DisabledZones?.Length == 0) {
return true;
}
if (configData.DisabledZones?.Length > 0 && configData.DisabledZones.Contains(key)) {
List<string> newzones = new List<string>();
foreach (string zone in configData.DisabledZones) {
if (zone == key) continue;
newzones.Add(zone);
}
configData.DisabledZones = newzones.ToArray();
SaveConfig(configData);
return true;
}
return true;
}
// From PlayerDatabase
private long ToEpochTime(DateTime dateTime) {
DateTime date = dateTime.ToUniversalTime();
long ticks = date.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks;
return ticks / TimeSpan.TicksPerSecond;
}
private bool CheckCupboardAccess(BaseEntity entity, BasePlayer player) {
if (!configData.Options.TCAuthedUserAccess) return false;
BuildingPrivlidge tc = entity.GetBuildingPrivilege();
if (tc == null) {
DoLog($"CheckCupboardAccess: Unable to find building privilege in range of {entity.ShortPrefabName}.");
return false;
// NO TC to check...}
foreach (ProtoBuf.PlayerNameID p in tc.
// ... [Code preview truncated due to length. Full source in attached file] ...