Skip to content

Session

Runnable example

python/examples/session_inspect.py — read the current session's settings, connected users, and permission roles (read-only).

resoio.session.SessionClient

SessionClient(socket_path: str | None = None)

Bases: _BaseClient[SessionStub]

Async client for the Resonite IO Session service over a UDS.

Use as an async context manager so the gRPC channel closes deterministically.

Targeting (kick / ban / silence / respawn / role): pass local=True to target yourself, otherwise user_id is tried first and user_name is the fallback. user_name resolution fails if several connected users share the name -- prefer user_id for guests. Moderation and settings writes are host-gated: calling them without host permission raises gRPC PermissionDenied.

Source code in src/resoio/_client.py
def __init__(self, socket_path: str | None = None) -> None:
    # Defer resolution to __aenter__ so env vars patched between
    # construction and connection are honoured, and so resolution
    # errors surface at the connect site.
    self._explicit_path: str | None = socket_path
    self._channel: Channel | None = None
    self._stub: TStub | None = None
    self._resolved_path: str | None = None

get_settings async

get_settings() -> SessionSettings

Return the current session settings snapshot.

Source code in src/resoio/session.py
async def get_settings(self) -> SessionSettings:
    """Return the current session settings snapshot."""
    stub = self._require_stub()
    return _settings_from_proto(await stub.get_settings(GetSettingsRequest()))

apply_settings async

apply_settings(
    *,
    world_name: str | None = None,
    world_description: str | None = None,
    max_users: int | None = None,
    access_level: SessionAccessLevel | None = None,
    hide_from_listing: bool | None = None,
    mobile_friendly: bool | None = None,
    away_kick_enabled: bool | None = None,
    away_kick_minutes: float | None = None,
    auto_save_enabled: bool | None = None,
    auto_save_interval_minutes: float | None = None,
    auto_cleanup_enabled: bool | None = None,
    auto_cleanup_interval_seconds: float | None = None,
    tags: Sequence[str] | None = None,
) -> None

Patch the session settings; None kwargs are left unchanged.

Scalar / bool / string fields ride on the proto3 optional presence flag, so a None kwarg is simply not put on the wire. access_level=None sends the UNSPECIFIED sentinel ("leave unchanged"); a concrete value sets it. tags is replace-all: pass a sequence to replace the tag set (empty clears it) or None to leave the tags untouched.

Returns None by contract: the engine applies settings on its own thread, so a post-apply snapshot is not reliable in the same RPC. Call :meth:get_settings afterwards if you need the new state.

Source code in src/resoio/session.py
async def apply_settings(
    self,
    *,
    world_name: str | None = None,
    world_description: str | None = None,
    max_users: int | None = None,
    access_level: SessionAccessLevel | None = None,
    hide_from_listing: bool | None = None,
    mobile_friendly: bool | None = None,
    away_kick_enabled: bool | None = None,
    away_kick_minutes: float | None = None,
    auto_save_enabled: bool | None = None,
    auto_save_interval_minutes: float | None = None,
    auto_cleanup_enabled: bool | None = None,
    auto_cleanup_interval_seconds: float | None = None,
    tags: Sequence[str] | None = None,
    # 予約 (GameLibs が World.ResoniteLink API を公開したら復活):
    # resonite_link_enabled: bool | None = None,
) -> None:
    """Patch the session settings; ``None`` kwargs are left unchanged.

    Scalar / bool / string fields ride on the proto3 ``optional``
    presence flag, so a ``None`` kwarg is simply not put on the wire.
    ``access_level=None`` sends the ``UNSPECIFIED`` sentinel ("leave
    unchanged"); a concrete value sets it. ``tags`` is replace-all: pass
    a sequence to replace the tag set (empty clears it) or ``None`` to
    leave the tags untouched.

    Returns ``None`` by contract: the engine applies settings on its own
    thread, so a post-apply snapshot is not reliable in the same RPC.
    Call :meth:`get_settings` afterwards if you need the new state.
    """
    stub = self._require_stub()
    wire_access = (
        _PbSessionAccessLevel.UNSPECIFIED
        if access_level is None
        else _ACCESS_LEVEL_TO_WIRE[access_level]
    )
    patch = SessionSettingsPatch(
        world_name=world_name,
        world_description=world_description,
        max_users=max_users,
        access_level=wire_access,
        hide_from_listing=hide_from_listing,
        mobile_friendly=mobile_friendly,
        away_kick_enabled=away_kick_enabled,
        away_kick_minutes=away_kick_minutes,
        auto_save_enabled=auto_save_enabled,
        auto_save_interval_minutes=auto_save_interval_minutes,
        auto_cleanup_enabled=auto_cleanup_enabled,
        auto_cleanup_interval_seconds=auto_cleanup_interval_seconds,
        replace_tags=tags is not None,
        tags=list(tags) if tags is not None else [],
        # 予約 (GameLibs が World.ResoniteLink API を公開したら復活):
        # resonite_link_enabled=resonite_link_enabled,
    )
    await stub.apply_settings(patch)

list_users async

list_users() -> tuple[SessionUser, ...]

List the users connected to the current session.

Source code in src/resoio/session.py
async def list_users(self) -> tuple[SessionUser, ...]:
    """List the users connected to the current session."""
    stub = self._require_stub()
    response = await stub.list_users(ListUsersRequest())
    return tuple(_user_from_proto(u) for u in response.users)

kick_user async

kick_user(
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
    kind: KickKind = KickKind.KICK_AND_REVOKE,
) -> None

Kick a user from the session.

