C#:
using System;
using UnityEngine;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Convert = System.Convert;
using System.Linq;
using Oxide.Game.Rust.Cui;
using Rust;
namespace Oxide.Plugins
{
[Info("Lock Barrels", "Julio Juajez", "1.1.1")]
[Description("Lock your Barels")]
class LockBarrels : RustPlugin
{
public static LockBarrels Instance;
ConfigData configData;
HashSet<ulong> playersInAddMode = new HashSet<ulong>();
class ConfigData {
public string Command { get; set; } = "lockbarrels_refresh";
public string AddCommand { get; set; } = "lockbarrels_add";
public string ListCommand { get; set; } = "lockbarrels_list";
public string CleanCommand { get; set; } = "lockbarrels_clean";
public string ResetConfigCommand { get; set; } = "lockbarrels_reset";
public string PermAdmin { get; set; } = "lockbarrels.admin";
public List<string> SupportedBarrels { get; set; }
}
protected override void LoadDefaultConfig() {
configData = GetDefaultConfig();
SaveConfig(configData);
PrintWarning("New configuration file created.");
}
private ConfigData GetDefaultConfig()
{
return new ConfigData
{
Command = "lockbarrels_refresh",
AddCommand = "lockbarrels_add",
ListCommand = "lockbarrels_list",
CleanCommand = "lockbarrels_clean",
ResetConfigCommand = "lockbarrels_reset",
PermAdmin = "lockbarrels.admin",
SupportedBarrels = new List<string>
{
// Barils de base DLC
"assets/prefabs/misc/decor_dlc/storagebarrel/storage_barrel_b.prefab",
"assets/prefabs/misc/decor_dlc/storagebarrel/storage_barrel_c.prefab",
// Barils Abyss DLC
"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",
// Barils Jungle DLC
"assets/prefabs/deployable/large wood storage/skins/jungle_dlc_large_wood_box/jungle_dlc_storage_horizontal/wicker_barrel.prefab",
"assets/prefabs/deployable/large wood storage/skins/jungle_dlc_large_wood_box/jungle_dlc_storage_vertical/bamboo_barrel.prefab"
}
};
}
private void Init(){
Instance = this;
// Charger la config existante ou créer une nouvelle si elle n'existe pas
try
{
configData = Config.ReadObject<ConfigData>();
if (configData == null)
{
LoadDefaultConfig();
}
else
{
// Sauvegarder seulement si la migration a eu lieu
bool migrated = MigrateConfigIfNeeded();
if (migrated)
{
SaveConfig(configData);
PrintWarning("Configuration updated with new parameters.");
}
}
}
catch
{
LoadDefaultConfig();
}
permission.RegisterPermission(configData.PermAdmin, this);
cmd.AddChatCommand(configData.Command, this, "CmdRefresh");
cmd.AddChatCommand(configData.AddCommand, this, "CmdAddBarrel");
cmd.AddChatCommand(configData.ListCommand, this, "CmdListBarrels");
cmd.AddChatCommand(configData.CleanCommand, this, "CmdCleanBarrels");
cmd.AddChatCommand(configData.ResetConfigCommand, this, "CmdResetConfig");
// Démarrer un timer pour vérifier les marteaux
timer.Every(2f, CheckHammersInHand);
}
private void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
private bool MigrateConfigIfNeeded()
{
bool needsUpdate = false;
var defaultConfig = GetDefaultConfig();
Puts("Starting configuration migration check...");
// Lire directement le fichier JSON pour voir ce qui manque vraiment
var jsonConfig = Config.ReadObject<Dictionary<string, object>>();
// Vérifier si c'est une première installation (aucun SupportedBarrels dans le JSON)
bool isFirstInstall = !jsonConfig.ContainsKey("SupportedBarrels");
// Vérifier chaque champ de configuration dans le JSON actuel
if (!jsonConfig.ContainsKey("CleanCommand"))
{
configData.CleanCommand = defaultConfig.CleanCommand;
needsUpdate = true;
Puts("Missing CleanCommand in JSON file - will be added");
}
if (!jsonConfig.ContainsKey("ResetConfigCommand"))
{
configData.ResetConfigCommand = defaultConfig.ResetConfigCommand;
needsUpdate = true;
Puts("Missing ResetConfigCommand in JSON file - will be added");
}
// Appliquer les valeurs par défaut pour les champs manquants
if (string.IsNullOrEmpty(configData.AddCommand))
{
configData.AddCommand = defaultConfig.AddCommand;
needsUpdate = true;
}
if (string.IsNullOrEmpty(configData.ListCommand))
{
configData.ListCommand = defaultConfig.ListCommand;
needsUpdate = true;
}
// Gestion spéciale pour SupportedBarrels
if (isFirstInstall)
{
// Première installation : on ajoute tous les barils par défaut
configData.SupportedBarrels = defaultConfig.SupportedBarrels;
needsUpdate = true;
Puts($"First installation detected - Added {defaultConfig.SupportedBarrels.Count} default barrels");
}
else if (configData.SupportedBarrels == null)
{
// Cas rare où la liste est null mais le champ existe dans le JSON
configData.SupportedBarrels = new List<string>();
needsUpdate = true;
Puts("SupportedBarrels was null - initialized empty list");
}
// IMPORTANT : Si SupportedBarrels existe déjà dans le JSON, on ne touche à RIEN
// L'utilisateur peut avoir volontairement supprimé des barils
// On n'ajoute PAS automatiquement les barils par défaut
if (needsUpdate)
{
Puts("Configuration migration required - updating JSON file.");
}
else
{
Puts("Configuration is complete, no migration needed.");
}
return needsUpdate;
}
private void CheckHammersInHand()
{
var playersToRemove = new List<ulong>();
foreach (var playerID in playersInAddMode)
{
var player = BasePlayer.FindByID(playerID);
if (player == null || !player.IsConnected)
{
playersToRemove.Add(playerID);
continue;
}
var activeItem = player.GetActiveItem();
if (activeItem == null || activeItem.info.shortname != "hammer")
{
playersToRemove.Add(playerID);
Message(player, "AddModeDisabledNoHammer");
Puts($"Admin {player.displayName} left barrel add mode (no hammer)");
}
}
foreach (var playerID in playersToRemove)
{
playersInAddMode.Remove(playerID);
}
}
private void CmdRefresh(BasePlayer player, string command, string[] args) {
if(!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)){
Message(player, "Usage");
return;
}
NextTick(() =>
{
foreach (var entity in BaseNetworkable.serverEntities.OfType<BoxStorage>()){
if (entity == null) { continue; }
if(isPlayer(entity.OwnerID)){
var barrel = entity as BoxStorage;
if(IsSupportedBarrel(barrel.PrefabName)){
barrel.isLockable = true;
barrel.SendNetworkUpdate();
barrel.SendNetworkUpdateImmediate();
}
}
}
Message(player, "Success");
});
}
static bool isPlayer(ulong id) => id > 76560000000000000L;
private bool IsSupportedBarrel(string prefabName)
{
return configData.SupportedBarrels.Contains(prefabName);
}
private void OnEntitySpawned(BaseNetworkable entity)
{
if (entity is BoxStorage)
{
var barrel = entity as BoxStorage;
if(IsSupportedBarrel(barrel.PrefabName)){
barrel.isLockable = true;
barrel.SendNetworkUpdate();
barrel.SendNetworkUpdateImmediate();
}
return;
}
}
void OnHammerHit(BasePlayer player, HitInfo info)
{
// Vérifier si le joueur est en mode d'ajout
if (!playersInAddMode.Contains(player.userID)) return;
// Vérifier s'il a les permissions
if (!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)) return;
// Vérifier si l'entité touchée est un conteneur de stockage
var entity = info.HitEntity;
if (entity != null && entity is BoxStorage)
{
var barrel = entity as BoxStorage;
// Vérifier que c'est bien un baril (contient "barrel" dans le nom)
if (!IsValidBarrel(barrel)) {
Message(player, "NotABarrel");
return;
}
// Vérifier si ce baril est déjà supporté
if (IsSupportedBarrel(barrel.PrefabName)) {
Message(player, "AlreadySupported", GetShortName(barrel.PrefabName));
return;
}
// Ajouter le baril à la liste
configData.SupportedBarrels.Add(barrel.PrefabName);
SaveConfig(configData);
// Rendre ce baril verrouillable immédiatement
barrel.isLockable = true;
barrel.SendNetworkUpdate();
barrel.SendNetworkUpdateImmediate();
string shortName = GetShortName(barrel.PrefabName);
Message(player, "BarrelAdded", shortName);
Puts($"Admin {player.displayName} added new barrel type: {barrel.PrefabName}");
}
}
private string GetShortName(string prefabName)
{
return prefabName.Split('/').LastOrDefault()?.Replace(".prefab", "") ?? prefabName;
}
private bool IsValidBarrel(BoxStorage storage)
{
if (storage == null || string.IsNullOrEmpty(storage.PrefabName))
return false;
// Vérifier que le prefab contient "barrel" dans son nom (insensible à la casse)
return storage.PrefabName.ToLower().Contains("barrel");
}
private void CmdAddBarrel(BasePlayer player, string command, string[] args) {
if(!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)){
Message(player, "Usage");
return;
}
// Toggle le mode d'ajout
if (playersInAddMode.Contains(player.userID)) {
// Désactiver le mode
playersInAddMode.Remove(player.userID);
Message(player, "AddModeDisabled");
Puts($"Admin {player.displayName} disabled barrel add mode");
} else {
// Activer le mode
playersInAddMode.Add(player.userID);
Message(player, "AddModeEnabled");
Puts($"Admin {player.displayName} enabled barrel add mode");
}
}
private void CmdListBarrels(BasePlayer player, string command, string[] args) {
if(!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)){
Message(player, "Usage");
return;
}
Message(player, "BarrelListHeader", configData.SupportedBarrels.Count);
foreach (var barrel in configData.SupportedBarrels) {
string shortName = barrel.Split('/').LastOrDefault()?.Replace(".prefab", "") ?? barrel;
SendReply(player, $"- {shortName}");
}
}
private void CmdCleanBarrels(BasePlayer player, string command, string[] args) {
if(!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)){
Message(player, "Usage");
return;
}
int originalCount = configData.SupportedBarrels.Count;
// Supprimer les doublons en gardant uniquement les éléments distincts
configData.SupportedBarrels = configData.SupportedBarrels.Distinct().ToList();
int newCount = configData.SupportedBarrels.Count;
int duplicatesRemoved = originalCount - newCount;
SaveConfig(configData);
if (duplicatesRemoved > 0) {
Message(player, "DuplicatesRemoved", duplicatesRemoved, newCount);
Puts($"Admin {player.displayName} cleaned {duplicatesRemoved} duplicate barrel entries");
} else {
Message(player, "NoDuplicates");
}
}
private void CmdResetConfig(BasePlayer player, string command, string[] args) {
if(!permission.UserHasPermission(player.UserIDString, configData.PermAdmin)){
Message(player, "Usage");
return;
}
// Réinitialiser la configuration avec les valeurs par défaut
configData = GetDefaultConfig();
SaveConfig(configData);
Message(player, "ConfigReset");
Puts($"Admin {player.displayName} reset the plugin configuration");
}
void OnPlayerDisconnected(BasePlayer player, string reason)
{
if (playersInAddMode.Contains(player.userID))
{
playersInAddMode.Remove(player.userID);
Puts($"Admin {player.displayName} left barrel add mode (disconnected)");
}
}
protected override void LoadDefaultMessages()
{
// Messages en anglais
lang.RegisterMessages(new Dictionary<string, string>
{
{"Usage", "You do not have permission to use this command"},
{"Success", "Refreshing is done"},
{"NeedHammer", "You need to have a hammer in your hands to add a new barrel type"},
{"NoTargetFound", "No target found. Look at a barrel and try again"},
{"NotABarrel", "The target is not a barrel (only barrels are supported)"},
{"AlreadySupported", "This barrel type is already supported: {0}"},
{"BarrelAdded", "Successfully added new barrel type: {0}"},
{"BarrelListHeader", "Currently supported barrel types ({0} total):"},
{"DuplicatesRemoved", "Removed {0} duplicate entries. Total barrels: {1}"},
{"NoDuplicates", "No duplicates found in the barrel list"},
{"AddModeEnabled", "Barrel add mode ENABLED. Hit barrels with hammer to add them!"},
{"AddModeDisabled", "Barrel add mode DISABLED"},
{"AddModeDisabledNoHammer", "Barrel add mode disabled (no hammer in hand)"},
{"ConfigReset", "Configuration has been reset to default values"}
}, this, "en");
// Messages en français
lang.RegisterMessages(new Dictionary<string, string>
{
{"Usage", "Vous n'avez pas la permission d'utiliser cette commande"},
{"Success", "Actualisation terminée"},
{"NeedHammer", "Vous devez avoir un marteau en main pour ajouter un nouveau type de baril"},
{"NoTargetFound", "Aucune cible trouvée. Regardez vers un baril et réessayez"},
{"NotABarrel", "La cible n'est pas un baril (seuls les barils sont supportés)"},
{"AlreadySupported", "Ce type de baril est déjà supporté : {0}"},
{"BarrelAdded", "Nouveau type de baril ajouté avec succès : {0}"},
{"BarrelListHeader", "Types de barils actuellement supportés ({0} au total) :"},
{"DuplicatesRemoved", "{0} doublons supprimés. Total de barils : {1}"},
{"NoDuplicates", "Aucun doublon trouvé dans la liste des barils"},
{"AddModeEnabled", "Mode d'ajout de barils ACTIVÉ. Tapez sur les barils avec le marteau pour les ajouter !"},
{"AddModeDisabled", "Mode d'ajout de barils DÉSACTIVÉ"},
{"AddModeDisabledNoHammer", "Mode d'ajout de barils désactivé (pas de marteau en main)"},
{"ConfigReset", "La configuration a été réinitialisée aux valeurs par défaut"}
}, this, "fr");
}
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
private void Message(BasePlayer player, string key, params object[] args) {
SendReply(player, Lang(key, player.UserIDString, args));
}
}
}