> For the complete documentation index, see [llms.txt](https://wiki.redmodding.org/scripting-cyberpunk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.redmodding.org/scripting-cyberpunk/scripting/snippets-and-examples/player/inventory-listener.md).

# Inventory Listener

How to setup a listener that's called whenever an item is added to the player's inventory

[TransactionSystem](https://nativedb.red4ext.com/TransactionSystem) allows you to register a listener to the inventory of a game object, which is the player in our case. The listener must be a class that inherits [`InventoryScriptCallback`](https://nativedb.red4ext.com/InventoryScriptCallback), which you can define any (or none if you want) of the listed methods in the [documentation](https://nativedb.red4ext.com/InventoryScriptCallback).

When registered, the transaction system will call the respective method from the given listener whenever the source object's inventory changes.

{% tabs %}
{% tab title="REDScript" %}

```swift
module MyMod

public class InventoryListener extends ScriptableSystem {
  protected let m_inventoryListenerCallback: ref<InventoryListenerScriptCallback>;

  protected let m_inventoryListener: ref<InventoryScriptListener>;

  protected let m_player: ref<PlayerPuppet>;

  protected let m_transactionSystem: ref<TransactionSystem>;

  protected let m_itemToWatch: TweakDBID = t"Items.money"; // the tweakdb id of the item to watch

  protected func RegisterListener() -> Void {
    this.m_inventoryListenerCallback = new InventoryListenerScriptCallback();
    this.m_inventoryListenerCallback.RegisterController(this);
    this.m_inventoryListener = this.m_transactionSystem.RegisterInventoryListener(this.m_player, this.m_inventoryListenerCallback);
  }

  protected func UnregisterListener() -> Void {
    this.m_transactionSystem.UnregisterInventoryListener(this.m_player, this.m_inventoryListener);
    this.m_inventoryListenerCallback = null;
    this.m_inventoryListener = null;
  }

  protected func OnPlayerAttach(request: ref<PlayerAttachRequest>) -> Void {
    this.m_player = GameInstance.GetPlayerSystem(request.owner.GetGame()).GetLocalPlayerMainGameObject() as PlayerPuppet;
    this.m_transactionSystem = GameInstance.GetTransactionSystem(this.m_player.GetGame());

    this.RegisterListener();
  }

  public func OnItemQuantityChanged(id: TweakDBID, diff: Int32, total: Uint32, flaggedAsSilent: Bool) -> Void {
    if Equals(id, this.m_itemToWatch) {
      // the desired item was either added or removed from the player's inventory
      FTLog(diff > 0 ? "item added" : "item lost");
    }
  }

  public func OnDetach() -> Void {
    this.UnregisterListener();

    this.m_player = null;
    this.m_transactionSystem = null;
  }

  public static func GetInstance(gameInstance: GameInstance) -> ref<InventoryListener> {
    return GameInstance.GetScriptableSystemsContainer(gameInstance).Get(NameOf<InventoryListener>()) as InventoryListener;
  }
}

class InventoryListenerScriptCallback extends InventoryScriptCallback {
  public let m_controller: ref<InventoryListener>;

  public func RegisterController(controller: ref<InventoryListener>) -> Void {
    this.m_controller = controller;
  }

  public func UnregisterController() -> Void {
    this.m_controller = null;
  }

  public func OnItemQuantityChanged(item: ItemID, diff: Int32, total: Uint32, flaggedAsSilent: Bool) -> Void {
    if IsDefined(this.m_controller) {
      this.m_controller.OnItemQuantityChanged(ItemID.GetTDBID(item), diff, total, flaggedAsSilent);
    }
  }
}
```

{% endtab %}

{% tab title="Lua" %}
{% hint style="info" %}
TODO (Not sure if it's possible in Lua)
{% endhint %}
{% endtab %}
{% endtabs %}