Source code in src/resoio/session.py
async def kick_user(
    self,
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
    kind: KickKind = KickKind.KICK_AND_REVOKE,
) -> None:
    """Kick a user from the session."""
    stub = self._require_stub()
    request = KickUserRequest(
        target=_target(user_id, user_name, local),
        kind=_KICK_KIND_TO_WIRE[kind],
    )
    await stub.kick_user(request)

ban_user async

ban_user(*, user_id: str = '', user_name: str = '', local: bool = False) -> None

Ban a user from the session.

Source code in src/resoio/session.py
async def ban_user(
    self,
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
) -> None:
    """Ban a user from the session."""
    stub = self._require_stub()
    request = BanUserRequest(target=_target(user_id, user_name, local))
    await stub.ban_user(request)

silence_user async

silence_user(
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
    silenced: bool = True,
) -> SessionUser

Silence (or unsilence) a user; returns the updated snapshot.

Source code in src/resoio/session.py
async def silence_user(
    self,
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
    silenced: bool = True,
) -> SessionUser:
    """Silence (or unsilence) a user; returns the updated snapshot."""
    stub = self._require_stub()
    request = SilenceUserRequest(
        target=_target(user_id, user_name, local),
        silenced=silenced,
    )
    response = await stub.silence_user(request)
    return _require_user(response.user)

respawn_user async

respawn_user(*, user_id: str = '', user_name: str = '', local: bool = False) -> None

Respawn a user.

With no target the engine respawns the local user.

Source code in src/resoio/session.py
async def respawn_user(
    self,
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
) -> None:
    """Respawn a user.

    With no target the engine respawns the local user.
    """
    stub = self._require_stub()
    request = RespawnUserRequest(target=_target(user_id, user_name, local))
    await stub.respawn_user(request)

respawn_self async

respawn_self() -> None

Respawn the local user (convenience for respawn_user(local=True)).

Source code in src/resoio/session.py
async def respawn_self(self) -> None:
    """Respawn the local user (convenience for
    ``respawn_user(local=True)``)."""
    await self.respawn_user(local=True)

set_user_role async

set_user_role(
    role_name: str, *, user_id: str = "", user_name: str = "", local: bool = False
) -> SessionUser

Assign role_name to a user; returns the updated snapshot.

Source code in src/resoio/session.py
async def set_user_role(
    self,
    role_name: str,
    *,
    user_id: str = "",
    user_name: str = "",
    local: bool = False,
) -> SessionUser:
    """Assign ``role_name`` to a user; returns the updated snapshot."""
    stub = self._require_stub()
    request = SetUserRoleRequest(
        target=_target(user_id, user_name, local),
        role_name=role_name,
    )
    response = await stub.set_user_role(request)
    return _require_user(response.user)

list_roles async

list_roles() -> SessionRoles

List the session's permission roles and default-role assignments.

Source code in src/resoio/session.py
async def list_roles(self) -> SessionRoles:
    """List the session's permission roles and default-role assignments."""
    stub = self._require_stub()
    return _roles_from_proto(await stub.list_roles(ListRolesRequest()))

get_user_role_overrides async

get_user_role_overrides() -> tuple[UserRoleOverride, ...]

List the per-user default-role overrides (DefaultUserPermissions).

Source code in src/resoio/session.py
async def get_user_role_overrides(self) -> tuple[UserRoleOverride, ...]:
    """List the per-user default-role overrides
    (``DefaultUserPermissions``)."""
    stub = self._require_stub()
    response = await stub.get_user_role_overrides(GetUserRoleOverridesRequest())
    return tuple(_override_from_proto(o) for o in response.overrides)

resoio.session.SessionSettings dataclass

SessionSettings(
    world_name: str,
    world_description: str,
    max_users: int,
    access_level: SessionAccessLevel,
    hide_from_listing: bool,
    mobile_friendly: bool,
    away_kick_enabled: bool,
    away_kick_minutes: float,
    auto_save_enabled: bool,
    auto_save_interval_minutes: float,
    auto_cleanup_enabled: bool,
    auto_cleanup_interval_seconds: float,
    tags: tuple[str, ...],
    session_id: str,
    is_host: bool,
)

Snapshot of the current session settings (Settings tab).

session_id / is_host are read-only metadata; the rest mirror the engine WorldConfiguration.

resoio.session.SessionUser dataclass

SessionUser(
    user_id: str,
    user_name: str,
    is_host: bool,
    is_local_user: bool,
    is_present_in_world: bool,
    is_silenced: bool,
    local_volume: float,
    role_name: str,
    platform: str,
    head_device: str,
)

One connected user (Users tab).

resoio.session.SessionRole dataclass

SessionRole(role_name: str, role_description: str, is_highest: bool, is_lowest: bool)

One permission role (Permissions tab).

resoio.session.SessionRoles dataclass

SessionRoles(
    roles: tuple[SessionRole, ...],
    default_anonymous_role: str,
    default_visitor_role: str,
    default_contact_role: str,
    default_host_role: str,
    default_owner_role: str,
)

The session's permission roles plus the default-role assignments.

resoio.session.UserRoleOverride dataclass

UserRoleOverride(user_id: str, role_name: str)

One DefaultUserPermissions entry (user id -> role name).

resoio.session.SessionAccessLevel

Bases: Enum

Session access level (mirrors SkyFrost.Base.SessionAccessLevel).

The wire UNSPECIFIED sentinel ("leave unchanged" on :meth:SessionClient.apply_settings) is deliberately omitted; use access_level=None for that.

resoio.session.KickKind

Bases: Enum

Kick variant (mirrors the engine KickRequestState).