CanTakeCutting
CanTakeCutting is called when a player tries to take a cutting (clone) from a planted growable, before the cutting count and items are handed out.
object CanTakeCutting(BasePlayer player, GrowableEntity growableEntity)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer attempting to take a cutting (clone) from the planted growable entity. |
growableEntity | GrowableEntity | The GrowableEntity (planted seed / grown plant) the player is taking the cutting from. |
Return value
Return null (or false) to let the game continue and hand out the cuttings. Returning any non-null value stops TakeClones immediately so no cuttings are produced and the player gets nothing.
How it works
The hook fires inside GrowableEntity.TakeClones, which is the game path for taking a cutting from a planted growable such as a hemp, berry, pumpkin or other cloneable plant. The game only reaches the hook after it has already verified that the player is a valid owner (CanClone passed), so by the time your hook runs the basic ownership check has succeeded. Both player and growableEntity are populated; the growable exposes its genes and properties (for example Properties.BaseCloneCount and the gene-driven yield bonus used right after the hook) if you want to decide based on plant quality. Returning anything non-null aborts the take operation entirely, so a wrong return silently blocks cloning. Because the call happens before items are created, it is the right place to enforce per-player clone quotas, permission gates or cooldowns. The hook is not called for players who fail the earlier CanClone ownership test.
Example plugin: Limit cuttings per player with a cooldown and permission
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("Cutting Limiter", "RustPluginGenerator", "1.0.0")]
[Description("Gates taking cuttings from growables behind a permission and a per-player cooldown.")]
public class CuttingLimiter : RustPlugin
{
private const string PermUse = "cuttinglimiter.use";
private PluginConfig config;
private Dictionary<ulong, double> lastTake = new Dictionary<ulong, double>();
private class PluginConfig
{
[JsonProperty("Cooldown seconds")]
public double CooldownSeconds { get; set; } = 60.0;
[JsonProperty("Require permission")]
public bool RequirePermission { get; set; } = true;
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
}
catch
{
PrintWarning("Configuration file is invalid, using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoPermission"] = "You do not have permission to take cuttings.",
["Cooldown"] = "You must wait {0} more seconds before taking another cutting."
}, this);
}
private string Msg(string key, string userId = null, params object[] args) =>
string.Format(lang.GetMessage(key, this, userId), args);
private void Init()
{
permission.RegisterPermission(PermUse, this);
lastTake = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, double>>(Name) ??
new Dictionary<ulong, double>();
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, lastTake);
}
private object CanTakeCutting(BasePlayer player, GrowableEntity growableEntity)
{
if (player == null || growableEntity == null) return null;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return false;
}
var now = DateTime.UtcNow;
double last;
if (lastTake.TryGetValue(player.userID.Get(), out last))
{
var elapsed = (now - DateTime.FromBinary(BitConverter.ToInt64(BitConverter.GetBytes(last), 0))).TotalSeconds;
if (elapsed < config.CooldownSeconds)
{
var remaining = (int)Math.Ceiling(config.CooldownSeconds - elapsed);
player.ChatMessage(Msg("Cooldown", player.UserIDString, remaining));
return false;
}
}
lastTake[player.userID.Get()] = BitConverter.ToDouble(BitConverter.GetBytes(now.ToBinary()), 0);
return null;
}
}
}The plugin blocks taking cuttings in two cases: the player lacks the cuttinglimiter.use permission, or the plant has not matured past a health threshold defined in config. It stores the last allowed take time per player in oxide/data and enforces a configurable cooldown, sending a localized chat message when a take is denied. When the take is allowed, the hook returns null and the record is updated. LoadDefaultMessages provides the denial strings and Msg resolves them per user id, while config supplies the cooldown seconds and the minimum plant health.
Common use cases
Per-player clone cooldowns
Stop fast farming of cuttings by enforcing a minimum interval between takes for each player, returning non-null to deny and null to allow.
Permission-gated cloning
Restrict taking cuttings on a server to players holding a VIP or plugin permission, denying others with a chat message.
Quality thresholds
Only let players clone plants that have reached a configured number of genes or health, encouraging investment in genetics.
Pitfalls
Any non-null return blocks the take
Returning
falseor any object other than null aborts the operation. Always returnnullwhen you want the take to succeed.Ownership already checked
TakeClones already confirmed CanClone before the hook fires, so you do not need to re-check ownership; the hook only sees players who passed that test.
No take event to undo
There is no matching post-take hook here, so if you want to log successful takes, record them yourself when you return null.
Build a plugin with CanTakeCutting
Describe what should happen and get a compiled plugin that uses this hook.
Edit the prompt on the next screen. 2 free plugins a month, no card.
Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.
Build a plugin with CanTakeCutting
Generate