C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using Facepunch;
using Rust;
namespace Oxide.Plugins
{
[Info("NoEscape", "rustservers.io", "2.0.2", ResourceId = 1394)]
[Description("Prevent commands/actions while raid and/or combat is occuring")]
class NoEscape : RustPlugin
{
#region Setup & Configuration
List<string> blockTypes = new List<string>()
{
"remove",
"tp",
"bank",
"trade",
"recycle",
"shop",
"bgrade",
"build",
"repair",
"upgrade",
"vend",
"kit",
"assignbed",
"craft",
"mailbox"
};
// COMBAT SETTINGS
private bool combatBlock;
private static float combatDuration;
private bool combatOnHitPlayer;
private bool combatOnTakeDamage;
// RAID BLOCK SETTINGS
private bool raidBlock;
private static float raidDuration;
private float raidDistance;
private bool blockOnDamage;
private bool blockOnDestroy;
// RAID-ONLY SETTINGS
private bool ownerCheck;
private bool blockUnowned;
private bool blockAll;
// IGNORES ALL OTHER CHECKS
private bool ownerBlock;
private bool cupboardShare;
private bool friendShare;
private bool clanShare;
private bool clanCheck;
private bool friendCheck;
private bool raiderBlock;
private List<string> raidDamageTypes;
private List<string> combatDamageTypes;
// RAID UNBLOCK SETTINGS
private bool raidUnblockOnDeath;
private bool raidUnblockOnWakeup;
private bool raidUnblockOnRespawn;
// COMBAT UNBLOCK SETTINGS
private bool combatUnblockOnDeath;
private bool combatUnblockOnWakeup;
private bool combatUnblockOnRespawn;
private float cacheTimer;
// MESSAGES
private bool raidBlockNotify;
private bool combatBlockNotify;
private bool useZoneManager;
private bool zoneEnter;
private bool zoneLeave;
internal bool sendUINotification;
internal bool sendChatNotification;
internal bool sendGUIAnnouncementsNotification;
internal bool sendLustyMapNotification;
internal string GUIAnnouncementTintColor = "Red";
internal string GUIAnnouncementTextColor = "White";
internal string LustyMapIcon = "special";
internal float LustyMapDuration = 150f;
private Dictionary<string, RaidZone> zones = new Dictionary<string, RaidZone>();
private Dictionary<string, List<string>> memberCache = new Dictionary<string, List<string>>();
private Dictionary<string, string> clanCache = new Dictionary<string, string>();
private Dictionary<string, List<string>> friendCache = new Dictionary<string, List<string>>();
private Dictionary<string, DateTime> lastClanCheck = new Dictionary<string, DateTime>();
private Dictionary<string, DateTime> lastCheck = new Dictionary<string, DateTime>();
private Dictionary<string, DateTime> lastFriendCheck = new Dictionary<string, DateTime>();
Dictionary<string, bool> prefabBlockCache = new Dictionary<string, bool>();
public static NoEscape plugin;
[PluginReference]
Plugin Clans, Friends, ZoneManager, GUIAnnouncements, LustyMap;
private readonly int cupboardMask = LayerMask.GetMask("Deployed");
private readonly int blockLayer = LayerMask.GetMask("Player (Server)");
private Dictionary<string, bool> _cachedExcludedWeapons = new Dictionary<string, bool>();
List<string> blockedPrefabs = new List<string>()
{
"door",
"window.bars",
"floor.ladder.hatch",
"floor.frame",
"wall.frame",
"shutter",
"external"
};
List<string> exceptionPrefabs = new List<string>()
{
"ladder.wooden"
};
List<string> exceptionWeapons = new List<string>()
{
"torch"
};
private List<string> GetDefaultRaidDamageTypes()
{
return new List<DamageType>()
{
DamageType.Bullet,
DamageType.Blunt,
DamageType.Stab,
DamageType.Slash,
DamageType.Explosion,
DamageType.Heat,
}.Select(x => x.ToString()).ToList<string>();
}
private List<string> GetDefaultCombatDamageTypes()
{
return new List<DamageType>()
{
DamageType.Bullet,
DamageType.Arrow,
DamageType.Blunt,
DamageType.Stab,
DamageType.Slash,
DamageType.Explosion,
DamageType.Heat,
DamageType.ElectricShock,
}.Select(x => x.ToString()).ToList<string>();
}
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);
protected override void LoadDefaultConfig()
{
Config["VERSION"] = Version.ToString();
// RAID SETTINGS
Config["Raid", "Block", "enabled"] = true;
Config["Raid", "Block", "duration"] = 300f; // 5 minutes
Config["Raid", "Block", "distance"] = 100f;
Config["Raid", "Block", "notify"] = true;
Config["Raid", "Block", "damageTypes"] = GetDefaultRaidDamageTypes();
Config["Raid", "Block", "includePrefabs"] = blockedPrefabs;
Config["Raid", "Block", "excludePrefabs"] = exceptionPrefabs;
Config["Raid", "Block", "excludeWeapons"] = exceptionWeapons;
Config["Raid", "BlockWhen", "damage"] = true;
Config["Raid", "BlockWhen", "destroy"] = true;
Config["Raid", "BlockWhen", "unowned"] = false;
Config["Raid", "BlockWho", "everyone"] = true;
Config["Raid", "BlockWho", "owner"] = false;
Config["Raid", "BlockWho", "cupboardAuthorized"] = false;
Config["Raid", "BlockWho", "clan"] = false;
Config["Raid", "BlockWho", "friends"] = false;
Config["Raid", "BlockWho", "raider"] = false;
Config["Raid", "BlockExcept", "owner"] = true;
Config["Raid", "BlockExcept", "friends"] = false;
Config["Raid", "BlockExcept", "clan"] = false;
Config["Raid", "Zone", "enabled"] = false;
Config["Raid", "Zone", "enter"] = true;
Config["Raid", "Zone", "leave"] = false;
Config["Raid", "Map", "enabled"] = false;
Config["Raid", "Map", "icon"] = "special";
Config["Raid", "Map", "duration"] = 150f;
Config["Raid", "UnblockWhen", "death"] = true;
Config["Raid", "UnblockWhen", "wakeup"] = false;
Config["Raid", "UnblockWhen", "respawn"] = true;
// COMBAT SETTINGS
Config["Combat", "Block", "enabled"] = false;
Config["Combat", "Block", "duration"] = 180f; // 3 minutes
Config["Combat", "Block", "notify"] = true;
Config["Combat", "Block", "damageTypes"] = GetDefaultCombatDamageTypes();
Config["Combat", "BlockWhen", "giveDamage"] = true;
Config["Combat", "BlockWhen", "takeDamage"] = true;
Config["Combat", "UnblockWhen", "death"] = true;
Config["Combat", "UnblockWhen", "wakeup"] = false;
Config["Combat", "UnblockWhen", "respawn"] = true;
Config["Settings", "cacheMinutes"] = 1f;
Config["Settings", "Block", "Types"] = blockTypes;
Config["Notifications", "UI"] = true;
Config["Notifications", "Chat"] = true;
Config["Notifications", "GUIAnnouncements", "enabled"] = false;
Config["Notifications", "GUIAnnouncements", "backgroundColor"] = "Red";
Config["Notifications", "GUIAnnouncements", "textColor"] = "White";
Config["VERSION"] = Version.ToString();
}
void Loaded()
{
LoadMessages();
}
void Unload()
{
if (useZoneManager)
foreach (var zone in zones.ToList())
EraseZone(zone.Value.zoneid);
var objects = GameObject.FindObjectsOfType(typeof(RaidBlock));
if (objects != null)
foreach (var gameObj in objects)
if (!((RaidBlock)gameObj).Active)
GameObject.Destroy(gameObj);
objects = GameObject.FindObjectsOfType(typeof(CombatBlock));
if (objects != null)
foreach (var gameObj in objects)
if (!((CombatBlock)gameObj).Active)
GameObject.Destroy(gameObj);
}
void LoadMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
{ "Raid Blocked Message", "You may not do that while raid blocked ({time})" },
{ "Combat Blocked Message", "You may do that while a in combat ({time})" },
{ "Raid Block Complete", "You are no longer raid blocked." },
{ "Combat Block Complete", "You are no longer combat blocked." },
{ "Raid Block Notifier", "You are raid blocked for {time}" },
{ "Combat Block Notifier", "You are combat blocked for {time}" },
{ "Combat Block UI Message", "COMBAT BLOCK" },
{ "Raid Block UI Message", "RAID BLOCK" },
{ "Unit Seconds", "second(s)" },
{ "Unit Minutes", "minute(s)" },
{ "Prefix", string.Empty }
}, this);
}
void CheckConfig()
{
if (Config["VERSION"] == null)
{
// FOR COMPATIBILITY WITH INITIAL VERSIONS WITHOUT VERSIONED CONFIG
ReloadConfig();
}
else if (GetConfig<string>("VERSION", string.Empty) != Version.ToString())
{
// ADDS NEW, IF ANY, CONFIGURATION OPTIONS
ReloadConfig();
}
}
protected void ReloadConfig()
{
Config["VERSION"] = Version.ToString();
// NEW CONFIGURATION OPTIONS HERE
// END NEW CONFIGURATION OPTIONS
PrintToConsole("Upgrading configuration file");
SaveConfig();
}
void OnServerInitialized()
{
NoEscape.plugin = this;
permission.RegisterPermission("noescape.disable", this);
blockTypes = GetConfig("Settings", "Block", "Types", blockTypes);
foreach (string command in blockTypes)
{
permission.RegisterPermission("noescape.raid." + command + "block", this);
permission.RegisterPermission("noescape.combat." + command + "block", this);
}
CheckConfig();
// RAID SETTINGS
raidBlock = GetConfig("Raid", "Block", "enabled", true);
raidDuration = GetConfig("Raid", "Block", "duration", 300f);
raidDistance = GetConfig("Raid", "Block", "distance", 100f);
raidBlockNotify = GetConfig("Raid", "Block", "notify", true);
raidDamageTypes = GetConfig("Raid", "Block", "damageTypes", GetDefaultRaidDamageTypes());
blockedPrefabs = GetConfig("Raid", "Block", "includePrefabs", blockedPrefabs);
exceptionPrefabs = GetConfig("Raid", "Block", "excludePrefabs", exceptionPrefabs);
exceptionWeapons = GetConfig("Raid", "Block", "excludeWeapons", exceptionWeapons);
blockOnDamage = GetConfig("Raid", "BlockWhen", "damage", true);
blockOnDestroy = GetConfig("Raid", "BlockWhen", "destroy", true);
blockUnowned = GetConfig("Raid", "BlockWhen", "unowned", false);
blockAll = GetConfig("Raid", "BlockWho", "everyone", true);
ownerBlock = GetConfig("Raid", "BlockWho", "owner", false);
friendShare = GetConfig("Raid", "BlockWho", "friends", false);
clanShare = GetConfig("Raid", "BlockWho", "clan", false);
cupboardShare = GetConfig("Raid", "BlockWho", "cupboardAuthorized", false);
raiderBlock = GetConfig("Raid", "BlockWho", "raider", false);
ownerCheck = GetConfig("Raid", "BlockExcept", "owner", true);
friendCheck = GetConfig("Raid", "BlockExcept", "friends", false);
clanCheck = GetConfig("Raid", "BlockExcept", "clan", false);
useZoneManager = GetConfig("Raid", "Zone", "enabled", false);
zoneEnter = GetConfig("Raid", "Zone", "enter", true);
zoneLeave = GetConfig("Raid", "Zone", "leave", false);
sendLustyMapNotification = GetConfig("Raid", "Map", "enabled", false);
LustyMapIcon = GetConfig("Raid", "Map", "icon", "special");
LustyMapDuration = GetConfig("Raid", "Map", "duration", 150f);
raidUnblockOnDeath = GetConfig("Raid", "UnblockWhen", "death", true);
raidUnblockOnWakeup = GetConfig("Raid", "UnblockWhen", "wakeup", false);
raidUnblockOnRespawn = GetConfig("Raid", "UnblockWhen", "respawn", true);
// COMBAT SETTINGS
combatBlock = GetConfig("Combat", "Block", "enabled", false);
combatDuration = GetConfig("Combat", "Block", "duration", 180f);
combatBlockNotify = GetConfig("Combat", "Block", "notify", true);
combatDamageTypes = GetConfig("Combat", "Block", "damageTypes", GetDefaultCombatDamageTypes());
combatOnHitPlayer = GetConfig("Combat", "BlockWhen", "giveDamage", true);
combatOnTakeDamage = GetConfig("Combat", "BlockWhen", "takeDamage", true);
combatUnblockOnDeath = GetConfig("Combat", "UnblockWhen", "death", true);
combatUnblockOnWakeup = GetConfig("Combat", "UnblockWhen", "wakeup", false);
combatUnblockOnRespawn = GetConfig("Combat", "UnblockWhen", "respawn", true);
cacheTimer = GetConfig("Settings", "cacheMinutes", 1f);
sendUINotification = GetConfig("Notifications", "UI", true);
sendChatNotification = GetConfig("Notifications", "Chat", true);
sendGUIAnnouncementsNotification = GetConfig("Notifications", "GUIAnnouncements", "enabled", false);
GUIAnnouncementTintColor = GetConfig("Notifications", "GUIAnnouncements", "backgroundColor", "Red");
GUIAnnouncementTextColor = GetConfig("Notifications", "GUIAnnouncements", "textColor", "White");
if ((clanShare || clanCheck) && !Clans)
{
clanShare = false;
clanCheck = false;
PrintWarning("Clans not found! All clan options disabled.Cannot use clan options without this plugin.http://oxidemod.org/plugins/clans.2087");
}
if (friendShare && !Friends)
{
friendShare = false;
friendCheck = false;
PrintWarning("Friends not found! All friend options disabled.Cannot use friend options without this plugin.http://oxidemod.org/plugins/friends-api.686");
}
if (useZoneManager && !ZoneManager)
{
useZoneManager = false;
PrintWarning("ZoneManager not found! All zone options disabled.Cannot use zone options without this plugin.http://oxidemod.org/plugins/zones-manager.739");
}
if (sendGUIAnnouncementsNotification && !GUIAnnouncements)
{
sendGUIAnnouncementsNotification = false;
PrintWarning("GUIAnnouncements not found! GUI announcement option disabled.Cannot use gui announcement integration without this plugin.http://oxidemod.org/plugins/gui-announcements.1222");
}
if (sendLustyMapNotification && !LustyMap)
{
sendLustyMapNotification = false;
PrintWarning("LustyMap not found! LustyMap notification option disabled.Cannot use LustyMap integration without this plugin.http://oxidemod.org/plugins/lustymap.1333");
}
if (sendLustyMapNotification && LustyMap && LustyMapDuration <= 0)
{
PrintWarning("LustyMap icon duration is zero, no icon will be displayed");
}
UnsubscribeHooks();
}
void UnsubscribeHooks()
{
if (!blockOnDestroy && !raidUnblockOnDeath && !combatUnblockOnDeath)
Unsubscribe("OnEntityDeath");
if (!raidUnblockOnWakeup && !combatUnblockOnWakeup)
Unsubscribe("OnPlayerSleepEnded");
if (!combatOnTakeDamage && !combatOnHitPlayer)
Unsubscribe("OnPlayerAttack");
if (!blockOnDamage)
Unsubscribe("OnEntityTakeDamage");
if (!blockTypes.Contains("repair"))
Unsubscribe("OnStructureRepair");
if (!blockTypes.Contains("upgrade"))
Unsubscribe("OnStructureUpgrade");
if (!blockTypes.Contains("mailbox"))
Unsubscribe("CanUseMailbox");
if (!blockTypes.Contains("vend"))
Unsubscribe("CanUseVending");
if (!blockTypes.Contains("build"))
Unsubscribe("CanBuild");
if (!blockTypes.Contains("assignbed"))
Unsubscribe("CanAssignBed");
if (!blockTypes.Contains("craft"))
Unsubscribe("CanCraft");
}
#endregion
#region Classes
public class RaidZone
{
public string zoneid;
public Vector3 position;
public Timer timer;
public RaidZone(string zoneid, Vector3 position)
{
this.zoneid = zoneid;
this.position = position;
}
public float Distance(RaidZone zone)
{
return Vector3.Distance(position, zone.position);
}
public float Distance(Vector3 pos)
{
return Vector3.Distance(position, pos);
}
public RaidZone ResetTimer()
{
if (timer is Timer && !timer.Destroyed)
timer.Destroy();
return this;
}
}
public abstract class BlockBehavior : MonoBehaviour
{
protected BasePlayer player;
public DateTime lastBlock = DateTime.MinValue;
public DateTime lastNotification = DateTime.MinValue;
internal DateTime lastUINotification = DateTime.MinValue;
internal Timer timer;
internal Action notifyCallback;
internal string iconUID;
internal abstract float Duration { get; }
internal abstract CuiRectTransformComponent NotificationWindow { get; }
internal abstract string notifyMessage { get; }
internal string BlockName
{
get
{
return GetType().Name;
}
}
public bool Active
{
get
{
if (lastBlock > DateTime.MinValue)
{
TimeSpan ts = DateTime.Now - lastBlock;
if (ts.TotalSeconds < Duration)
{
return true;
}
}
GameObject.Destroy(this);
return false;
}
}
void Awake()
{
player = GetComponent<BasePlayer>();
}
void Destroy()
{
Stop();
}
void Update()
{
if (!plugin.sendUINotification)
return;
bool send = false;
if (lastUINotification == DateTime.MinValue)
{
lastUINotification = DateTime.Now;
send = true;
}
else
{
TimeSpan ts = DateTime.Now - lastUINotification;
if (ts.TotalSeconds > 2)
{
send = true;
}
else
{
send = false;
}
}
if (player is BasePlayer && player.IsConnected)
{
if (!Active)
{
CuiHelper.DestroyUi(player, "BlockMsg" + BlockName);
}
if (send && Active)
{
lastUINotification = DateTime.Now;
SendGUI();
}
}
}
public void Stop()
{
if (notifyCallback is Action)
notifyCallback.Invoke();
if (timer is Timer && !timer.Destroyed)
timer.Destroy();
if (plugin.sendUINotification && player is BasePlayer && player.IsConnected)
CuiHelper.DestroyUi(player, "BlockMsg" + BlockName);
GameObject.Destroy(this);
}
public void Notify(Action callback)
{
if (plugin.sendUINotification)
SendGUI();
notifyCallback = callback;
if (timer is Timer && !timer.Destroyed)
timer.Destroy();
timer = plugin.timer.In(Duration, callback);
}
private string FormatTime(TimeSpan ts)
{
if (ts.Days > 0)
return string.Format("{0}D, {1}H", ts.Days, ts.Hours);
if (ts.Hours > 0)
return string.Format("{0}H {1}M", ts.Hours, ts.Minutes);
return string.Format("{0}M {1}S", ts.Minutes, ts.Seconds);
}
void SendGUI()
{
TimeSpan ts = lastBlock.AddSeconds(Duration) - DateTime.Now;
string countDown = FormatTime(ts);
CuiHelper.DestroyUi(player, "BlockMsg" + BlockName);
var elements = new CuiElementContainer();
var BlockMsg = elements.Add(new CuiPanel
{
Image =
{
Color = "0.95 0 0.02 0.67"
},
RectTransform =
{
AnchorMax = NotificationWindow.AnchorMax,
AnchorMin = NotificationWindow.AnchorMin
}
}, "Hud", "BlockMsg" + BlockName);
elements.Add(new CuiElement
{
Parent = BlockMsg,
Components =
{
new CuiRawImageComponent
{
Sprite = "assets/icons/explosion.png",
Color = "0.95 0 0.02 0.67"
},
new CuiRectTransformComponent
{
AnchorMin = "0 0",
AnchorMax = "0.13 1"
}
}
});
elements.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0.15 0",
AnchorMax = "0.82 1"
},
Text =
{
Text = notifyMessage,
FontSize = 11,
Align = TextAnchor.MiddleLeft,
}
}, BlockMsg);
elements.Add(new CuiElement
{
Name = "TimerPanel",
Parent = BlockMsg,
Components =
{
new CuiImageComponent
{
Color = "0 0 0 0.64",
ImageType = UnityEngine.UI.Image.Type.Filled
},
new CuiRectTransformComponent
{
AnchorMin = "0.73 0",
AnchorMax = "1 1"
}
}
});
elements.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0",
AnchorMax = "1 1"
},
Text =
{
Text = countDown,
FontSize = 12,
Align = TextAnchor.MiddleCenter,
}
}, "TimerPanel");
CuiHelper.AddUi(player, elements);
}
}
public class CombatBlock : BlockBehavior
{
internal override float Duration
{
get
{
return combatDuration;
}
}
internal override string notifyMessage
{
get { return NoEscape.GetMsg("Combat Block UI Message", player); }
}
private CuiRectTransformComponent _notificationWindow = null;
internal override CuiRectTransformComponent NotificationWindow
{
get
{
if (_notificationWindow != null)
{
return _notificationWindow;
}
return _notificationWindow = new CuiRectTransformComponent()
{
AnchorMin = "0.87 0.35",
AnchorMax = "0.99 0.38"
};
}
}
}
public class RaidBlock : BlockBehavior
{
internal override float Duration
{
get
{
return raidDuration;
}
}
internal override string notifyMessage
{
get { return NoEscape.GetMsg("Raid Block UI Message", player); }
}
private CuiRectTransformComponent _notificationWindow = null;
internal override CuiRectTransformComponent NotificationWindow
{
get
{
if (_notificationWindow != null)
{
return _notificationWindow;
}
return _notificationWindow = new CuiRectTransformComponent()
{
AnchorMin = "0.87 0.39",
AnchorMax = "0.99 0.42"
};
}
}
}
#endregion
#region Oxide Hooks
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo)
{
if (!blockOnDamage || !raidBlock)
return;
if (hitInfo == null || hitInfo.WeaponPrefab == null || hitInfo.Initiator == null || !IsEntityBlocked(entity) || hitInfo.Initiator.transform == null || hitInfo.Initiator.transform.position == null)
return;
if (!IsRaidDamage(hitInfo.damageTypes.GetMajorityDamageType()))
return;
if (IsExcludedWeapon(hitInfo.WeaponPrefab.ShortPrefabName))
return;
StructureAttack(entity, hitInfo.Initiator, hitInfo.WeaponPrefab.ShortPrefabName, hitInfo.HitPositionWorld);
}
void OnPlayerAttack(BasePlayer attacker, HitInfo hitInfo)
{
if (!combatBlock || !(hitInfo.HitEntity is BasePlayer))
return;
if (!IsCombatDamage(hitInfo.damageTypes.GetMajorityDamageType()))
return;
BasePlayer target = hitInfo.HitEntity as BasePlayer;
if (combatOnTakeDamage)
StartCombatBlocking(target);
if (combatOnHitPlayer)
StartCombatBlocking(attacker);
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo)
{
if (blockOnDestroy && raidBlock)
{
if (hitInfo == null || hitInfo.WeaponPrefab == null || hitInfo.Initiator == null || !IsRaidDamage(hitInfo.damageTypes.GetMajorityDamageType()) || !IsEntityBlocked(entity))
return;
StructureAttack(entity, hitInfo.Initiator, hitInfo.WeaponPrefab.ShortPrefabName, hitInfo.HitPositionWorld);
}
if (entity.ToPlayer() == null)
return;
var player = entity.ToPlayer();
RaidBlock raidBlocker;
if (raidBlock && raidUnblockOnDeath && TryGetBlocker<RaidBlock>(player, out raidBlocker))
{
timer.In(0.3f, delegate()
{
raidBlocker.Stop();
});
}
CombatBlock combatBlocker;
if (combatBlock && combatUnblockOnDeath && TryGetBlocker<CombatBlock>(player, out combatBlocker))
{
timer.In(0.3f, delegate()
{
combatBlocker.Stop();
});
}
}
void OnPlayerSleepEnded(BasePlayer player)
{
RaidBlock raidBlocker;
if (raidBlock && raidUnblockOnWakeup && TryGetBlocker<RaidBlock>(player, out raidBlocker))
{
timer.In(0.3f, delegate()
{
raidBlocker.Stop();
});
}
CombatBlock combatBlocker;
if (combatBlock && combatUnblockOnWakeup && TryGetBlocker<CombatBlock>(player, out combatBlocker))
{
timer.In(0.3f, delegate()
{
combatBlocker.Stop();
});
}
}
void OnPlayerRespawned(BasePlayer player)
{
if (raidBlock && raidUnblockOnRespawn && IsRaidBlocked(player))
{
timer.In(0.3f, delegate()
{
StopBlocking(player);
});
}
if (combatBlock && combatUnblockOnRespawn && IsCombatBlocked(player))
{
timer.In(0.3f, delegate()
{
StopBlocking(player);
});
}
}
#endregion
#region Block Handling
void StructureAttack(BaseEntity targetEntity, BaseEntity sourceEntity, string weapon, Vector3 hitPosition)
{
BasePlayer source = null;
if (sourceEntity.ToPlayer() is BasePlayer)
source = sourceEntity.ToPlayer();
else
{
ulong ownerID = sourceEntity.OwnerID;
if (ownerID.IsSteamId())
source = BasePlayer.FindByID(ownerID);
else
return;
}
if (source == null)
return;
List<string> sourceMembers = null;
if (targetEntity.OwnerID.IsSteamId() || (blockUnowned && !targetEntity.OwnerID.IsSteamId()))
{
if (clanCheck || friendCheck)
sourceMembers = getFriends(source.UserIDString);
if (blockAll)
{
BlockAll(source, targetEntity.transform.position, sourceMembers);
}
else
{
if (ownerBlock)
OwnerBlock(source, sourceEntity, targetEntity.OwnerID, targetEntity.transform.position, sourceMembers);
if (raiderBlock)
RaiderBlock(source, targetEntity.OwnerID, targetEntity.transform.position, sourceMembers);
}
}
}
void BlockAll(BasePlayer source, Vector3 position, List<string> sourceMembers = null)
{
StartRaidBlocking(source, position);
var nearbyTargets = Pool.GetList<BasePlayer>();
Vis.Entities<BasePlayer>(position, raidDistance, nearbyTargets, blockLayer);
if (nearbyTargets.Count > 0)
{
RaidBlock blocker;
foreach (BasePlayer nearbyTarget in nearbyTargets)
{
if (TryGetBlocker<RaidBlock>(nearbyTarget, out blocker) && blocker.Active)
{
StartRaidBlocking(nearbyTarget, position);
}
else if (ShouldBlockEscape(nearbyTarget.userID, source.userID, sourceMembers))
{
StartRaidBlocking(nearbyTarget, position);
}
}
}
Pool.FreeList<BasePlayer>(ref nearbyTargets);
}
void OwnerBlock(BasePlayer source, BaseEntity sourceEntity, ulong target, Vector3 position, List<string> sourceMembers = null)
{
if (!ShouldBlockEscape(target, source.userID, sourceMembers))
return;
var targetMembers = new List<string>();
if (clanShare || friendShare)
targetMembers = getFriends(target.ToString());
var nearbyTargets = Pool.GetList<BasePlayer>();
Vis.Entities<BasePlayer>(position, raidDistance, nearbyTargets, blockLayer);
if (cupboardShare)
sourceMembers = CupboardShare(target.ToString(), position, sourceEntity, sourceMembers);
if (nearbyTargets.Count > 0)
foreach (BasePlayer nearbyTarget in nearbyTargets)
if (nearbyTarget.userID == target || (targetMembers != null && targetMembers.Contains(nearbyTarget.UserIDString)))
StartRaidBlocking(nearbyTarget, position);
Pool.FreeList<BasePlayer>(ref nearbyTargets);
}
List<string> CupboardShare(string owner, Vector3 position, BaseEntity sourceEntity, List<string> sourceMembers = null)
{
var nearbyCupboards = Pool.GetList<BuildingPrivlidge>();
Vis.Entities<BuildingPrivlidge>(position, raidDistance, nearbyCupboards, cupboardMask);
if (sourceMembers == null)
sourceMembers = new List<string>();
List<string> cupboardMembers = new List<string>();
var sourcePlayer = sourceEntity as BasePlayer;
if (sourcePlayer != null)
{
foreach (var cup in nearbyCupboards)
{
if (cup.IsAuthed(sourcePlayer))
{
bool ownerOrFriend = false;
if (owner == cup.OwnerID.ToString())
ownerOrFriend = true;
foreach (var member in sourceMembers)
{
if (member == cup.OwnerID.ToString())
ownerOrFriend = true;
}
if (ownerOrFriend)
foreach (var proto in cup.authorizedPlayers)
if (!sourceMembers.Contains(proto.userid.ToString()))
cupboardMembers.Add(proto.userid.ToString());
}
}
}
sourceMembers.AddRange(cupboardMembers);
Pool.FreeList<BuildingPrivlidge>(ref nearbyCupboards);
return sourceMembers;
}
void RaiderBlock(BasePlayer source, ulong target, Vector3 position, List<string> sourceMembers = null)
{
if (!ShouldBlockEscape(target, source.userID, sourceMembers))
return;
var targetMembers = new List<string>();
if ((clanShare || friendShare) && sourceMembers == null)
sourceMembers = getFriends(source.UserIDString);
var nearbyTargets = Pool.GetList<BasePlayer>();
Vis.Entities<BasePlayer>(position, raidDistance, nearbyTargets, blockLayer);
if (nearbyTargets.Count > 0)
foreach (BasePlayer nearbyTarget in nearbyTargets)
if (nearbyTarget == source || (sourceMembers != null && sourceMembers.Contains(nearbyTarget.UserIDString)))
StartRaidBlocking(nearbyTarget, position);
Pool.FreeList<BasePlayer>(ref nearbyTargets);
}
#endregion
#region API
bool IsBlocked(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer)
{
return IsBlocked(player);
}
return false;
}
bool IsBlocked(BasePlayer target)
{
if (IsBlocked<RaidBlock>(target) || IsBlocked<CombatBlock>(target))
return true;
return false;
}
public bool IsBlocked<T>(BasePlayer target) where T : BlockBehavior
{
T behavior;
if (TryGetBlocker<T>(target, out behavior) && behavior.Active)
return true;
return false;
}
bool IsRaidBlocked(BasePlayer target)
{
return IsBlocked<RaidBlock>(target);
}
bool IsCombatBlocked(BasePlayer target)
{
return IsBlocked<CombatBlock>(target);
}
bool IsEscapeBlocked(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer)
{
return IsBlocked(player);
}
return false;
}
bool IsRaidBlocked(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer)
{
return IsBlocked<RaidBlock>(player);
}
return false;
}
bool IsCombatBlocked(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer)
{
return IsBlocked<CombatBlock>(player);
}
return false;
}
bool ShouldBlockEscape(ulong target, ulong source, List<string> sourceMembers = null)
{
if (target == source)
{
if ((ownerBlock || raiderBlock) && (!ownerCheck))
return true;
return false;
}
if (sourceMembers is List<string> && sourceMembers.Count > 0 && sourceMembers.Contains(target.ToString()))
return false;
return true;
}
//[ChatCommand("bblocked")]
//void cmdBBlocked(BasePlayer player, string command, string[] args)
//{
// StartCombatBlocking(player);
// StartRaidBlocking(player);
//}
void StartRaidBlocking(BasePlayer target, bool createZone = true)
{
StartRaidBlocking(target, target.transform.position, createZone);
}
void StartRaidBlocking(BasePlayer target, Vector3 position, bool createZone = true)
{
if (HasPerm(target.UserIDString, "disable"))
{
return;
}
if (position == null)
{
position = target.transform.position;
}
if (target.gameObject == null)
return;
var raidBlocker = target.gameObject.GetComponent<RaidBlock>();
if (raidBlocker == null)
{
raidBlocker = target.gameObject.AddComponent<RaidBlock>();
}
raidBlocker.lastBlock = DateTime.Now;
if (raidBlockNotify)
SendBlockMessage(target, raidBlocker, "Raid Block Notifier", "Raid Block Complete");
if (useZoneManager && createZone && (zoneEnter || zoneLeave))
CreateRaidZone(position);
}
void StartCombatBlocking(BasePlayer target)
{
if (HasPerm(target.UserIDString, "disable"))
{
return;
}
if (target.gameObject == null)
return;
var combatBlocker = target.gameObject.GetComponent<CombatBlock>();
if (combatBlocker == null)
{
combatBlocker = target.gameObject.AddComponent<CombatBlock>();
}
combatBlocker.lastBlock = DateTime.Now;
if (combatBlockNotify)
SendBlockMessage(target, combatBlocker, "Combat Block Notifier", "Combat Block Complete");
}
void StopBlocking(BasePlayer target)
{
if (IsRaidBlocked(target))
StopBlocking<RaidBlock>(target);
if (IsCombatBlocked(target))
StopBlocking<CombatBlock>(target);
}
public void StopBlocking<T>(BasePlayer target) where T : BlockBehavior
{
if (target.gameObject == null)
return;
var block = target.gameObject.GetComponent<T>();
if (block is BlockBehavior)
block.Stop();
}
void ClearRaidBlockingS(string target)
{
StopRaidBlocking(target);
}
void StopRaidBlocking(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer && IsRaidBlocked(player))
StopBlocking<RaidBlock>(player);
}
void StopCombatBlocking(string target)
{
var player = BasePlayer.Find(target);
if (player is BasePlayer && IsRaidBlocked(player))
StopBlocking<CombatBlock>(player);
}
void ClearCombatBlocking(string target)
{
StopCombatBlocking(target);
}
#endregion
#region Zone Handling
void EraseZone(string zoneid)
{
ZoneManager.CallHook("EraseZone", zoneid);
zones.Remove(zoneid);
}
void ResetZoneTimer(RaidZone zone)
{
zone.ResetTimer().timer = timer.In(raidDuration, delegate()
{
EraseZone(zone.zoneid);
});
}
void CreateRaidZone(Vector3 position)
{
var zoneid = position.ToString();
RaidZone zone;
if (zones.TryGetValue(zoneid, out zone))
{
ResetZoneTimer(zone);
return;
}
else
{
foreach (var nearbyZone in zones)
{
if (nearbyZone.Value.Distance(position) < (raidDistance / 2))
{
ResetZoneTimer(nearbyZone.Value);
return;
}
}
}
ZoneManager.CallHook("CreateOrUpdateZone", zoneid, new string[]
{
"radius",
raidDistance.ToString()
}, position);
zones.Add(zoneid, zone = new RaidZone(zoneid, position));
ResetZoneTimer(zone);
}
[HookMethod("OnEnterZone")]
void OnEnterZone(string zoneid, BasePlayer player)
{
if (!zoneEnter)
return;
if (!zones.ContainsKey(zoneid))
return;
StartRaidBlocking(player, player.transform.position, false);
}
[HookMethod("OnExitZone")]
void OnExitZone(string zoneid, BasePlayer player)
{
if (!zoneLeave)
return;
if (!zones.ContainsKey(zoneid))
return;
if (IsRaidBlocked(player))
{
StopBlocking<RaidBlock>(player);
}
}
#endregion
#region Friend/Clan Integration
public List<string> getFriends(string player)
{
var players = new List<string>();
if (player == null)
return players;
if (friendShare || friendCheck)
{
var friendList = getFriendList(player);
if (friendList != null)
players.AddRange(friendList);
}
if (clanShare || clanCheck)
{
var members = getClanMembers(player);
if (members != null)
players.AddRange(members);
}
return players;
}
public List<string> getFriendList(string player)
{
object friends_obj = null;
DateTime lastFriendCheckPlayer;
var players = new List<string>();
if (lastFriendCheck.TryGetValue(player, out lastFriendCheckPlayer))
{
if ((DateTime.Now - lastFriendCheckPlayer).TotalMinutes <= cacheTimer && friendCache.TryGetValue(player, out players))
{
return players;
}
else
{
friends_obj = Friends?.CallHook("IsFriendOfS", player);
lastFriendCheck[player] = DateTime.Now;
}
}
else
{
friends_obj = Friends?.CallHook("IsFriendOfS", player);
lastFriendCheck.Add(player, DateTime.Now);
}
if (friends_obj == null)
return players;
string[] friends = friends_obj as string[];
foreach (string fid in friends)
players.Add(fid);
if (friendCache.ContainsKey(player))
friendCache[player] = players;
else
friendCache.Add(player, players);
return players;
}
public List<string> getClanMembers(string player)
{
string tag = null;
DateTime lastClanCheckPlayer;
string lastClanCached;
if (lastClanCheck.TryGetValue(player, out lastClanCheckPlayer) && clanCache.TryGetValue(player, out lastClanCached))
{
if ((DateTime.Now - lastClanCheckPlayer).TotalMinutes <= cacheTimer)
// ... [Code preview truncated due to length. Full source in attached file] ...