C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Facepunch.Extend;
using HarmonyLib;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;
using static UnityEngine.Object;
using Quaternion = UnityEngine.Quaternion;
using Vector3 = UnityEngine.Vector3;
//==================================================
//CHANGELOG
//==================================================
//1.0.6 => 05/11/2024
// - Fixed: Duplicated message in chat with auto lock pin code
//1.0.7 => 08/11/2024
// - Fixed: Double printing of pin messages in chat
//1.0.8 => 10/11/2024
// - Added: Auto closing system, Door Closer
// - Fixed: Default player setting data
//1.0.9 => 11/11/2024
// - Added: AutoDoors plugin integration: Prevents automatic door closing if a Door Closer is present
// - Fixed: Code Lock unlock fix
//1.1.0 => 14/11/2024
// - Fixed: Vehicle auto lock
//1.1.1 => 22/11/2024
// - Fixed: Invalid code with leading 0s
// - Fixed: Modular car guest code lock
//1.1.2 => 23/11/2024
// - Added: Support for Car Chassis
//1.1.3 => 24/11/2024
// - Fixed: Key Lock Clan/Team sharing
//1.1.4 => 30/11/2024
// - Added: New command /loker and /closer to add lock and door closer manually
//1.1.5 => 15/12/2024
// - Updated: Configuration file for default player settings
// - Added: Added command to change the closing time of the individual Door Closer you are looking at
// - Improved: Code refactoring
// - Fixed: Lock position for players who have the [ultimatelocker.autolock.nolockrequired] role
//1.1.6 => 15/12/2024
// - Fixed: bug fix
//1.1.7 => 16/12/2024
// - Fixed: Shared lock for offline or death players
//1.1.8 => 17/12/2024
// - Added: Message when placing a door closer via the command
// - Fixed: Loss of setted custom time for single door closer after server restart
// - Fixed: Issue where door closers were always placed if added via command, even if a door closer was already present
//1.1.9 => 22/12/2024
// - Fixed: Vanish (CanUseLockedEntity) hook conflict
// - Update: disable lock/unlock effect if player is invisible or flying
//1.2.0 => 30/01/2025
// - Added: Lock and auto closer support for windows: Wood Shutters
// - Improved: Door closer positioning
// - Added: Automatic lock closing when dismount of the vehicle
//1.2.1 => 07/02/2025
// - Fixed: Horse lock after Rust update (06/02/2025)
//1.2.2 => 09/02/2025
// - Fixed: Horse prefab name
//1.2.3 => 10/02/2025
// - Added: Door Closer for Medieval door
// - Added: Code Lock support for Medieval entities: Mounted Ballista, Battering Ram, Catapult, Siege Tower, Ballista
// - Added: Medieval entities block usage: opening/closing doors, reloading/firing ammo, mounting, driving, pushing, pulling, etc...//1.2.4 => 13/02/2025
// - Added: Codelock support for Medieval Large Wood Box
//1.2.5 => 27/02/2025
// - Fix: Integration with plugins [Backpack] and [Bank]
//1.2.6 => 03/03/2025
// - Added: Player Auto Closing default settings
// - Added: New configuration option to resync all player settings to the default settings configured
// - Added: New configuration option to Force share locks with clan/team members.//1.2.7 => 08/03/2025
// - Added: New lockable entities [Triangle Planter Box, Triangle Rail Road Planter, Single Plant Pot, Beehive, Chicken Coop, Cooking Workbench, Engineering Workbench, Hopper]
//1.2.8 => 12/03/2025
// - Added: New translations [es, es-ES, fr, de, nl, tr, ru, uk, zh-CN]
//1.2.9 => 19/03/2025
// - Fix: Russian translation
// - Added: Added property to enable only use of key locks
//1.3.0 => 22/03/2025
// - Added: New translation [zh-TW] Traditional Chinese
//1.3.1 => 16/04/2025
// - Added: Configuration to disable door closer removal
// - Fixed: bug fix
//1.3.2 => 01/05/2025
// - Fixed: Rust update (01/05/2025)
//1.3.3 => 02/05/2025
// - Added: Codelock support for [Bamboo Barrel, Wicker Barrel]
//1.3.4 => 06/05/2025
// - Added: Show Box and Storage Container lock status in the UI
//1.3.5 => 13/05/2025
// - Added: New permission to bypass some controls during the deployment of the lock in vehicles
//1.3.6 => 27/05/2025
// - Fixed: Fixed issue where CodeLocks were shared even in "Use key lock only" mode
//1.3.7 => 04/07/2025
// - Added: Codelock support for Abyss Horizontal Storage Tank, Abyss Vertical Storage Tank
//1.3.8 => 07/07/2025
// - Fixed: RemoverTool bug fix
//1.3.9 => 08/07/2025
// - Improved: Delay while positioning the lock/Codelock
//1.4.0 => 08/07/2025
// - Improved: Delay while positioning the lock/Codelock (Second improvement)
//1.4.1 => 08/07/2025
// - Improved: Performance improved
// - Improved: Code refactoring
//1.4.2 => 08/07/2025
// - Fixed: Bug fix
//1.4.3 => 08/07/2025
// - Fixed: NRE Bug fix
namespace Oxide.Plugins {
[Info("UltimateLocker", "Scalbox", "1.4.3")]
[Description("Place Code Locks everywhere & Auto Lock / Auto Closing.Vehicles, Furnaces, Weapon Racks, Turrets, Deployable Items and much more.")]
public class UltimateLocker : RustPlugin {
#region Fields
[PluginReference]
private Plugin? ImageLibrary;
[PluginReference]
private Plugin? Clans;
[PluginReference]
private Plugin? Vanish;
[PluginReference]
private Plugin? RemoverTool;
[PluginReference]
private Plugin? GunShip;
private static UltimateLocker? self;
private enum EntityType {
Vehicle, VehicleBike, VehicleMedieval, DeployableConstruction, DeployableMedieval, DeployableStorage, DeployableWorkbench, DeployableElectrical, DeployableElectricalButton, DeployableElectricSwitch, DeployableElectricGenerator, DeployableLiquidContainer, DeployableTurret, DeployableTraps, DeployableModularCarLift, DeployableSnowFogMachine, DeployableElevator, DeployableElectricalNeonSign, DeployableMiningQuarry, DeployableMiningQuarryStatic, DeployableMiningPumpJack, DeployableMiningPumpJackStatic, DeployableWeaponRack, DeployableStash, DeployableItems, DeployableResources, DeployableIndustrial, DeployableMisc, DeployableFun,
}
private enum LockCategory {
None, Door, Window, Box, StorageContainer, Locker, Cupboard, Vehicle, Medieval, Furnace, VendingMachine, Composter, MixingTable, Planter, AutoTurret, SamSite, Trap, WeaponRack, Stash, NeonSign, OtherLockableEntities, OtherCustomEntities
}
private enum AutoClosingType {
None, Door, DoubleDoor, Window, Garage, LadderHatch, ExternalGate, FenceGate, LegacyWoodShelterDoor
}
private readonly List<ItemLockData> _allowedItemsLock = new();
private readonly List<string> _entityRequiredPermission = new();
//PrefabName
private readonly List<string> _vehiclesCockpitPrefabName = new() {
"assets/content/vehicles/modularcar/module_entities/1module_cockpit.prefab", "assets/content/vehicles/modularcar/module_entities/1module_cockpit_armored.prefab", "assets/content/vehicles/modularcar/module_entities/1module_cockpit_with_engine.prefab"
}
;
//PrefabName
private readonly List<string> _boxesPrefabName = new() {
"assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab", "assets/prefabs/deployable/large wood storage/box.wooden.large.prefab", "assets/prefabs/deployable/large wood storage/skins/medieval_large_wood_box/medieval.box.wooden.large.prefab", //Medieval Large Wood Box
"assets/prefabs/misc/decor_dlc/storagebarrel/storage_barrel_a.prefab", "assets/prefabs/misc/decor_dlc/storagebarrel/storage_barrel_b.prefab", "assets/prefabs/misc/decor_dlc/storagebarrel/storage_barrel_c.prefab", "assets/prefabs/deployable/large wood storage/skins/abyss_dlc_large_wood_box/abyss_dlc_storage_horizontal/abyss_barrel_horizontal.prefab", "assets/prefabs/deployable/large wood storage/skins/abyss_dlc_large_wood_box/abyss_dlc_storage_vertical/abyss_barrel_vertical.prefab", "assets/prefabs/deployable/large wood storage/skins/jungle_dlc_large_wood_box/jungle_dlc_storage_vertical/bamboo_barrel.prefab", "assets/prefabs/deployable/large wood storage/skins/jungle_dlc_large_wood_box/jungle_dlc_storage_horizontal/wicker_barrel.prefab", "assets/content/vehicles/boats/rhib/subents/rhib_storage.prefab", "assets/prefabs/misc/halloween/coffin/coffinstorage.prefab"
}
;
//PrefabName
private readonly List<string> _windowsPrefabName = new() {
"assets/prefabs/building/wall.window.shutter/shutter.wood.a.prefab"
}
;
//PrefabName
private readonly List<string> _medievalPrefabName = new() {
"assets/content/vehicles/siegeweapons/ballista/ballista.entity.prefab", //Mounted Ballista
"assets/content/vehicles/siegeweapons/batteringram/batteringram.entity.prefab", //Battering Ram
"assets/content/vehicles/siegeweapons/catapult/catapult.entity.prefab", //Catapult
"assets/content/vehicles/siegeweapons/siegetower/siegetower.entity.prefab", //Siege Tower
"assets/content/vehicles/siegeweapons/ballista/ballistagun.static.entity.prefab" //Ballista
}
;
private readonly Dictionary<AutoClosingType, List<string>> _autoClosingEntities = new() {
{
AutoClosingType.Door, new List<string> {
"assets/prefabs/building/door.hinged/door.hinged.wood.prefab", "assets/prefabs/building/door.hinged/door.hinged.metal.prefab", "assets/prefabs/building/door.hinged/door.hinged.toptier.prefab", "assets/prefabs/misc/permstore/factorydoor/door.hinged.industrial.d.prefab", "assets/prefabs/misc/medieval door skin/medieval.door.hinged.metal.prefab"
}
}
, {
AutoClosingType.DoubleDoor, new List<string> {
"assets/prefabs/building/door.double.hinged/door.double.hinged.wood.prefab", "assets/prefabs/building/door.double.hinged/door.double.hinged.metal.prefab", "assets/prefabs/building/door.double.hinged/door.double.hinged.toptier.prefab", "assets/prefabs/building/wall.frame.cell/wall.frame.cell.gate.prefab", "assets/prefabs/misc/medieval door skin/medieval.door.double.hinged.metal.prefab"
}
}
, {
AutoClosingType.Window, new List<string> {
"assets/prefabs/building/wall.window.shutter/shutter.wood.a.prefab"
}
}
, {
AutoClosingType.Garage, new List<string> {
"assets/prefabs/building/wall.frame.garagedoor/wall.frame.garagedoor.prefab"
}
}
, {
AutoClosingType.LadderHatch, new List<string> {
"assets/prefabs/building/floor.ladder.hatch/floor.ladder.hatch.prefab", "assets/prefabs/building/floor.triangle.ladder.hatch/floor.triangle.ladder.hatch.prefab"
}
}
, {
AutoClosingType.ExternalGate, new List<string> {
"assets/prefabs/building/gates.external.high/gates.external.high.wood/gates.external.high.wood.prefab", "assets/prefabs/building/gates.external.high/gates.external.high.stone/gates.external.high.stone.prefab"
}
}
, {
AutoClosingType.FenceGate, new List<string> {
"assets/prefabs/building/wall.frame.fence/wall.frame.fence.gate.prefab"
}
}
, {
AutoClosingType.LegacyWoodShelterDoor, new List<string> {
"assets/prefabs/building/legacy.shelter.wood/legacy.shelter.wood.deployed.prefab", "assets/prefabs/building/legacy.shelter.wood/legacy.shelter.wood.door.prefab"
}
}
}
;
//Vehicle name - Component Name
private readonly Dictionary<string, string> _gunShipVehiclesComponentName = new() {
{
"Apache", "Oxide.Plugins.GunShip/Apache"
}
, {
"ArmedSedan", "Oxide.Plugins.GunShip/ArmedSedan"
}
, {
"AttackRhib", "Oxide.Plugins.GunShip/AttackRhib"
}
, {
"CargoTruck", "Oxide.Plugins.GunShip/CargoTruck"
}
, {
"Cougar", "Oxide.Plugins.GunShip/Cougar"
}
, {
"Enforcer", "Oxide.Plugins.GunShip/Enforcer"
}
, {
"Guardian", "Oxide.Plugins.GunShip/Guardian"
}
, {
"HeavyTechnical", "Oxide.Plugins.GunShip/HeavyTechnical"
}
, {
"MiniFighter", "Oxide.Plugins.GunShip/MiniFighter"
}
, {
"Reaper", "Oxide.Plugins.GunShip/Reaper"
}
, {
"Stallion", "Oxide.Plugins.GunShip/Stallion"
}
, {
"Stinger", "Oxide.Plugins.GunShip/Stinger"
}
, {
"TCOPCobra", "Oxide.Plugins.GunShip/TCOPCobra"
}
, {
"TCOPHuey", "Oxide.Plugins.GunShip/TCOPHuey"
}
, {
"Technical", "Oxide.Plugins.GunShip/Technical"
}
, {
"Viper", "Oxide.Plugins.GunShip/Viper"
}
}
;
private const string UILocker = "UI.UltimateLocker.Locker";
private const string UIAutoLock = "UI.UltimateLocker.AutoLock";
private const string UIAutoClosing = "UI.UltimateLocker.AutoClosing";
private const string PermissionUse = "ultimatelocker.use";
private const string PermissionAdmin = "ultimatelocker.admin";
private const string PermissionBypassForce = "ultimatelocker.bypass.force";
private const string PermissionBypassLockDeployVehicleCheck = "ultimatelocker.bypass.lock_deploy_vehicle_check";
private const string PermissionAutoLockEnabled = "ultimatelocker.autolock.enabled";
private const string PermissionAutoLockNoLockRequired = "ultimatelocker.autolock.nolockrequired";
private const string PermissionAutoClosingEnabled = "ultimatelocker.autoclosing.enabled";
private const string PermissionAutoClosingNoDoorCloserRequired = "ultimatelocker.autoclosing.nodoorcloserrequired";
private const string DefaultTimeZone = "Europe/London";
private const int KeyLockItemID = -850982208;
private const int CodeLockItemID = 1159991980;
private const int DoorCloserItemID = 1409529282;
private const string CodeLockOnDeployImageName = "UltimateLocker::CodeLockOnDeploy";
private const string KeyLockOnDeployImageName = "UltimateLocker::KeyLockOnDeploy";
private const string CodeLockPrefab = "assets/prefabs/locks/keypad/lock.code.prefab";
private const string KeyLockPrefab = "assets/prefabs/locks/keylock/lock.key.prefab";
private const string DoorCloserPrefabName = "assets/prefabs/misc/doorcloser/doorcloser.prefab";
private const string LegacyShelterWoodDoorPrefabName = "assets/prefabs/building/legacy.shelter.wood/legacy.shelter.wood.door.prefab";
private const string KeyLockShortPrefabName = "lock.key";
private const string CodeLockShortPrefabName = "lock.code";
private const string DoorCloserShortPrefabName = "door.closer";
private const string DefaultModularCarCodeLockCode = "0000";
private const int GarageOpenDuration = 1;
private const string ModuleCarPartialShortPrefabName = "module_car_spawned.entity";
private const string CarChassisModuleCarPartialPrefabName = "assets/content/vehicles/modularcar/car_chassis_";
private const int CoroutineIteratorsPerFrame = 5;
private const float CoroutineCodeLocksWait = 0.5F;
private const string CodeLockDeployEffect = "assets/prefabs/locks/keypad/effects/lock-code-deploy.prefab";
private const string CodeLockDeniedEffect = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
private const string CodeLockLockEffect = "assets/prefabs/locks/keypad/effects/lock.code.lock.prefab";
private const string CodeLockUnlockEffect = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab";
private const string CodeLockCodeUpdatedEffect = "assets/prefabs/locks/keypad/effects/lock.code.updated.prefab";
private const string CodeLockShockEffect = "assets/prefabs/locks/keypad/effects/lock.code.shock.prefab";
private const string CodeLockOnDeployImageUrl = "https://dl.scalbox.com/Rust/Plugins/UltimateLocker/CodeLock_OnDeploy.jpg";
private const string KeyLockOnDeployImageUrl = "https://dl.scalbox.com/Rust/Plugins/UltimateLocker/KeyLock_OnDeploy.jpg";
private static readonly Regex AlphanumericRegex = new Regex("[^a-zA-Z0-9\\._-]", RegexOptions.Compiled);
// private static readonly Regex AlphanumericRegex = new Regex("alphabet\\.", RegexOptions.Compiled);
private readonly object _true = true;
private readonly DateTime _epochDateTime = DateTime.Parse("1970-01-01");
private Harmony _harmony;
private List<Coroutine> _coroutines = new();
private Configuration _config;
private Data _data;
#endregion
#region Hook
private void Init() {
if (_config.ChatCommand.IsNullOrEmpty()) {
Puts("Command missing in configuration");
Interface.Oxide.UnloadPlugin(Name);
return;
}
foreach (var command in _config.AutoLockConfiguration.ChatCommand) {
AddCovalenceCommand(command, nameof(AutoLockCmdHandler));
}
foreach (var command in _config.ChatCommand) {
AddCovalenceCommand(command, nameof(CmdHandler));
}
AddCovalenceCommand(new[] {
_config.AutoLockConfiguration.AddLockerChatCommand, _config.AutoClosingConfiguration.AddCloserChatCommand, _config.AutoClosingConfiguration.RemoveCloserChatCommand
}
, nameof(LockerCloserCmdHandler));
_allowedItemsLock.AddRange(_config.LockConfiguration.Vehicles.Where(v => v.EnableLock).ToList());
_allowedItemsLock.AddRange(_config.LockConfiguration.Deployables.Where(d => d.EnableLock).ToList());
self = this;
_data = Interface.Oxide.DataFileSystem.ReadObject<Data>(Name);
permission.RegisterPermission(PermissionUse, this);
permission.RegisterPermission(PermissionAdmin, this);
permission.RegisterPermission(PermissionBypassForce, this);
permission.RegisterPermission(PermissionBypassLockDeployVehicleCheck, this);
permission.RegisterPermission(PermissionAutoLockEnabled, this);
permission.RegisterPermission(PermissionAutoLockNoLockRequired, this);
permission.RegisterPermission(PermissionAutoClosingEnabled, this);
permission.RegisterPermission(PermissionAutoClosingNoDoorCloserRequired, this);
//Register all entity required permissions
_entityRequiredPermission.AddRange(EntityRequiredPermission());
if (!_entityRequiredPermission.IsNullOrEmpty()) {
foreach (var perm in _entityRequiredPermission) {
permission.RegisterPermission(perm, this);
}
}
}
private void OnServerInitialized() {
if (_config.AutoLockConfiguration.ResyncPlayersDefaultSettings) {
PrintWarning("Resyncing players default settings, STARTED...");
if (!_data.AutoLockPlayerSettingsData.IsNullOrEmpty()) {
foreach (var steamID in _data.AutoLockPlayerSettingsData.Keys.ToList()) {
var currentAutoLockPlayerSettings = _data.AutoLockPlayerSettingsData[steamID];
var defaultAutoLockPlayerSettingsData = GetDefaultAutoLockPlayerSettingsData(steamID);
defaultAutoLockPlayerSettingsData.CodeLock = currentAutoLockPlayerSettings.CodeLock;
defaultAutoLockPlayerSettingsData.GuestCodeLock = currentAutoLockPlayerSettings.GuestCodeLock;
_data.AutoLockPlayerSettingsData[steamID] = defaultAutoLockPlayerSettingsData;
}
SaveData();
}
if (!_data.AutoClosingPlayerSettingsData.IsNullOrEmpty()) {
foreach (var autoClosingPlayerSettingsDataKey in _data.AutoClosingPlayerSettingsData.Keys.ToList()) {
_data.AutoClosingPlayerSettingsData[autoClosingPlayerSettingsDataKey] = GetDefaultAutoClosingPlayerSettingsData(autoClosingPlayerSettingsDataKey);
}
SaveData();
}
_config.AutoLockConfiguration.ResyncPlayersDefaultSettings = false;
SaveConfig();
PrintWarning("Resyncing players default settings, DONE!");
}
_harmony = new Harmony($"{Name}_Patch_{Version.Major}_{Version.Minor}_{Version.Patch}");
_harmony.Patch(original : AccessTools.Method(typeof(ModularCarCodeLock), nameof(ModularCarCodeLock.TryAddALock)), postfix : new HarmonyMethod(typeof(ModularCarCodeLock_Settings), nameof(ModularCarCodeLock_Settings.Postfix_TryAddALock)));
_harmony.Patch(original : AccessTools.Method(typeof(ModularCarCodeLock), nameof(ModularCarCodeLock.RemoveLock)), postfix : new HarmonyMethod(typeof(ModularCarCodeLock_Settings), nameof(ModularCarCodeLock_Settings.Postfix_RemoveLock)));
_harmony.Patch(original : AccessTools.Method(typeof(Workbench), nameof(Workbench.RPC_TechTreeUnlock)), prefix : new HarmonyMethod(typeof(Workbench_Settings), nameof(Workbench_Settings.Prefix_RPC_TechTreeUnlock)));
_harmony.Patch(original : AccessTools.Method(typeof(SmartSwitch), nameof(SmartSwitch.ToggleSwitch)), prefix : new HarmonyMethod(typeof(SmartSwitch_ToggleSwitch), nameof(SmartSwitch_ToggleSwitch.Prefix)));
_harmony.Patch(original : AccessTools.Method(typeof(TimerSwitch), nameof(TimerSwitch.SVSwitch)), prefix : new HarmonyMethod(typeof(TimerSwitch_SVSwitch), nameof(TimerSwitch_SVSwitch.Prefix)));
_harmony.Patch(original : AccessTools.Method(typeof(CustomTimerSwitch), nameof(CustomTimerSwitch.SERVER_SetTime)), prefix : new HarmonyMethod(typeof(CustomTimerSwitch_SERVER_SetTime), nameof(CustomTimerSwitch_SERVER_SetTime.Prefix)));
_harmony.Patch(original : AccessTools.Method(typeof(FogMachine), nameof(FogMachine.SetFogOn)), prefix : new HarmonyMethod(typeof(FogMachine_Toggle), nameof(FogMachine_Toggle.Prefix_SetFogOn)));
_harmony.Patch(original : AccessTools.Method(typeof(FogMachine), nameof(FogMachine.SetFogOff)), prefix : new HarmonyMethod(typeof(FogMachine_Toggle), nameof(FogMachine_Toggle.Prefix_SetFogOff)));
_harmony.Patch(original : AccessTools.Method(typeof(StrobeLight), nameof(StrobeLight.SetStrobe), new[] {
typeof(BaseEntity.RPCMessage)
}
), prefix : new HarmonyMethod(typeof(StrobeLight_Settings), nameof(StrobeLight_Settings.Prefix_SetStrobe)));
_harmony.Patch(original : AccessTools.Method(typeof(StrobeLight), nameof(StrobeLight.SetStrobeSpeed)), prefix : new HarmonyMethod(typeof(StrobeLight_Settings), nameof(StrobeLight_Settings.Prefix_SetStrobeSpeed)));
_harmony.Patch(original : AccessTools.Method(typeof(AudioVisualisationEntity), nameof(AudioVisualisationEntity.ServerUpdateSettings)), prefix : new HarmonyMethod(typeof(AudioVisualisationEntity_Settings), nameof(AudioVisualisationEntity_Settings.Prefix_ServerUpdateSettings)));
// _harmony.Patch(original: AccessTools.Method(typeof(Signage), nameof(Signage.CanUpdateSign)),
// prefix: new HarmonyMethod(typeof(Signage_Settings), nameof(Signage_Settings.Prefix_CanUpdateSign)));
_harmony.Patch(original : AccessTools.Method(typeof(Signage), nameof(Signage.LockSign)), prefix : new HarmonyMethod(typeof(Signage_Settings), nameof(Signage_Settings.Prefix_LockSign)));
_harmony.Patch(original : AccessTools.Method(typeof(Signage), nameof(Signage.UnLockSign)), prefix : new HarmonyMethod(typeof(Signage_Settings), nameof(Signage_Settings.Prefix_UnLockSign)));
_harmony.Patch(original : AccessTools.Method(typeof(NeonSign), nameof(NeonSign.SetAnimationSpeed)), prefix : new HarmonyMethod(typeof(NeonSign_Settings), nameof(NeonSign_Settings.Prefix_SetAnimationSpeed)));
_harmony.Patch(original : AccessTools.Method(typeof(NeonSign), nameof(NeonSign.UpdateNeonColors)), prefix : new HarmonyMethod(typeof(NeonSign_Settings), nameof(NeonSign_Settings.Prefix_UpdateNeonColors)));
_harmony.Patch(original : AccessTools.Method(typeof(SearchLight), nameof(SearchLight.RPC_UseLight)), prefix : new HarmonyMethod(typeof(SearchLight_Settings), nameof(SearchLight_Settings.Prefix_UseLight)));
_harmony.Patch(original : AccessTools.Method(typeof(PoweredRemoteControlEntity), nameof(PoweredRemoteControlEntity.CanChangeID)), prefix : new HarmonyMethod(typeof(PoweredRemoteControlEntity_Settings), nameof(PoweredRemoteControlEntity_Settings.Prefix_CanChangeID)));
_harmony.Patch(original : AccessTools.Method(typeof(PoweredRemoteControlEntity), nameof(PoweredRemoteControlEntity.CanControl)), prefix : new HarmonyMethod(typeof(PoweredRemoteControlEntity_Settings), nameof(PoweredRemoteControlEntity_Settings.Prefix_CanControl)));
_harmony.Patch(original : AccessTools.Method(typeof(RFBroadcaster), nameof(RFBroadcaster.ServerSetFrequency)), prefix : new HarmonyMethod(typeof(RFBroadcaster_Settings), nameof(RFBroadcaster_Settings.Prefix_ServerSetFrequency)));
_harmony.Patch(original : AccessTools.Method(typeof(RFReceiver), nameof(RFReceiver.ServerSetFrequency)), prefix : new HarmonyMethod(typeof(RFReceiver_Settings), nameof(RFReceiver_Settings.Prefix_ServerSetFrequency)));
_harmony.Patch(original : AccessTools.Method(typeof(AutoTurret), nameof(AutoTurret.CanControl)), prefix : new HarmonyMethod(typeof(AutoTurret_Settings), nameof(AutoTurret_Settings.Prefix_CanControl)));
// _harmony.Patch(original: AccessTools.Method(typeof(GrowableEntity), nameof(GrowableEntity.PickFruit)),
// prefix: new HarmonyMethod(typeof(GrowableEntity_Settings),
// nameof(GrowableEntity_Settings.Prefix_PickFruit)));
_harmony.Patch(original : AccessTools.Method(typeof(IndustrialCrafter), "SvSwitch"), prefix : new HarmonyMethod(typeof(IndustrialCrafter_Settings), nameof(IndustrialCrafter_Settings.Prefix_SvSwitch)));
//######################################## MEDIEVAL ENTITIES ########################################
_harmony.Patch(original : AccessTools.Method(typeof(BatteringRam), "RPC_OpenDoor"), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.BatteringRam_Prefix_RPC_OpenDoor)));
_harmony.Patch(original : AccessTools.Method(typeof(BatteringRam), "RPC_CloseDoor"), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.BatteringRam_Prefix_RPC_CloseDoor)));
_harmony.Patch(original : AccessTools.Method(typeof(Door), "RPC_OpenDoor"), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.SiegeTower_Prefix_RPC_OpenDoor)));
_harmony.Patch(original : AccessTools.Method(typeof(Door), "RPC_CloseDoor"), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.SiegeTower_Prefix_RPC_CloseDoor)));
_harmony.Patch(original : AccessTools.Method(typeof(Catapult), "SERVER_ReloadStart"), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.Catapult_Prefix_SERVER_ReloadStart)));
_harmony.Patch(original : AccessTools.Method(typeof(BaseSiegeWeapon), nameof(BaseSiegeWeapon.SERVER_StartPulling)), prefix : new HarmonyMethod(typeof(MedievalEntity_Settings), nameof(MedievalEntity_Settings.BaseSiegeWeapon_Prefix_SERVER_StartPulling)));
//###################################################################################################
if (RemoverTool != null && !_config.AutoClosingConfiguration.CanRemoveDoorCloser) {
var targetType = AccessTools.TypeByName("Oxide.Plugins.RemoverTool");
_harmony.Patch(original : AccessTools.Method(targetType, "HasAccess"), prefix : new HarmonyMethod(typeof(RemoverTool_Patch), nameof(RemoverTool_Patch.Prefix_HasAccess)));
}
ImageLibrary?.Call("AddImage", CodeLockOnDeployImageUrl, CodeLockOnDeployImageName);
ImageLibrary?.Call("AddImage", KeyLockOnDeployImageUrl, KeyLockOnDeployImageName);
//TODO da testare e poi rimuovere
// NextFrame(() => _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleStorageContainerLockableOnStartup())));
if (!_config.AutoLockConfiguration.UseOnlyKeyLock) NextFrame(() => _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleUpdateCodeLockAuthOnStartup())));
NextFrame(() => _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleUpdateDoorCloserDelayTimeOnStartup())));
}
private List<string> EntityRequiredPermission() {
var itemPermissions = _allowedItemsLock.Where(i => !IsNullOrEmpty(i.RequiredPermission)).Select(i => i.RequiredPermission).ToList();
if (IsNullOrEmpty(itemPermissions)) return Array.Empty<string>().ToList();
var validEntityPermissionsList = new List<string?>();
foreach (var itemPermission in itemPermissions.Select(GetValidPermission).Where(permissions => !IsNullOrEmpty(permissions))) {
validEntityPermissionsList.AddRange(itemPermission);
}
if (IsNullOrEmpty(validEntityPermissionsList)) return Array.Empty<string>().ToList();
//Remove empty and duplicated permissions
validEntityPermissionsList = validEntityPermissionsList.Where(s => s != null && !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
return validEntityPermissionsList!;
}
private List<string> GetValidPermission(ICollection<string> permissions) {
if (IsNullOrEmpty(permissions)) return Array.Empty<string>().ToList();
return permissions.Select(GetValidPermission).Where(perm => perm != null).ToList()!;
}
private string? GetValidPermission(string perm) {
if (string.IsNullOrWhiteSpace(perm)) return null;
perm = perm.Replace(" ", "_");
perm = AlphanumericRegex.Replace(perm, "");
var permissionPrefix = Name.ToLower();
return string.IsNullOrWhiteSpace(perm) ? null : $"{permissionPrefix}.{perm.ToLower()}";
}
private bool HasValidPermission(BasePlayer? player, ICollection<string> permissions) {
if (player == null || IsNullOrEmpty(permissions)) return false;
var validPermission = GetValidPermission(permissions);
if (IsNullOrEmpty(validPermission)) return true;
return validPermission.Any(perm => _entityRequiredPermission.Contains(perm) && permission.UserHasPermission(player.UserIDString, perm));
}
private void Unload() {
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, UILocker);
CuiHelper.DestroyUi(player, UIAutoLock);
CuiHelper.DestroyUi(player, UIAutoClosing);
DestroyMonoComponent(player);
}
if (!_coroutines.IsNullOrEmpty()) {
foreach (var coroutine in _coroutines.Where(c => c != null)) {
ServerMgr.Instance.StopCoroutine(coroutine);
}
}
//TODO DA RIMUOVERE
ServerMgr.Instance.StartCoroutine(HandleStorageContainerLockableOnunload());
_coroutines.Clear();
_entityRequiredPermission.Clear();
_vehiclesCockpitPrefabName.Clear();
_harmony.UnpatchAll($"{Name}_Patch_{Version.Major}_{Version.Minor}_{Version.Patch}");
self = null;
}
private void OnPlayerConnected(BasePlayer player) {
DestroyMonoComponent(player);
}
private void OnPlayerDisconnected(BasePlayer player, string reason) {
DestroyMonoComponent(player);
}
private void OnNewSave(string filename) {
_data.AutoLockPlayerSettingsData.Clear();
_data.AutoClosingPlayerSettingsData.Clear();
_data.CodeLockItemsData.Clear();
_data.DoorCloserCustomTimeItemsData.Clear();
SaveData();
}
protected override void LoadConfig() {
base.LoadConfig();
_config = Config.ReadObject<Configuration>();
MergeConfiguration();
if (!Equals(_config.VersionNumber, Version)) {
UpdateConfigValues();
_config.VersionNumber = Version;
}
SaveConfig();
// // For debug for new entities
// _config.LockConfiguration.Vehicles.Clear();
// _config.LockConfiguration.Deployables.Clear();
//
// PrintWarning("FORCE CONFIG FOR DEBUG: Started updating the configuration file...");
//
// var confDebug = Configuration.CreateConfig();
// if (!confDebug.LockConfiguration.Vehicles.IsNullOrEmpty())
// {
// foreach (var vehicle in confDebug.LockConfiguration.Vehicles)
// {
// if (!_config.LockConfiguration.Vehicles.Any(i => i.PrefabName.Equals(vehicle.PrefabName, StringComparison.OrdinalIgnoreCase)))
// {
// vehicle.EnableLock = true;
// _config.LockConfiguration.Vehicles.Add(vehicle);
// }
// }
//
// SaveConfig();
// }
//
// if (!confDebug.LockConfiguration.Deployables.IsNullOrEmpty())
// {
// foreach (var deployable in confDebug.LockConfiguration.Deployables)
// {
// if (!_config.LockConfiguration.Deployables.Any(i => i.PrefabName.Equals(deployable.PrefabName, StringComparison.OrdinalIgnoreCase)))
// {
// deployable.EnableLock = true;
// _config.LockConfiguration.Deployables.Add(deployable);
// }
// }
//
// SaveConfig();
// }
//
// PrintWarning("FORCE CONFIG FOR DEBUG: Config update completed!");
// //-------------------- End debug --------------------
}
//Merge Json Ignored value to the config
private void MergeConfiguration() {
var tmpConf = Configuration.CreateConfig();
foreach (var tmpVehicle in tmpConf.LockConfiguration.Vehicles) {
var vehicle = _config.LockConfiguration.Vehicles.FirstOrDefault(v => v.PrefabName.ToLower().Equals(tmpVehicle.PrefabName.ToLower()));
if (vehicle == null) continue;
vehicle.LockCategory = tmpVehicle.LockCategory;
vehicle.EntityType = tmpVehicle.EntityType;
vehicle.CodeLockPosition = tmpVehicle.CodeLockPosition;
vehicle.CodeLockRotation = tmpVehicle.CodeLockRotation;
}
foreach (var tmpDeployable in tmpConf.LockConfiguration.Deployables) {
var deployable = _config.LockConfiguration.Deployables.FirstOrDefault(v => v.PrefabName.ToLower().Equals(tmpDeployable.PrefabName.ToLower()));
if (deployable == null) continue;
deployable.LockCategory = tmpDeployable.LockCategory;
deployable.EntityType = tmpDeployable.EntityType;
deployable.CodeLockPosition = tmpDeployable.CodeLockPosition;
deployable.CodeLockRotation = tmpDeployable.CodeLockRotation;
}
}
private void DeleteLangFiles() {
var langDir = Interface.Oxide.LangDirectory;
string[] languages = lang.GetLanguages(this);
foreach (var language in languages) {
var langFile = Path.Combine(langDir, language, $"{Name}.json");
if (!File.Exists(langFile)) continue;
File.Delete(langFile);
Puts($"########## Delete old lang file: {langFile} ##########");
}
}
private void UpdateConfigValues() {
UpdateDataValues();
if (_config.VersionNumber < new VersionNumber(0, 9, 84)) {
if (!_config.LockConfiguration.Vehicles.Any(dep => dep.PrefabName.Equals("assets/content/vehicles/bikes/motorbike.prefab"))) {
_config.LockConfiguration.Vehicles.Add(new ItemLockData {
ItemName = "Motorbike", EnableLock = false, PrefabName = "assets/content/vehicles/bikes/motorbike.prefab", EntityType = EntityType.VehicleBike, CodeLockPosition = new Vector3(0.074f, 0.8f, 0.14f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Vehicles.Any(dep => dep.PrefabName.Equals("assets/content/vehicles/bikes/motorbike_sidecar.prefab"))) {
_config.LockConfiguration.Vehicles.Add(new ItemLockData {
ItemName = "Motorbike With Sidecar", EnableLock = false, PrefabName = "assets/content/vehicles/bikes/motorbike_sidecar.prefab", EntityType = EntityType.VehicleBike, CodeLockPosition = new Vector3(0.72f, 0.52f, -0.65f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Vehicles.Any(dep => dep.PrefabName.Equals("assets/content/vehicles/bikes/pedalbike.prefab"))) {
_config.LockConfiguration.Vehicles.Add(new ItemLockData {
ItemName = "Pedal Bike", EnableLock = false, PrefabName = "assets/content/vehicles/bikes/pedalbike.prefab", EntityType = EntityType.VehicleBike, CodeLockPosition = new Vector3(0.0f, 0.6f, -0.07f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Vehicles.Any(dep => dep.PrefabName.Equals("assets/content/vehicles/bikes/pedaltrike.prefab"))) {
_config.LockConfiguration.Vehicles.Add(new ItemLockData {
ItemName = "Pedal Trike", EnableLock = false, PrefabName = "assets/content/vehicles/bikes/pedaltrike.prefab", EntityType = EntityType.VehicleBike, CodeLockPosition = new Vector3(0.0f, 0.7f, -0.5f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/deployable/weaponracks/weaponrack_single1.deployed.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Frontier Bolts Single Item Rack", EnableLock = false, PrefabName = "assets/prefabs/deployable/weaponracks/weaponrack_single1.deployed.prefab", EntityType = EntityType.DeployableWeaponRack, CodeLockPosition = new Vector3(-0.5f, 0.0f, 0.0f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/deployable/weaponracks/weaponrack_single2.deployed.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Frontier Horseshoe Single Item Rack", EnableLock = false, PrefabName = "assets/prefabs/deployable/weaponracks/weaponrack_single2.deployed.prefab", EntityType = EntityType.DeployableWeaponRack, CodeLockPosition = new Vector3(-0.5f, 0.0f, 0.0f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/deployable/weaponracks/weaponrack_single3.deployed.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Frontier Horns Single Item Rack", EnableLock = false, PrefabName = "assets/prefabs/deployable/weaponracks/weaponrack_single3.deployed.prefab", EntityType = EntityType.DeployableWeaponRack, CodeLockPosition = new Vector3(-0.5f, 0.0f, 0.0f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
}
if (_config.VersionNumber < new VersionNumber(0, 9, 85)) {
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/bundled/prefabs/static/miningquarry_static.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Mining Quarry Static", EnableLock = false, PrefabName = "assets/bundled/prefabs/static/miningquarry_static.prefab", EntityType = EntityType.DeployableMiningQuarryStatic, CodeLockPosition = new Vector3(-2.36f, 4.5f, 1.66f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
}
if (_config.VersionNumber < new VersionNumber(0, 9, 86)) {
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/deployable/oil jack/mining.pumpjack.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Pump Jack", EnableLock = false, PrefabName = "assets/prefabs/deployable/oil jack/mining.pumpjack.prefab", EntityType = EntityType.DeployableMiningPumpJack, CodeLockPosition = new Vector3(3.26f, 4.5f, -1.36f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/bundled/prefabs/static/pumpjack-static.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Pump Jack Static", EnableLock = false, PrefabName = "assets/bundled/prefabs/static/pumpjack-static.prefab", EntityType = EntityType.DeployableMiningPumpJackStatic, CodeLockPosition = new Vector3(3.26f, 4.5f, -1.36f), CodeLockRotation = Quaternion.Euler(0.0f, 90.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
}
if (_config.VersionNumber < new VersionNumber(0, 9, 902)) {
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/content/vehicles/boats/rhib/subents/rhib_storage.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "RHIB Storage", EnableLock = false, PrefabName = "assets/content/vehicles/boats/rhib/subents/rhib_storage.prefab", EntityType = EntityType.DeployableStorage, CodeLockPosition = new Vector3(0.0f, 0.38f, 0.30f), CodeLockRotation = Quaternion.Euler(0, 90, 0), RequiredPermission = new[] {
""
}
}
);
}
}
if (_config.VersionNumber < new VersionNumber(0, 9, 910)) {
Puts("Configuration file is outdated.Updating...");
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/misc/chinesenewyear/chineselantern/chineselantern.deployed.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Chinese Lantern", EnableLock = false, PrefabName = "assets/prefabs/misc/chinesenewyear/chineselantern/chineselantern.deployed.prefab", EntityType = EntityType.DeployableStorage, CodeLockPosition = new Vector3(0.0f, -0.4f, 0.0f), CodeLockRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/misc/chinesenewyear/chineselantern/chineselantern_white.deployed.prefab"))) {
_config.LockConfiguration.Deployables.Add(new ItemLockData {
ItemName = "Chinese Lantern White", EnableLock = false, PrefabName = "assets/prefabs/misc/chinesenewyear/chineselantern/chineselantern_white.deployed.prefab", EntityType = EntityType.DeployableStorage, CodeLockPosition = new Vector3(0.0f, -0.4f, 0.0f), CodeLockRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f), RequiredPermission = new[] {
""
}
}
);
}
if (!_config.LockConfiguration.Deployables.Any(dep => dep.PrefabName.Equals("assets/prefabs/deployable/tuna can wall lamp/tunalight.deployed.prefab"))) {
_conf
// ... [Code preview truncated due to length. Full source in attached file] ...