C#:
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<string, PlayerData> 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<string, int> GroupLandLimits { get; set; }
public Dictionary<string, int> 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<Vector3> LandMachinePositions { get; set; }
public List<Vector3> WaterMachinePositions { get; set; }
}
protected override void LoadDefaultConfig()
{
ConfigData config = new ConfigData
{
DefaultLandLimit = 5,
DefaultWaterLimit = 3,
GroupLandLimits = new Dictionary<string, int>
{
{ "default", 5 },
{ "vip", 10 }
},
GroupWaterLimits = new Dictionary<string, int>
{
{ "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<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.",
["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<string, string>
{
["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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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<Vector3>(), WaterMachinePositions = new List<Vector3>() };
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);
}
}
}