Prevent underwater vending machines?

Is there a plugin that will block putting vending machines in water ?

I found a similar topic, but the plugin was removed, why?

One guy posted this:

void OnItemDeployed(Deployer deployer, BaseCombatEntity entity, BaseEntity slotEntity)
        {
            if (entity.pickup.itemTarget == null || !entity.pickup.itemTarget.shortname.Contains("vending"))
                return;
            if (entity.transform.position.y > WaterSystem.OceanLevel - 1f)
                return;
            //entity is under water
            entity.Kill();
        }

but this code in plugin doesn't work, help, thx

Hi. I tried using the CanDeployItem hook, but for some reason, it doesn't get called at all. You can try using OnEntitySpawned instead.

void OnEntitySpawned(VendingMachine vending)
{
	if (vending.OwnerID.IsSteamId() && vending.transform.position.y < WaterSystem.OceanLevel - 1f)
	{
		var player = BasePlayer.FindByID(vending.OwnerID);
		if (player != null)
		{
			//You can add refund logic as the player loses the item on deployment
            player.ChatMessage("*Your Warning Message*");
        }
        vending.Kill();
    }
}

And don't forget that when the server is started, this hook will also be triggered. Don't forget to add an unsubscribe in Init and a subscribe in OnServerInitialized to this hook.

Hi, played a little with chatgpt and the plugin works. However, the permissions I tried to install don't work. They are registered, but nothing happens when they are awarded. Maybe someone can take a look over it.

using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("NoUnderwaterVendingMachines", "ChatGPT", "1.0.0")]
    [Description("Prevents placing vending machines underwater and manages placement permissions.")]

    class NoUnderwaterVendingMachines : CovalencePlugin
    {
        private const string PermCanPlace = "nounderwatervendingmachines.canplace";
        private const string PermCanPlaceLimited = "nounderwatervendingmachines.canplacelimited";

        private Dictionary<string, int> playerLimits = new Dictionary<string, int>();

        private ConfigData configData;

        private class ConfigData
        {
            public int DefaultLimit { get; set; }
            public Dictionary<string, int> GroupLimits { get; set; }
        }

        protected override void LoadDefaultConfig()
        {
            ConfigData config = new ConfigData
            {
                DefaultLimit = 3,
                GroupLimits = new Dictionary<string, int>
                {
                    { "default", 3 },
                    { "vip", 10 }
                }
            };

            Config.WriteObject(config, true);
        }

        private void Init()
        {
            permission.RegisterPermission(PermCanPlace, this);
            permission.RegisterPermission(PermCanPlaceLimited, this);

            configData = Config.ReadObject<ConfigData>();

            // Laden der Sprachdateien
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["CannotPlaceUnderwater"] = "You cannot place vending machines underwater.",
                ["ReachedLimit"] = "You have reached the limit for placing vending machines.",
                ["NoPermission"] = "You do not have permission to place vending machines.",
                ["CheckLimit"] = "You have placed {0} out of {1} allowed vending machines.",
                ["NoLimitedPermission"] = "You do not have a limited permission to place vending machines."
            }, this);

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["CannotPlaceUnderwater"] = "Du kannst keine Verkaufsautomaten unter Wasser platzieren.",
                ["ReachedLimit"] = "Du hast das Limit für das Platzieren von Verkaufsautomaten erreicht.",
                ["NoPermission"] = "Du hast keine Berechtigung, Verkaufsautomaten zu platzieren.",
                ["CheckLimit"] = "Du hast {0} von {1} erlaubten Verkaufsautomaten platziert.",
                ["NoLimitedPermission"] = "Du hast keine eingeschränkte Berechtigung, Verkaufsautomaten zu platzieren."
            }, this, "de");
        }

        private string GetMessage(string key, string userId = null) => lang.GetMessage(key, this, userId);

        private bool IsUnderwater(BaseEntity entity)
        {
            return entity.transform.position.y < TerrainMeta.WaterMap.GetHeight(entity.transform.position);
        }

        private bool CanPlaceVendingMachine(BasePlayer player)
        {
            // Debugging: Ausgabe der UserID und Überprüfung der Berechtigungen
            Puts($"Checking permissions for player {player.displayName} ({player.UserIDString})");

            if (permission.UserHasPermission(player.UserIDString, PermCanPlace))
            {
                Puts($"{player.displayName} has permission to place vending machines.");
                return true;
            }

            if (permission.UserHasPermission(player.UserIDString, PermCanPlaceLimited))
            {
                Puts($"{player.displayName} has limited permission to place vending machines.");

                if (!playerLimits.ContainsKey(player.UserIDString))
                    playerLimits[player.UserIDString] = 0;

                int limit = GetLimit(player);
                if (playerLimits[player.UserIDString] < limit)
                {
                    playerLimits[player.UserIDString]++;
                    Puts($"{player.displayName} has placed {playerLimits[player.UserIDString]} out of {limit} allowed vending machines.");
                    return true;
                }
                else
                {
                    player.ChatMessage(GetMessage("ReachedLimit", player.UserIDString));
                    Puts($"{player.displayName} has reached the limit for placing vending machines.");
                    return false;
                }
            }

            player.ChatMessage(GetMessage("NoPermission", player.UserIDString));
            Puts($"{player.displayName} does not have permission to place vending machines.");
            return false;
        }

        private int GetLimit(BasePlayer player)
        {
            foreach (var group in permission.GetUserGroups(player.UserIDString))
            {
                if (configData.GroupLimits.ContainsKey(group))
                    return configData.GroupLimits[group];
            }

            return configData.DefaultLimit;
        }

        private object OnEntityBuilt(Planner planner, GameObject go)
        {
            BaseEntity entity = go.ToBaseEntity();
            BasePlayer player = planner.GetOwnerPlayer();

            if (entity == null || player == null)
                return null;

            if (entity is VendingMachine)
            {
                if (IsUnderwater(entity))
                {
                    entity.Kill();
                    player.inventory.GiveItem(ItemManager.CreateByName("vending.machine"));
                    player.ChatMessage(GetMessage("CannotPlaceUnderwater", player.UserIDString));
                    Puts($"{player.displayName} tried to place a vending machine underwater.");
                    return false;
                }

                if (!CanPlaceVendingMachine(player))
                {
                    entity.Kill();
                    player.inventory.GiveItem(ItemManager.CreateByName("vending.machine"));
                    return false;
                }
            }

            return null;
        }

        [ChatCommand("checklimit")]
        private void CheckLimitCommand(IPlayer player, string command, string[] args)
        {
            if (player == null || !player.IsServer)
                return;

            BasePlayer basePlayer = player.Object as BasePlayer;
            if (basePlayer == null)
                return;

            if (permission.UserHasPermission(player.Id, PermCanPlaceLimited))
            {
                int placedMachines = playerLimits.ContainsKey(player.Id) ? playerLimits[player.Id] : 0;
                basePlayer.ChatMessage(string.Format(GetMessage("CheckLimit", player.Id), placedMachines, GetLimit(basePlayer)));
            }
            else
            {
                basePlayer.ChatMessage(GetMessage("NoLimitedPermission", player.Id));
            }
        }
    }
}
​


