OnCowMilk
OnCowMilk is called in Rust.Ai.Gen2.Cow.TryMilk right after the game creates the milk item and before it hands it to the player, letting you block, modify or replace the milk yield.
object OnCowMilk(Rust.Ai.Gen2.Cow cow, BasePlayer player, Item item)Parameters
| Parameter | Type | Description |
|---|---|---|
cow | Rust.Ai.Gen2.Cow | The Rust.Ai.Gen2.Cow entity that is being milked. Use it for position checks, owner checks (OwnerID) or to feed it back into other Gen2 animal hooks. |
player | BasePlayer | The BasePlayer who is interacting with the cow. This is the player that would receive the milk item, so it is the right argument for permission checks and messaging. |
item | Item | The milk Item that the game just created and is about to give to the player. You can inspect or modify its amount, skin or condition, or remove it yourself before returning. |
Return value
Return null (or nothing) to let the milk item be delivered as usual. Any non-null return removes the item the game created; returning a bool sets the return value of TryMilk (true still counts as a successful milking from the game's point of view, false counts as failure), while other non-bool values simply suppress the item.
How it works
The hook fires inside Rust.Ai.Gen2.Cow.TryMilk, after the milk item has been created with ItemManager.Create using the cow's configured milk definition and its current MilkedAmount(), and before the item is placed into the player's inventory. It fires once per milking attempt that reaches the item creation stage, so a cow that refuses the interaction, is not milkable yet, or has no milk definition never reaches this hook.
The cow argument is the Gen2 animal entity; player is the person doing the milking; item is the freshly created milk stack, still not owned by any container, which is why you can safely remove it or change its amount in the hook.
Declaring all three parameters with the exact types shown is the safest option. If you declare a specific type for cow and the game passes a different entity type, Oxide skips your method for that call, so avoid narrowing unless you know only that type reaches the hook.
Returning nothing keeps the milk. Returning anything non-null removes the created item and cancels the yield; returning a bool also controls the result of TryMilk itself, so false makes the game treat the milking as failed.
Example plugin: Limit milk yield per player with a cooldown
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Cow Milk Cooldown", "RustPluginGenerator", "1.0.0")]
[Description("Enforces a per-player cooldown between cow milkings and optionally boosts the yield.")]
public class CowMilkCooldown : RustPlugin
{
private const string PermBoost = "cowmilkcooldown.boost";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastMilked = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Cooldown seconds")]
public float CooldownSeconds { get; set; } = 60f;
[JsonProperty("Boosted milk amount")]
public int BoostedAmount { get; set; } = 2;
}
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>
{
["Cooldown"] = "This cow needs a break. Try again in {0} seconds."
}, 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(PermBoost, this);
}
private object OnCowMilk(Rust.Ai.Gen2.Cow cow, BasePlayer player, Item item)
{
if (player == null || item == null || player.IsNpc)
return null;
float now = Time.realtimeSinceStartup;
float last;
if (lastMilked.TryGetValue(player.userID, out last))
{
float remaining = config.CooldownSeconds - (now - last);
if (remaining > 0f)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, Mathf.CeilToInt(remaining)));
item.Remove();
return false;
}
}
lastMilked[player.userID] = now;
if (config.BoostedAmount > 1 && permission.UserHasPermission(player.UserIDString, PermBoost))
item.amount = config.BoostedAmount;
return null;
}
private void Unload()
{
lastMilked.Clear();
}
}
}The plugin applies a configurable cooldown between milkings per player. When OnCowMilk fires it checks the player against the stored timestamps; if the cooldown is still active it sends a lang message, removes the freshly created milk item and returns false so the game treats the milking as failed. Otherwise it records Time.realtimeSinceStartup and returns null so the milk is delivered normally. Timestamps are kept in memory only and unloaded with the plugin, which is enough for an anti-spam measure that resets on restart.
Common use cases
Anti-spam cooldowns
Track a per-player timestamp and cancel milkings that happen too close together, which stops players from automating repeated interactions with the same cow.
Boosted or scaled yield
Change
item.amountbefore returning, for example to double output for players with a VIP permission node.Restricted milk for flagged players
Block the milk entirely for players who lack a permission or are on a punish list by returning false and removing the item.
Pitfalls
The item is already created
If you decide the milk should not be delivered, remove the item or return a non-null value. Returning null alone always hands the milk over.
Parameter type narrowing
The hook is patched into
Rust.Ai.Gen2.Cow.TryMilk. Declaring a narrower type forcoworplayermakes Oxide skip the call whenever the argument is something else, so keep the documented types.Bool return also changes TryMilk
Returning false does not just drop the item; the game sees the milking as unsuccessful. Prefer returning true or a non-bool object if you only want to suppress the item.
Build a plugin with OnCowMilk
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 OnCowMilk
Generate