C#:
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Rust;
using Facepunch;
using UnityEngine;
using Newtonsoft.Json;
namespace Oxide.Plugins
{
[Info("Instant Grow", "Beast_", "1.0.1")]
[Description("Allows players with permission to instantly grow plants.")]
public class InstantGrow : RustPlugin
{
#region Fields
private Configuration config;
private Dictionary<string, DateTime> cooldowns = new Dictionary<string, DateTime>();
private Dictionary<string, PlayerData> playersData = new Dictionary<string, PlayerData>();
#endregion
#region Configuration
private class Configuration
{
[JsonProperty("Global Settings")]
public GlobalSettings globalSettings = new GlobalSettings();
[JsonProperty("Chat Settings")]
public ChatSettings chatSettings = new ChatSettings();
[JsonProperty("Grow Tiers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, GrowTier> growTiers = new Dictionary<string, GrowTier>
{
["instantgrow.use"] = new GrowTier
{
AllowManualGrow = true,
ManualCooldown = 60f,
AllowAutoGrow = false,
UseRadius = false,
Radius = 0f,
PlantersOnly = true,
MaxPlantsPerUse = 3
},
["instantgrow.vip"] = new GrowTier
{
AllowManualGrow = true,
ManualCooldown = 10f,
AllowAutoGrow = true,
UseRadius = true,
Radius = 5f,
PlantersOnly = false,
MaxPlantsPerUse = 0
}
};
public class GlobalSettings
{
[JsonProperty("Allowed Plant Shortnames (empty = all)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> AllowedPlants = new List<string>();
[JsonProperty("Blocked Plant Shortnames", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> BlockedPlants = new List<string>();
[JsonProperty("Allow Growing Other Players Plants")]
public bool AllowOtherPlayersPlants = false;
}
public class ChatSettings
{
[JsonProperty("Chat Commands")]
public string[] Commands = { "instantgrow", "grow" };
[JsonProperty("Auto Grow Toggle Command")]
public string AutoGrowCommand = "autogrow";
[JsonProperty("Chat Prefix")]
public string Prefix = "<color=#00cc00>[InstantGrow]</color>: ";
[JsonProperty("Icon SteamID")]
public ulong IconSteamId = 0;
}
public class GrowTier
{
[JsonProperty("Allow Manual Command")]
public bool AllowManualGrow { get; set; }
[JsonProperty("Manual Command Cooldown Seconds")]
public float ManualCooldown { get; set; }
[JsonProperty("Enable Auto Grow")]
public bool AllowAutoGrow { get; set; }
[JsonProperty("Use Radius")]
public bool UseRadius { get; set; }
[JsonProperty("Max Radius")]
public float Radius { get; set; }
[JsonProperty("Planters Only")]
public bool PlantersOnly { get; set; }
[JsonProperty("Max Plants Per Use (0 = Unlimited)")]
public int MaxPlantsPerUse { get; set; }
}
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null) throw new JsonException();
SaveConfig();
}
catch
{
PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig() => Config.WriteObject(config, true);
#endregion
#region Data
public class PlayerData
{
public bool AutoGrowEnabled;
}
private void LoadData()
{
try
{
playersData = Interface.GetMod().DataFileSystem.ReadObject<Dictionary<string, PlayerData>>(Name);
if (playersData == null)
{
playersData = new Dictionary<string, PlayerData>();
SaveData();
}
}
catch
{
playersData = new Dictionary<string, PlayerData>();
SaveData();
}
}
private void SaveData() => Interface.GetMod().DataFileSystem.WriteObject(Name, playersData);
private bool IsAutoGrowEnabled(string userId)
{
if (playersData.TryGetValue(userId, out var data))
{
return data.AutoGrowEnabled;
}
return false;
}
private void ToggleAutoGrow(string userId)
{
if (!playersData.TryGetValue(userId, out var data))
{
data = new PlayerData();
playersData[userId] = data;
}
data.AutoGrowEnabled = !data.AutoGrowEnabled;
}
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoPermission"] = "You do not have permission to use this command.",
["Cooldown"] = "You must wait <color=orange>{0}</color> seconds before using this command again.",
["InvalidSyntax"] = "Syntax: <color=yellow>/{0}</color> or <color=yellow>/{0} radius</color>",
["NoEntityFound"] = "No growable entity found where you are looking.",
["GrewEntity"] = "You instantly grew the plant!",
["GrewEntities"] = "You instantly grew <color=yellow>{0}</color> plants!",
["RadiusNotAllowed"] = "You do not have permission to use a radius.",
["RadiusTooLarge"] = "The radius you specified is too large. Max: <color=yellow>{0}</color>.",
["NoPlantsInRadius"] = "No growable plants found within radius.",
["AutoGrowEnabled"] = "Auto-Grow has been <color=green>ENABLED</color>.",
["AutoGrowDisabled"] = "Auto-Grow has been <color=red>DISABLED</color>.",
["PlantBlocked"] = "This plant type is blocked from instant growing.",
["NotOwner"] = "You cannot grow plants that do not belong to you.",
["PlantersOnly"] = "You can only grow plants inside a planter box."
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
{
var message = lang.GetMessage(key, this, userId);
return args.Length > 0 ? string.Format(message, args) : message;
}
private void Reply(BasePlayer player, string key, params object[] args)
{
Player.Message(player, Msg(key, player.UserIDString, args), config.chatSettings.Prefix, config.chatSettings.IconSteamId);
}
#endregion
#region Hooks
private void Init()
{
LoadData();
foreach (var perm in config.growTiers.Keys)
permission.RegisterPermission(perm, this);
}
private void OnServerInitialized()
{
AddCovalenceCommand(config.chatSettings.Commands, nameof(CmdGrow));
AddCovalenceCommand(config.chatSettings.AutoGrowCommand, nameof(CmdAutoGrow));
}
private void OnServerSave() => SaveData();
private void Unload()
{
SaveData();
cooldowns.Clear();
}
private void OnEntitySpawned(GrowableEntity entity)
{
if (entity == null) return;
NextTick(() =>
{
if (entity == null || entity.IsDestroyed || entity.OwnerID == 0) return;
if (!AllowedToGrowGlobal(entity, entity.OwnerID)) return;
if (!IsAutoGrowEnabled(entity.OwnerID.ToString())) return;
var tier = GetBestTier(entity.OwnerID.ToString());
if (tier != null && tier.AllowAutoGrow)
{
if (tier.PlantersOnly && !(entity.GetParentEntity() is PlanterBox)) return;
GrowPlant(entity);
}
});
}
#endregion
#region Commands
private void CmdAutoGrow(IPlayer basePlayer, string command, string[] args)
{
var player = basePlayer.Object as BasePlayer;
if (player == null) return;
var tier = GetBestTier(player.UserIDString);
if (tier == null || !tier.AllowAutoGrow)
{
Reply(player, "NoPermission");
return;
}
ToggleAutoGrow(player.UserIDString);
bool enabled = IsAutoGrowEnabled(player.UserIDString);
Reply(player, enabled ? "AutoGrowEnabled" : "AutoGrowDisabled");
}
private void CmdGrow(IPlayer basePlayer, string command, string[] args)
{
var player = basePlayer.Object as BasePlayer;
if (player == null) return;
var tier = GetBestTier(player.UserIDString);
if (tier == null || !tier.AllowManualGrow)
{
Reply(player, "NoPermission");
return;
}
if (tier.ManualCooldown > 0 && cooldowns.TryGetValue(player.UserIDString, out DateTime lastUse))
{
var remaining = (tier.ManualCooldown - (DateTime.Now - lastUse).TotalSeconds);
if (remaining > 0)
{
Reply(player, "Cooldown", Math.Ceiling(remaining));
return;
}
}
bool attemptedGrow = false;
int count = 0;
int max = tier.MaxPlantsPerUse > 0 ? tier.MaxPlantsPerUse : int.MaxValue;
bool useRadius = args.Length > 0 && (args[0] == "r" || args[0] == "radius");
if (useRadius)
{
if (!tier.UseRadius)
{
Reply(player, "RadiusNotAllowed");
return;
}
var plants = Pool.Get<List<GrowableEntity>>();
Vis.Entities(player.transform.position, tier.Radius, plants);
foreach (var plant in plants)
{
if (count >= max) break;
if (CheckAndGrow(plant, player.userID, tier))
{
count++;
}
}
if (count == 0 && plants.Count == 0)
{
Reply(player, "NoPlantsInRadius");
Pool.FreeUnmanaged(ref plants);
return;
}
else if (count == 0)
{
Reply(player, "NoPlantsInRadius");
Pool.FreeUnmanaged(ref plants);
return;
}
attemptedGrow = true;
Pool.FreeUnmanaged(ref plants);
}
else
{
if (!Physics.Raycast(player.eyes.HeadRay(), out RaycastHit hit, 5f, Layers.Mask.Harvestable))
{
Reply(player, "NoEntityFound");
return;
}
var entity = hit.GetEntity();
if (entity == null)
{
Reply(player, "NoEntityFound");
return;
}
var planter = entity as PlanterBox;
var plant = entity as GrowableEntity;
if (planter != null)
{
if (planter.children != null)
{
foreach (var child in planter.children)
{
if (count >= max) break;
if (child is GrowableEntity childPlant)
{
if (CheckAndGrow(childPlant, player.userID, tier)) count++;
}
}
}
if (count > 0) attemptedGrow = true;
else if (planter.children == null || planter.children.Count == 0)
{
Reply(player, "NoEntityFound");
return;
}
}
else if (plant != null)
{
if (CheckAndGrow(plant, player.userID, tier))
{
count = 1;
attemptedGrow = true;
}
}
else
{
Reply(player, "NoEntityFound");
return;
}
}
if (attemptedGrow)
{
if (count > 0)
{
if (tier.ManualCooldown > 0) cooldowns[player.UserIDString] = DateTime.Now;
if (count == 1) Reply(player, "GrewEntity");
else Reply(player, "GrewEntities", count);
}
}
}
#endregion
#region Helpers
private Configuration.GrowTier GetBestTier(string userId)
{
Configuration.GrowTier best = null;
foreach (var kvp in config.growTiers)
{
if (permission.UserHasPermission(userId, kvp.Key))
{
if (best == null) best = kvp.Value;
else
{
if (kvp.Value.Radius > best.Radius) best = kvp.Value;
else if (kvp.Value.Radius == best.Radius)
{
if (kvp.Value.ManualCooldown < best.ManualCooldown) best = kvp.Value;
}
}
}
}
return best;
}
private bool AllowedToGrowGlobal(GrowableEntity plant, ulong userId)
{
if (plant == null) return false;
if (config.globalSettings.BlockedPlants.Contains(plant.ShortPrefabName)) return false;
if (config.globalSettings.AllowedPlants.Count > 0 && !config.globalSettings.AllowedPlants.Contains(plant.ShortPrefabName)) return false;
if (!config.globalSettings.AllowOtherPlayersPlants && plant.OwnerID != 0 && plant.OwnerID != userId)
return false;
return true;
}
private bool CheckAndGrow(GrowableEntity plant, ulong userId, Configuration.GrowTier tier)
{
if (plant == null || plant.IsDead()) return false;
if (tier.PlantersOnly && !(plant.GetParentEntity() is PlanterBox)) return false;
if (!AllowedToGrowGlobal(plant, userId)) return false;
return GrowPlant(plant);
}
private bool GrowPlant(GrowableEntity plant)
{
if (plant == null || plant.IsDead() || plant.Properties == null) return false;
// mature?
if (plant.State >= PlantProperties.State.Mature) return false;
plant.ChangeState(PlantProperties.State.Fruiting, false);
return true;
}
#endregion
}
}