I just instaled this and get this when I try to change my code.
StringPool.GetNumber - no number for string EnterUnlockCode
StringPool.GetNumber error
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
}
}