Lingara Lingara Docs Guides API Libraries Apps Build Embed Web app
Language: English

Bevy

bevy_lingara is a Bevy plugin over Lingara’s player core. Add it to your app, tell it how to reach your server for tokens, and read what Lingara sends as ordinary Bevy Messages.

Add the plugin

Add the crate to your game, then add LingaraPlugin to your app with a LingaraConfig.

Get tokens from your server

The plugin never holds a secret. When it needs a token, it asks your own server, which mints one with a server kit and answers with the token and its expiry.

There are two ways to answer. In the common case, give the config your server’s token route and any header your session needs, and the plugin calls it for you. Or leave the route unset and answer each LingaraTokenNeeded Message yourself with a ProvideToken, using whatever sign-in your game already has.

Read events once per frame

The core runs its network I/O on its own thread and never calls into your code. The plugin drains its queue once per frame and turns what arrived into Messages your systems read like any other:

  • LingaraEventReceived for an event about the player, such as a lesson plan becoming ready;
  • NpcTranscript, a component on each character that grows as a reply streams in (see NPC dialogue);
  • PracticeFinished when a practice session ends (see practice results).

Nothing blocks a frame: a slow network shows up as a Message arriving a little later.

Bevy

cargo add bevy_lingara@0.1.0-alpha.6

Bevy

/// The common case: the plugin POSTs to your own server's token route, with
/// your game's session as a header, and reads `{token, expires_at}`.
fn lingara_config(session_header: bevy_lingara::lingara_embed::Header) -> LingaraConfig {
    LingaraConfig::new()
        .token_endpoint("https://game.example.com/lingara-token", vec![session_header])
        .source_lang("en")
}

/// Or keep the session in ECS: leave the token endpoint unset, answer each
/// `LingaraTokenNeeded` with what your server returned.
fn answer_token_requests(mut needed: MessageReader<LingaraTokenNeeded>, mut provide: MessageWriter<ProvideToken>) {
    for _request in needed.read() {
        let (token, expires_at) = fetch_from_your_server();
        provide.write(ProvideToken::new(token, expires_at));
    }
}

Bevy

App::new()
    .add_plugins(DefaultPlugins)
    .add_plugins(LingaraPlugin::new(lingara_config(header)))
    .add_systems(Update, on_lingara_event)

/// The plugin drains Lingara's events once per frame: read them as Messages.
fn on_lingara_event(mut events: MessageReader<LingaraEventReceived>) {
    for LingaraEventReceived(event) in events.read() {
        info!("{}: {}", event.event_type, event.data_json);
    }
}