As it says above. Any way to get a fix for that?
Hide and code change command are not working
Same thing for me. This part of the code who call ClientRPC is obsolete.
Any update on that so far?
Nope, no update, I think I will create a fork for this plugin.
Same here - any alternatives out there yet?
Here is a fix
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = Oxide.Core.Random;
namespace Oxide.Plugins
{
[Info("Auto Lock", "birthdates", "2.4.5")]
[Description("Automatically adds a codelock to a lockable entity with a set pin")]
public class AutoLock : RustPlugin
{
#region Variables
private const string PermissionUse = "autolock.use";
private const string PermissionItemBypass = "autolock.item.bypass";
private readonly Dictionary<BasePlayer, TimedCodeLock> _awaitingResponse =
new Dictionary<BasePlayer, TimedCodeLock>();
[UsedImplicitly] [PluginReference("NoEscape")]
private Plugin _noEscape;
private struct TimedCodeLock
{
public CodeLock CodeLock { get; set; }
public DateTime Expiry { get; set; }
}
#endregion
#region Hooks
[UsedImplicitly]
private void Init()
{
LoadConfig();
permission.RegisterPermission(PermissionUse, this);
permission.RegisterPermission(PermissionItemBypass, this);
_data = Interface.Oxide.DataFileSystem.ReadObject<Data>(Name);
cmd.AddChatCommand("autolock", this, ChatCommand);
cmd.AddChatCommand("al", this, ChatCommand);
if (_config.CodeLockExpiry <= 0f) Unsubscribe(nameof(OnServerInitialized));
}
[UsedImplicitly]
private void OnServerInitialized()
{
timer.Every(3f, () =>
{
for (var i = _awaitingResponse.Count - 1; i > 0; i--)
{
var timedLock = _awaitingResponse.ElementAt(i);
if (timedLock.Value.Expiry > DateTime.UtcNow) continue;
_awaitingResponse.Remove(timedLock.Key);
}
});
}
[UsedImplicitly]
private void OnEntityBuilt(HeldEntity plan, GameObject go)
{
var player = plan.GetOwnerPlayer();
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermissionUse)) return;
var entity = go.ToBaseEntity() as DecayEntity;
if (entity == null || _config.Disabled.Contains(entity.PrefabName)) return;
var container = entity as StorageContainer;
if (entity.IsLocked() || container != null && container.inventorySlots < 12 ||
!container && !(entity is AnimatedBuildingBlock)) return;
if (_noEscape != null)
{
if (_config.NoEscapeSettings.BlockRaid && _noEscape.Call<bool>("IsRaidBlocked", player.UserIDString))
{
SendMessage(player, "RaidBlocked");
return;
}
if (_config.NoEscapeSettings.BlockCombat &&
_noEscape.Call<bool>("IsCombatBlocked", player.UserIDString))
{
SendMessage(player, "CombatBlocked");
return;
}
}
var playerData = CreateDataIfAbsent(player.UserIDString);
if (!playerData.Enabled || !HasCodeLock(player)) return;
var code = GameManager.server.CreateEntity("assets/prefabs/locks/keypad/lock.code.prefab") as CodeLock;
if (code != null)
{
code.gameObject.Identity();
code.SetParent(entity, entity.GetSlotAnchorName(BaseEntity.Slot.Lock));
code.Spawn();
code.code = playerData.Code;
code.hasCode = true;
entity.SetSlot(BaseEntity.Slot.Lock, code);
Effect.server.Run("assets/prefabs/locks/keypad/effects/lock-code-deploy.prefab", code.transform.position);
code.whitelistPlayers.Add(player.userID);
code.SetFlag(BaseEntity.Flags.Locked, true);
}
TakeCodeLock(player);
// Here we pass both the message key "CodeAdded" and the actual code to the SendMessage method
SendMessage(player, "CodeAdded", playerData.Code);
}
private static string GetRandomCode()
{
return Random.Range(1000, 9999).ToString();
}
[UsedImplicitly]
private void OnServerShutdown()
{
Unload();
}
private void Unload()
{
SaveData();
foreach (var timedLock in _awaitingResponse.Values.Where(timedLock => !timedLock.CodeLock.IsDestroyed))
timedLock.CodeLock.Kill();
}
private PlayerData CreateDataIfAbsent(string id)
{
PlayerData playerData;
if (_data.Codes.TryGetValue(id, out playerData)) return playerData;
_data.Codes.Add(id, playerData = new PlayerData
{
Code = GetRandomCode(),
Enabled = true
});
return playerData;
}
#endregion
#region Command
private void ChatCommand(BasePlayer player, string label, string[] args)
{
// Check if the player has permission
if (!permission.UserHasPermission(player.UserIDString, PermissionUse))
{
// Send no-permission message to the player
SendMessage(player, "NoPermission");
return;
}
// Check if the player provided enough arguments
if (args.Length < 1)
{
SendMessage(player, "InvalidArgs", label);
return;
}
// Ensure the player has associated data
CreateDataIfAbsent(player.UserIDString);
switch (args[0].ToLower())
{
case "code":
// Ensure the player has provided the code argument
if (args.Length != 2)
{
SendMessage(player, "InvalidArgs", label);
return;
}
// Set the player's code
SetPlayerCode(player, args[1]);
break;
case "toggle":
// Toggle the auto-lock feature and send feedback to the player
SendMessage(player, Toggle(player) ? "Enabled" : "Disabled");
break;
case "hide":
// Toggle the visibility of messages
ToggleHideMessages(player);
break;
default:
// Send invalid arguments message if the command is not recognized
SendMessage(player, "InvalidArgs", label);
break;
}
}
private void SendMessage(BasePlayer player, string messageKey, string code = null)
{
// Fetch the player's data to check if they have hidden messages
var playerData = CreateDataIfAbsent(player.UserIDString);
// If the player has chosen to hide messages, don't send the message
if (playerData.HideMessages) return;
// Fetch the localized message from the language file
string message = lang.GetMessage(messageKey, this, player.UserIDString);
// If a code is provided, format the message to include it
if (code != null)
{
message = string.Format(message, code);
}
// Send the message using Rust's chat system
player.ChatMessage(message);
}
private void SetPlayerCode(BasePlayer player, string code)
{
// Ensure the code is a 4-digit number
if (code.Length != 4 || !int.TryParse(code, out _))
{
SendMessage(player, "InvalidCode");
return;
}
// Find the entity the player is looking at
RaycastHit hit;
if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 5f))
{
SendMessage(player, "NoEntityFound");
return;
}
var entity = hit.GetEntity();
if (entity == null)
{
SendMessage(player, "NoEntityFound");
return;
}
// Check if the entity has a code lock
var codeLock = entity.GetSlot(BaseEntity.Slot.Lock) as CodeLock;
if (codeLock == null)
{
SendMessage(player, "NoCodeLockFound");
return;
}
// Set the new code on the code lock
codeLock.code = code;
codeLock.hasCode = true;
codeLock.SetFlag(BaseEntity.Flags.Locked, true); // Ensure the lock is locked
// Respect the player's HideMessages setting
var playerData = CreateDataIfAbsent(player.UserIDString);
if (!playerData.HideMessages)
{
// Send the message using the SendMessage method, passing the code as the second parameter
SendMessage(player, "CodeUpdated", code);
}
// Play the effect to indicate the code has changed
Effect.server.Run(codeLock.effectCodeChanged.resourcePath, codeLock.transform.position);
}
private void ToggleHideMessages(BasePlayer player)
{
var playerData = CreateDataIfAbsent(player.UserIDString);
playerData.HideMessages = !playerData.HideMessages;
// Inform the player whether messages are hidden or visible
SendMessage(player, playerData.HideMessages ? "MessagesHidden" : "MessagesVisible");
}
private static bool HasCodeLock(BasePlayer player)
{
return player.IPlayer.HasPermission(PermissionItemBypass) || player.inventory.FindItemByItemID(1159991980) != null;
}
private static void TakeCodeLock(BasePlayer player)
{
if (!player.IPlayer.HasPermission(PermissionItemBypass))
player.inventory.Take(null, 1159991980, 1);
}
private bool Toggle(BasePlayer player)
{
var data = _data.Codes[player.UserIDString];
var newToggle = !data.Enabled;
data.Enabled = newToggle;
return newToggle;
}
#endregion
#region Configuration & Language
private ConfigFile _config;
private Data _data;
private class PlayerData
{
public string Code;
public bool Enabled;
public bool HideMessages;
}
private class Data
{
public readonly Dictionary<string, PlayerData> Codes = new Dictionary<string, PlayerData>();
}
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
{"CodeAdded", "Codelock placed with code {0}."},
{"Disabled", "You have disabled auto locks."},
{"Enabled", "You have enabled auto locks."},
{"CodeUpdated", "Your new code is {0}."},
{"NoPermission", "You don't have permission."},
{"InvalidArgs", "/{0} code|toggle|hide"},
{"RaidBlocked", "The codelock wasn't automatically locked due to you being raid blocked!"},
{"CombatBlocked", "The codelock wasn't automatically locked due to you being combat blocked!"},
{"MessagesHidden", "Auto lock messages are now hidden."},
{"MessagesVisible", "Auto lock messages are now visible."},
{"InvalidCode", "Please enter a valid 4-digit code."},
{"NoEntityFound", "You are not looking at a valid entity."},
{"NoCodeLockFound", "No code lock found on the entity."}
}, this);
}
public class ConfigFile
{
[JsonProperty("Code Lock Expiry Time (Seconds, put -1 if you want to disable)")]
public float CodeLockExpiry;
[JsonProperty("Disabled Items (Prefabs)")]
public List<string> Disabled;
[JsonProperty("No Escape")] public NoEscapeSettings NoEscapeSettings;
public static ConfigFile DefaultConfig()
{
return new ConfigFile
{
Disabled = new List<string>
{
"assets/prefabs/deployable/large wood storage/box.wooden.large.prefab"
},
CodeLockExpiry = 10f,
NoEscapeSettings = new NoEscapeSettings
{
BlockCombat = true,
BlockRaid = true
}
};
}
}
public class NoEscapeSettings
{
[JsonProperty("Block Auto Lock whilst in Combat?")]
public bool BlockCombat;
[JsonProperty("Block Auto Lock whilst Raid Blocked?")]
public bool BlockRaid;
}
private void SaveData()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
}
protected override void LoadConfig()
{
base.LoadConfig();
_config = Config.ReadObject<ConfigFile>();
if (_config == null) LoadDefaultConfig();
}
protected override void LoadDefaultConfig()
{
_config = ConfigFile.DefaultConfig();
PrintWarning("Default configuration has been loaded.");
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
#endregion
}
} The /autlock code 1234 for example should change that code in the data file where all codes stored for the players but not the lock itself.