using System.Collections.Generic; using Oxide.Core; using Oxide.Core.Libraries.Covalence; using UnityEngine; namespace Oxide.Plugins { [Info("ManageVendingPlacement", "Omegablue", "1.0.2")] [Description("Manages placement of vending machines with permissions and limits for land and underwater.")] class ManageVendingPlacement : CovalencePlugin { private const string PermCanPlaceAboveWater = "managevendingplacement.canplace.abovewater"; private const string PermCanPlaceUnderwater = "managevendingplacement.canplace.underwater"; private const string PermCanPlaceLimitedAboveWater = "managevendingplacement.canplace.limited.abovewater"; private const string PermCanPlaceLimitedUnderwater = "managevendingplacement.canplace.limited.underwater"; private const string DataFileName = "ManageVendingPlacementData"; private Dictionary playerData; private ConfigData configData; private class ConfigData { public bool AllowAboveWaterDefault { get; set; } = true; public bool AllowUnderWaterDefault { get; set; } = true; public int DefaultLandLimit { get; set; } = 5; public int DefaultWaterLimit { get; set; } = 3; public Dictionary GroupLandLimits { get; set; } public Dictionary GroupWaterLimits { get; set; } public string ChatCommand { get; set; } = "vplimit"; // Default command name } private class PlayerData { public int LandPlacedMachines { get; set; } public int WaterPlacedMachines { get; set; } public List LandMachinePositions { get; set; } public List WaterMachinePositions { get; set; } } protected override void LoadDefaultConfig() { ConfigData config = new ConfigData { DefaultLandLimit = 5, DefaultWaterLimit = 3, GroupLandLimits = new Dictionary { { "default", 5 }, { "vip", 10 } }, GroupWaterLimits = new Dictionary { { "default", 3 }, { "vip", 6 } }, ChatCommand = "vplimit" }; Config.WriteObject(config, true); } private void Init() { permission.RegisterPermission(PermCanPlaceAboveWater, this); permission.RegisterPermission(PermCanPlaceUnderwater, this); permission.RegisterPermission(PermCanPlaceLimitedAboveWater, this); permission.RegisterPermission(PermCanPlaceLimitedUnderwater, this); configData = Config.ReadObject(); playerData = Interface.Oxide.DataFileSystem.ReadObject>(DataFileName) ?? new Dictionary(); lang.RegisterMessages(new Dictionary { ["CannotPlaceUnderwater"] = "You cannot place vending machines underwater.", ["ReachedLandLimit"] = "You have reached the land limit for placing vending machines.", ["ReachedWaterLimit"] = "You have reached the water 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.", ["RankLimits"] = "Rank: {0}\nLand Limits: {1}\nWater Limits: {2}", ["LimitsHeader"] = "Vending Machine Limits by Rank:" }, this); lang.RegisterMessages(new Dictionary { ["CannotPlaceUnderwater"] = "Du kannst keine Verkaufsautomaten unter Wasser platzieren.", ["ReachedLandLimit"] = "Du hast das Limit für das Platzieren von Verkaufsautomaten an Land erreicht.", ["ReachedWaterLimit"] = "Du hast das Limit für das Platzieren von Verkaufsautomaten unter Wasser 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.", ["RankLimits"] = "Rang: {0}\nLandlimits: {1}\nWasserlimits: {2}", ["LimitsHeader"] = "Limits für Verkaufsautomaten nach Rang:" }, this, "de"); AddCovalenceCommand(configData.ChatCommand, nameof(ShowRankLimits)); } 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; bool isUnderwater = IsUnderwater(entity); if (isUnderwater) { if (permission.UserHasPermission(player.UserIDString, PermCanPlaceUnderwater)) { if (permission.UserHasPermission(player.UserIDString, PermCanPlaceLimitedUnderwater)) { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; int limit = GetWaterLimit(player); if (limit == -1 || playerData[player.UserIDString].WaterPlacedMachines < limit) { return true; } else { player.ChatMessage(GetMessage("ReachedWaterLimit", player.UserIDString)); return false; } } else { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; return true; } } else { player.ChatMessage(GetMessage("CannotPlaceUnderwater", player.UserIDString)); return false; } } else // Above water placement { if (permission.UserHasPermission(player.UserIDString, PermCanPlaceAboveWater)) { if (permission.UserHasPermission(player.UserIDString, PermCanPlaceLimitedAboveWater)) { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; int limit = GetLandLimit(player); if (limit == -1 || playerData[player.UserIDString].LandPlacedMachines < limit) { return true; } else { player.ChatMessage(GetMessage("ReachedLandLimit", player.UserIDString)); return false; } } else { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; return true; } } else { player.ChatMessage(GetMessage("NoPermission", player.UserIDString)); return false; } } } private int GetLandLimit(BasePlayer player) { foreach (var group in permission.GetUserGroups(player.UserIDString)) { if (configData.GroupLandLimits.ContainsKey(group)) return configData.GroupLandLimits[group]; } return configData.DefaultLandLimit; } private int GetWaterLimit(BasePlayer player) { foreach (var group in permission.GetUserGroups(player.UserIDString)) { if (configData.GroupWaterLimits.ContainsKey(group)) return configData.GroupWaterLimits[group]; } return configData.DefaultWaterLimit; } 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 (IsUnderwater(entity)) { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; playerData[player.UserIDString].WaterMachinePositions.Add(entity.transform.position); playerData[player.UserIDString].WaterPlacedMachines++; } else { if (!playerData.ContainsKey(player.UserIDString)) playerData[player.UserIDString] = new PlayerData { LandPlacedMachines = 0, WaterPlacedMachines = 0, LandMachinePositions = new List(), WaterMachinePositions = new List() }; playerData[player.UserIDString].LandMachinePositions.Add(entity.transform.position); playerData[player.UserIDString].LandPlacedMachines++; } SaveData(); } return null; } private void OnEntityKill(BaseNetworkable entity) { if (entity is VendingMachine vendingMachine) { BasePlayer player = BasePlayer.FindByID(vendingMachine.OwnerID); if (player != null && playerData.ContainsKey(player.UserIDString)) { PlayerData data = playerData[player.UserIDString]; if (IsUnderwater(vendingMachine)) { data.WaterMachinePositions.Remove(vendingMachine.transform.position); data.WaterPlacedMachines = data.WaterMachinePositions.Count; } else { data.LandMachinePositions.Remove(vendingMachine.transform.position); data.LandPlacedMachines = data.LandMachinePositions.Count; } SaveData(); } } } private void ShowRankLimits(IPlayer player, string command, string[] args) { string header = GetMessage("LimitsHeader", player.Id); string message = $"{header}\n"; foreach (var group in configData.GroupLandLimits.Keys) { int landLimit = configData.GroupLandLimits[group]; int waterLimit = configData.GroupWaterLimits.ContainsKey(group) ? configData.GroupWaterLimits[group] : configData.DefaultWaterLimit; message += GetMessage("RankLimits", player.Id).Replace("{0}", group).Replace("{1}", landLimit.ToString()).Replace("{2}", waterLimit.ToString()) + "\n"; } player.Message(message); } } }