Merged post

It work now with permission. Standard is prevent from placing any vending machine. Under and above water. You can grant permission for above water, under water and than set a limit for under water in config file.
It has also a data file where the vending machine positions are saved if group or user has permission.
It also has language file to translate if needed.

Permissions
nounderwatervendingmachines.canplace.abovewater
nounderwatervendingmachines.canplace.underwater
nounderwatervendingmachines.canplace.limited

Please let me know if you test it how it works. I also have upload it here and it waits for approval.

using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("NoUnderwaterVendingMachines", "Omegablue", "1.0.0")]
    [Description("Prevents placing vending machines underwater and manages placement permissions.")]

    class NoUnderwaterVendingMachines : CovalencePlugin
    {
        private const string PermCanPlaceAboveWater = "nounderwatervendingmachines.canplace.abovewater";
        private const string PermCanPlaceUnderwater = "nounderwatervendingmachines.canplace.underwater";
        private const string PermCanPlaceLimited = "nounderwatervendingmachines.canplace.limited";
        private const string DataFileName = "NoUnderwaterVendingMachinesData";

        private Dictionary<string, PlayerData> playerData;
        private ConfigData configData;

        private class ConfigData
        {
            public int DefaultLimit { get; set; }
            public Dictionary<string, int> GroupLimits { get; set; }
        }

        private class PlayerData
        {
            public int PlacedMachines { get; set; }
            public List<Vector3> MachinePositions { get; set; }
        }

        protected override void LoadDefaultConfig()
        {
            ConfigData config = new ConfigData
            {
                DefaultLimit = 3,
                GroupLimits = new Dictionary<string, int>
                {
                    { "default", 3 },
                    { "vip", 10 }
                }
            };

            Config.WriteObject(config, true);
        }

        private void Init()
        {
            permission.RegisterPermission(PermCanPlaceAboveWater, this);
            permission.RegisterPermission(PermCanPlaceUnderwater, this);
            permission.RegisterPermission(PermCanPlaceLimited, this);

            configData = Config.ReadObject<ConfigData>();
            playerData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, PlayerData>>(DataFileName) ?? new Dictionary<string, PlayerData>();

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["CannotPlaceUnderwater"] = "You cannot place vending machines underwater.",
                ["ReachedLimit"] = "You have reached the limit for placing vending machines.",
                ["NoPermission"] = "You do not have permission to place vending machines.",
                ["CheckLimit"] = "You have placed {0} out of {1} allowed vending machines.",
                ["NoLimitedPermission"] = "You do not have a limited permission to place vending machines."
            }, this);

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["CannotPlaceUnderwater"] = "Du kannst keine Verkaufsautomaten unter Wasser platzieren.",
                ["ReachedLimit"] = "Du hast das Limit für das Platzieren von Verkaufsautomaten erreicht.",
                ["NoPermission"] = "Du hast keine Berechtigung, Verkaufsautomaten zu platzieren.",
                ["CheckLimit"] = "Du hast {0} von {1} erlaubten Verkaufsautomaten platziert.",
                ["NoLimitedPermission"] = "Du hast keine eingeschränkte Berechtigung, Verkaufsautomaten zu platzieren."
            }, this, "de");
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(DataFileName, playerData);
        }

        private string GetMessage(string key, string userId = null) => lang.GetMessage(key, this, userId);

        private bool IsUnderwater(BaseEntity entity)
        {
            return entity.transform.position.y < TerrainMeta.WaterMap.GetHeight(entity.transform.position);
        }

        private bool CanPlaceVendingMachine(BasePlayer player, BaseEntity entity)
        {
            if (entity == null || player == null)
                return false;

            if (IsUnderwater(entity))
            {
                if (permission.UserHasPermission(player.UserIDString, PermCanPlaceUnderwater))
                {
                    if (permission.UserHasPermission(player.UserIDString, PermCanPlaceLimited))
                    {
                        if (!playerData.ContainsKey(player.UserIDString))
                            playerData[player.UserIDString] = new PlayerData { PlacedMachines = 0, MachinePositions = new List<Vector3>() };

                        int limit = GetLimit(player);
                        if (playerData[player.UserIDString].PlacedMachines < limit)
                        {
                            return true;
                        }
                        else
                        {
                            player.ChatMessage(GetMessage("ReachedLimit", player.UserIDString));
                            return false;
                        }
                    }

                    player.ChatMessage(GetMessage("NoLimitedPermission", player.UserIDString));
                    return false;
                }

                player.ChatMessage(GetMessage("CannotPlaceUnderwater", player.UserIDString));
                return false;
            }
            else // Above water placement
            {
                if (permission.UserHasPermission(player.UserIDString, PermCanPlaceAboveWater))
                {
                    return true;
                }

                player.ChatMessage(GetMessage("NoPermission", player.UserIDString));
                return false;
            }
        }

        private int GetLimit(BasePlayer player)
        {
            foreach (var group in permission.GetUserGroups(player.UserIDString))
            {
                if (configData.GroupLimits.ContainsKey(group))
                    return configData.GroupLimits[group];
            }

            return configData.DefaultLimit;
        }

        private object OnEntityBuilt(Planner planner, GameObject go)
        {
            BaseEntity entity = go.ToBaseEntity();
            BasePlayer player = planner.GetOwnerPlayer();

            if (entity == null || player == null)
                return null;

            if (entity is VendingMachine)
            {
                if (!CanPlaceVendingMachine(player, entity))
                {
                    entity.Kill();
                    player.inventory.GiveItem(ItemManager.CreateByName("vending.machine"));
                    return false;
                }

                if (!playerData.ContainsKey(player.UserIDString))
                    playerData[player.UserIDString] = new PlayerData { PlacedMachines = 0, MachinePositions = new List<Vector3>() };

                playerData[player.UserIDString].MachinePositions.Add(entity.transform.position);
                playerData[player.UserIDString].PlacedMachines++;
                SaveData();
            }

            return null;
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            if (entity is VendingMachine)
            {
                VendingMachine vendingMachine = entity as VendingMachine;
                BasePlayer player = BasePlayer.FindByID(vendingMachine.OwnerID);
                if (player != null && playerData.ContainsKey(player.UserIDString))
                {
                    PlayerData data = playerData[player.UserIDString];
                    data.MachinePositions.Remove(vendingMachine.transform.position);
                    data.PlacedMachines = data.MachinePositions.Count;
                    SaveData();
                }
            }
        }
    }
}

thx a lot, it works, i clear code, because I don't need perms and data

and remove the code below too, it doesn’t allow you to install vend even on land(terrain):

                if (!CanPlaceVendingMachine(player))
                {
                    entity.Kill();
                    player.inventory.GiveItem(ItemManager.CreateByName("vending.machine"));
                    return false;
                }

Have changed the plugin name to ManageVendingPlacement and changed the perm logic. If someone need or want to test it let me know till it´s approved.
Now placement on land, in water and with limits are seperatly configurable.

Permissions

managevendingplacement.canplace.abovewater Allow above water

managevendingplacement.canplace.underwater Allow under water

managevendingplacement.canplace.limited.abovewater Allow above water with limit

managevendingplacement.canplace.limited.underwater Allow under water with limit

Configuration

{
  "AllowAboveWaterDefault": true,
  "AllowUnderWaterDefault": true,
  "DefaultLandLimit": 5,
  "DefaultWaterLimit": 3,
  "GroupLandLimits": {
    "default": 5,
    "vip": 10
  },
  "GroupWaterLimits": {
    "default": 3,
    "vip": 6
  }
}