GameServer.Hooks behaviour (game_server v1.0.296)

View Source

Behaviour for application-level hooks / callbacks.

Implement this behaviour to receive lifecycle events from core flows (registration, login, provider linking, deletion) and run custom logic.

A module implementing this behaviour can be configured with

config :game_server, :hooks_module, MyApp.HooksImpl

The default implementation is GameServer.Hooks.Default which is a no-op.

Summary

Functions

Call an arbitrary function exported by the configured hooks module.

When a hooks function is executed via call/3 or internal_call/3, an optional :caller can be provided in the options. The caller will be injected into the spawned task's process dictionary and is accessible via GameServer.Hooks.caller/0 (the raw value) or caller_id/0 (the numeric id when the value is a user struct or map containing :id).

Return the user struct for the current caller when available. This will attempt to resolve the caller via GameServer.Accounts.get_user!/1 when the caller is an integer id or a map containing an :id key. Returns nil when no caller or user is found.

Return a list of exported functions on the currently registered hooks module.

Call an internal lifecycle callback. When a callback is missing this returns a sensible default (eg. {:ok, attrs} for before callbacks) so domain code doesn't need to handle missing hooks specially in most cases.

Return the configured module that implements the hooks behaviour.

Register a module from a source file at runtime. We capture any compiler output (warnings or compile-time prints) and record a timestamp and status (ok, ok_with_warnings, error) in application environment so the admin UI can display diagnostics.

Types

hook_result(attrs_or_user)

@type hook_result(attrs_or_user) :: {:ok, attrs_or_user} | {:error, term()}

Callbacks

after_lobby_create(term)

@callback after_lobby_create(term()) :: any()

after_lobby_delete(term)

@callback after_lobby_delete(term()) :: any()

after_lobby_host_change(term, term)

@callback after_lobby_host_change(term(), term()) :: any()

after_lobby_join(t, term)

@callback after_lobby_join(GameServer.Accounts.User.t(), term()) :: any()

after_lobby_leave(t, term)

@callback after_lobby_leave(GameServer.Accounts.User.t(), term()) :: any()

after_lobby_update(term)

@callback after_lobby_update(term()) :: any()

after_user_kicked(t, t, term)

@callback after_user_kicked(
  GameServer.Accounts.User.t(),
  GameServer.Accounts.User.t(),
  term()
) :: any()

after_user_login(t)

@callback after_user_login(GameServer.Accounts.User.t()) :: any()

after_user_register(t)

@callback after_user_register(GameServer.Accounts.User.t()) :: any()

before_lobby_create(map)

@callback before_lobby_create(map()) :: hook_result(map())

before_lobby_delete(term)

@callback before_lobby_delete(term()) :: hook_result(term())

before_lobby_join(t, term, term)

@callback before_lobby_join(GameServer.Accounts.User.t(), term(), term()) ::
  hook_result({GameServer.Accounts.User.t(), term(), term()})

before_lobby_leave(t, term)

@callback before_lobby_leave(GameServer.Accounts.User.t(), term()) ::
  hook_result({GameServer.Accounts.User.t(), term()})

before_lobby_update(term, map)

@callback before_lobby_update(term(), map()) :: hook_result(map())

before_user_kicked(t, t, term)

@callback before_user_kicked(
  GameServer.Accounts.User.t(),
  GameServer.Accounts.User.t(),
  term()
) ::
  hook_result(
    {GameServer.Accounts.User.t(), GameServer.Accounts.User.t(), term()}
  )

Functions

call(name, args \\ [], opts \\ [])

Call an arbitrary function exported by the configured hooks module.

This is a safe wrapper that checks function existence, enforces an allow-list if configured and runs the call inside a short Task with a configurable timeout to avoid long-running user code.

Returns {:ok, result} | {:error, reason}

caller()

@spec caller() :: any() | nil

When a hooks function is executed via call/3 or internal_call/3, an optional :caller can be provided in the options. The caller will be injected into the spawned task's process dictionary and is accessible via GameServer.Hooks.caller/0 (the raw value) or caller_id/0 (the numeric id when the value is a user struct or map containing :id).

caller_id()

@spec caller_id() :: integer() | nil

caller_user()

@spec caller_user() :: GameServer.Accounts.User.t() | nil

Return the user struct for the current caller when available. This will attempt to resolve the caller via GameServer.Accounts.get_user!/1 when the caller is an integer id or a map containing an :id key. Returns nil when no caller or user is found.

exported_functions()

Return a list of exported functions on the currently registered hooks module.

The result is a list of maps like: [%{name: "start_game", arities: [2,3]}, ...] This is useful for tooling and admin UI to display what RPCs are available.

internal_call(name, args \\ [], opts \\ [])

Call an internal lifecycle callback. When a callback is missing this returns a sensible default (eg. {:ok, attrs} for before callbacks) so domain code doesn't need to handle missing hooks specially in most cases.

module()

Return the configured module that implements the hooks behaviour.

register_file(path)

Register a module from a source file at runtime. We capture any compiler output (warnings or compile-time prints) and record a timestamp and status (ok, ok_with_warnings, error) in application environment so the admin UI can display diagnostics.