RustTip

CanLootEntity

OxideCarbonEntity

Called to determine whether to loot entity.

Return true to allow the action and false to block it.

object CanLootEntity(BasePlayer basePlayer, LootableCorpse lootableCorpse)
object CanLootEntity(BasePlayer basePlayer, ResourceContainer resourceContainer)
object CanLootEntity(BasePlayer player, DroppedItemContainer droppedItemContainer)
object CanLootEntity(BasePlayer basePlayer, RidableHorse ridableHorse)
object CanLootEntity(BasePlayer player, StorageContainer storageContainer)
object CanLootEntity(BasePlayer player, ContainerIOEntity containerIOEntity)
object CanLootEntity(BasePlayer player, IndustrialCrafter industrialCrafter)
object CanLootEntity(object L1, WorldItem worldItem)
Method changed — check — the game method differs from the one the hook is recorded for in Oxide. The hook is still called, but its place may have shifted — worth checking after an update.

Parameters

basePlayer
BasePlayer
lootableCorpse
LootableCorpse

Return value

objectReturn non-null to cancel the game action.

Example

object — you can affect the game: return a value to change or cancel the action.

private object CanLootEntity(BasePlayer basePlayer, LootableCorpse lootableCorpse)
{
    Puts("CanLootEntity");

    // change nothing — the game continues as usual
    return null;

    // to affect the game:
    // return false; // non-null cancels the game action
}

Works in both Oxide and Carbon: Carbon loads Oxide plugins as is.

Injection point 1

Rust.opj (Oxide)
void LootableCorpse.RPC_LootCorpse(BaseEntity.RPCMessage)

Passes: BasePlayer basePlayer, LootableCorpse lootableCorpse

WorksReturnBehavior: ExitWhenValidTypeArgumentBehavior: UseArgumentString (l0, this)Assembly-CSharp.dll

Where it is called (this branch's game code)

// …
[RPC_Server.IsVisible(3f)]
private void RPC_LootCorpse(RPCMessage rpc)
{
	BasePlayer player = rpc.player;
	if (!player || !player.CanInteract() || !CanLoot(player) || containers == null || !player.inventory.loot.StartLootingEntity(this))
	{
		return;
	}
	if (Interface.CallHook("CanLootEntity", player, this) != null)
	{
		return;
	}
	using (FlagsUpdateScope flagsUpdateScope = StartSetFlags(FlagsUpdateMode.SendNetworkUpdate))
	{
		flagsUpdateScope.Set(Flags.Open, b: true);
	}
	for (int i = 0; i < containers.Length; i++)
// …

Injection point 2

Rust.opj (Oxide)
void ResourceContainer.StartLootingContainer(BaseEntity.RPCMessage)

Passes: BasePlayer basePlayer, ResourceContainer resourceContainer

WorksReturnBehavior: ExitWhenValidTypeArgumentBehavior: UseArgumentString (l0, this)Assembly-CSharp.dll

Where it is called (this branch's game code)

[BaseEntity.RPC_Server]
[BaseEntity.RPC_Server.IsVisible(3f)]
private void StartLootingContainer(BaseEntity.RPCMessage msg)
{
	BasePlayer player = msg.player;
	if ((bool)player && player.CanInteract() && lootable && player.inventory.loot.StartLootingEntity(baseEntity))
	{
		if (Interface.CallHook("CanLootEntity", player, this) != null)
		{
			return;
		}
		lastAccessTime = Time.realtimeSinceStartup;
		player.inventory.loot.AddContainer(container);
	}
}

Injection point 3

Rust.opj (Oxide)
void DroppedItemContainer.PlayerOpenLoot(BasePlayer)

Passes: BasePlayer player, DroppedItemContainer droppedItemContainer

WorksReturnBehavior: ExitWhenValidTypeArgumentBehavior: UseArgumentString (a0, this)Assembly-CSharp.dll

Where it is called (this branch's game code)

public void PlayerOpenLoot(BasePlayer player)
{
	if ((bool)player && player.CanInteract() && player.inventory.loot.StartLootingEntity(this))
	{
		if (Interface.CallHook("CanLootEntity", player, this) != null)
		{
			return;
		}
		SetFlagLocal(Flags.Open, b: true);
		player.inventory.loot.AddContainer(inventory);
		player.inventory.loot.SendImmediate();
		player.ClientRPC(RpcTarget.Player("RPC_OpenLootPanel", player), lootPanelName);
		SendNetworkUpdate();
// …

Injection point 4

Rust.opj (Oxide)
void RidableHorse.SERVER_OpenLoot(BaseEntity.RPCMessage)

Passes: BasePlayer basePlayer, RidableHorse ridableHorse

Method changed — checkReturnBehavior: ExitWhenValidTypeArgumentBehavior: UseArgumentString (l0, this)Assembly-CSharp.dll

Where it is called (this branch's game code)

// …
if (storageInventory == null)
{
	return;
}
BasePlayer player = rpc.player;
string text = rpc.read.String();
if (!(player == null) && player.CanInteract() && CanOpenStorage(player) && (!needsBuildingPrivilegeToUse || player.CanBuild()) && player.inventory.loot.StartLootingEntity(this))
{
	if (Interface.CallHook("CanLootEntity", player, this) != null)
	{
		return;
	}
	ItemContainer container = equipmentInventory;
	string arg = lootPanelName;
	if (text == "storage")
	{
		arg = storagePanelName;
// …

Injection point 5

Rust.opj (Oxide)
bool StorageContainer.PlayerOpenLoot(BasePlayer, string, bool)

Passes: BasePlayer player, StorageContainer storageContainer

WorksReturnBehavior: ExitWhenNonNullAssembly-CSharp.dll

Where it is called (this branch's game code)

public virtual bool PlayerOpenLoot(BasePlayer player, string panelToOpen = "", bool doPositionChecks = true)
{
	if (Interface.CallHook("CanLootEntity", player, this) != null)
	{
		return false;
	}
	if (IsLocked() || IsTransferring())
	{
		player.ShowToast(GameTip.Styles.Red_Normal, LockedMessage, false);
		return false;
	}
// …

Injection point 6

Rust.opj (Oxide)
bool ContainerIOEntity.PlayerOpenLoot(BasePlayer, string, bool)

Passes: BasePlayer player, ContainerIOEntity containerIOEntity

WorksReturnBehavior: ExitWhenNonNullAssembly-CSharp.dll

Where it is called (this branch's game code)

public virtual bool PlayerOpenLoot(BasePlayer player, string panelToOpen = "", bool doPositionChecks = true)
{
	if (Interface.CallHook("CanLootEntity", player, this) != null)
	{
		return false;
	}
	if ((needsBuildingPrivilegeToUse || StorageContainer.ShouldRequireAuthIfNoCodelock(this, requireAuthIfNotLocked)) && !player.CanBuild())
	{
		return false;
	}
	if (needsBuildingPrivilegeToUse && !player.CanBuild())
// …

Injection point 7

Rust.opj (Oxide)
bool IndustrialCrafter.PlayerOpenLoot(BasePlayer, string, bool)

Passes: BasePlayer player, IndustrialCrafter industrialCrafter

WorksReturnBehavior: ExitWhenNonNullAssembly-CSharp.dll

Where it is called (this branch's game code)

public virtual bool PlayerOpenLoot(BasePlayer player, string panelToOpen = "", bool doPositionChecks = true)
{
	if (Interface.CallHook("CanLootEntity", player, this) != null)
	{
		return false;
	}
	if (NeedsBuildingPrivilegeToUse && !player.CanBuild())
	{
		return false;
	}
	if (OnlyOneUser && IsOpen())
// …

Injection point 8

Rust.opj (Oxide)
void WorldItem.RPC_OpenLoot(BaseEntity.RPCMessage)

Passes: object L1, WorldItem worldItem

WorksReturnBehavior: ExitWhenValidTypeArgumentBehavior: UseArgumentString (L1, this)Assembly-CSharp.dll

Where it is called (this branch's game code)

// …
	return;
}
ItemModContainer component = item.info.GetComponent<ItemModContainer>();
if (!(component == null) && component.canLootInWorld)
{
	BasePlayer player = rpc.player;
	if ((bool)player && player.CanInteract() && !player.IsBlockedFromLootingByMountable() && CanOpenInSafeZone(player) && player.inventory.loot.StartLootingEntity(this))
	{
		if (Interface.CallHook("CanLootEntity", L1, this) != null)
		{
			return;
		}
		SetFlagLocal(Flags.Open, b: true);
		player.inventory.loot.AddContainer(item.contents);
		player.inventory.loot.SendImmediate();
		player.ClientRPC(RpcTarget.Player("RPC_OpenLootPanel", player), "generic_resizable");
		SendNetworkUpdate();
// …

Sources: Rust.opj from OxideMod/Oxide.Rust (MIT) and hook metadata of the Carbon documentation (MIT). Method code is decompiled from this branch's server.