Lingara Lingara بەڵگەنامەکان ڕێنماییەکان API کتێبخانەکان ئەپەکان دروستکردن جێگیرکردن ئەپی وێب
زمان: سۆرانی

Godot

ئەم پەڕەیە لە ئینگلیزییەوە وەرگێڕدراوە. ئەگەر هەردووکیان جیاواز بوون، پەڕە ئینگلیزییەکە ڕاستە. پەڕە ئینگلیزییەکە بخوێنەوە

Godot دوو زمان پێشکەش دەکات، و Lingara بۆ هەر یەکێکیان کیتێکی هەیە. یارییەکی GDScript پێوەکراوی Lingara بەکاردەهێنێت. یارییەکی Godot ی C# Lingara.Embed بەکاردەهێنێت، هەمان پاکێج کە یارییەکی Unity بەکاری دەهێنێت. لە پرۆژەیەکدا یەکێکیان بەکاربهێنە، هەرگیز هەردووکیان نا. تابەکانی خوارەوە هەر یەکێکیان نیشان دەدەن.

دامەزراندن

GDScript. پێوەکراوی Lingara لە Godot Asset Library دابمەزرێنە، پاشان لەژێر Project Settings، Plugins چالاکی بکە. چالاککردنی autoload ێک بە ناوی Lingara زیاد دەکات، کە هەموو دیمەنێک لە /root/Lingara پێی دەگات.

C#. Lingara.Embed وەک ئاماژەیەکی پاکێج بۆ پرۆژەکەت زیاد بکە. گرێی نموونەی خوارەوە، LingaraEmbedNode، بەشێک نییە لە پاکێجەکە: سەرچاوەکەی بۆ پرۆژەکەت زیاد بکە و بیخەرە ناو دیمەنێکەوە.

تۆکن لە سێرڤەرەکەی خۆت وەربگرە

هیچ کام لە کیتەکان نهێنی هەڵناگرێت. کاتێک ناوکەکە پێویستی بە تۆکنێک بێت، لە سێرڤەرەکەی خۆت داوای دەکات، کە بە کیتی سێرڤەر یەکێک دروست دەکات و بە تۆکنەکە و کاتی بەسەرچوونی وەڵام دەداتەوە.

لەگەڵ پێوەکراوەکە، ڕێڕەوی تۆکنی سێرڤەرەکەت لەژێر Project Settings دیاری بکە و Lingara لەسەر thread ـی خۆی بانگی دەکات. ئەگەر ڕێڕەوەکە پێویستی بە دانیشتنی یاریزانەکە بێت، لە جیاتی ئەوە لە کاتی کارکردندا دیاری بکە، چونکە ڕێکخستنەکانی پرۆژە لەناو export ەکەتدا دەنێردرێن. یان token_needed ببەستەوە و خۆت وەڵامی هەر داواکارییەک بدەرەوە. لەگەڵ C#، گرێی نموونە هەر کاتێک کلاینتەکە داوای تۆکن بکات داواکارییەک بۆ ڕێڕەوی تۆکنەکەت دەنێرێت. بە هەر شێوەیەک، شکستێک بە token_unavailable یان TokenUnavailable ڕابگەیەنە، بۆ ئەوەی بانگکردنە چاوەڕوانەکان دەستبەجێ شکست بهێنن.

ڕووداوەکان لە هەر چوارچێوەیەکدا پرۆسێس بکە

ناوکەکە I/O ـی تۆڕەکەی لەسەر thread ـی خۆی کار پێدەکات. autoload ـی پێوەکراوەکە لە هەر چوارچێوەیەکدا یەک جار بەتاڵی دەکات و بۆ هەر ڕووداوێک یەک سیگناڵ دەردەکات، بۆیە تۆ ئەو سیگناڵانە دەبەستیتەوە کە یارییەکەت پێویستی پێیانە و هەرگیز خۆت هیچ شتێک بەتاڵ ناکەیت. گرێی C# لە _process دا بەتاڵ دەکات، لە هەر چوارچێوەیەکدا بەلایەنی زۆرەوە 256 ڕووداو، و هەر یەکێکیان دووبارە وەک سیگناڵێکی Godot دەردەکاتەوە.

هەمان سیگناڵەکان وەڵامە پارچەپارچەکانی NPC (بڕوانە گفتوگۆی NPC) و نوێکارییەکانی ڕاهێنان (بڕوانە ئەنجامەکانی ڕاهێنان) هەڵدەگرن.

<PackageReference Include="Lingara.Embed" Version="0.1.0-alpha.6" />
زمانی نموونەی کۆد

Godot C#

// Your own server mints the token: never put a client secret in a game. The
// continuation may run off the main thread, which the client allows.
private async Task FetchToken()
{
    try
    {
        using var response = await Http.PostAsync(TokenUrl, new StringContent("{}"));
        response.EnsureSuccessStatusCode();
        using var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
        Client?.ProvideToken(body.RootElement.GetProperty("token").GetString(), body.RootElement.GetProperty("expires_at").GetString());
    }
    catch (Exception e) when (e is HttpRequestException || e is JsonException || e is KeyNotFoundException)
    {
        Client?.TokenUnavailable(e.Message); // fail the waiting calls now
    }
}

GDScript

# The common case: set Project Settings > lingara/token_url to your server's
# token route, which answers exactly {"token", "expires_at"}. Lingara POSTs to
# it on its own thread whenever it needs a token. If the route needs the
# player's session, set it at run time instead (never in ProjectSettings,
# which ships inside the export):
func use_my_session(session_cookie: String) -> void:
	lingara.set_token_endpoint("https://game.example.com/lingara-token", {"cookie": session_cookie})


# Or answer each token_needed yourself, with whatever login your game has.
func _on_token_needed(_request: int, _reason: String) -> void:
	var http := HTTPRequest.new()
	add_child(http)
	http.request("https://game.example.com/lingara-token", [], HTTPClient.METHOD_POST, "{}")
	var reply: Array = await http.request_completed
	http.queue_free()
	var body: Variant = JSON.parse_string((reply[3] as PackedByteArray).get_string_from_utf8())
	if reply[1] == 200 and body is Dictionary:
		lingara.provide_token(body["token"], body["expires_at"])
	else:
		lingara.token_unavailable("the token route answered %d" % reply[1])
زمانی نموونەی کۆد

Godot C#

public override void _Process(double delta)
{
    if (Client == null) return;
    events.Clear();
    Client.Drain(events); // at most 256 a frame; the rest wait for the next
    foreach (var e in events)
    {
        switch (e)
        {
            case EmbedEvent.TokenNeeded _: _ = FetchToken(); break;
            case EmbedEvent.NpcTurn { Update: NpcTurnUpdate.Fragment f } t:
                EmitSignal(SignalName.NpcTurnFragment, t.Dialogue.Value, t.Request.Value, f.Text); break;
            case EmbedEvent.NpcTurn { Update: NpcTurnUpdate.Finished f } t:
                EmitSignal(SignalName.NpcTurnFinished, t.Dialogue.Value, t.Request.Value, f.Text); break;
            case EmbedEvent.Practice p: EmitSignal(SignalName.PracticeChanged, p.Session.Value, p.Snapshot.Phase.ToString()); break;
            case EmbedEvent.Failed f: EmitSignal(SignalName.Failed, f.Error.KindName, f.Error.Message, f.Error.Request?.Value ?? 0); break;
            case EmbedEvent.Log log: GD.Print($"[lingara] {log.Level} {log.Target}: {log.Message}"); break;
        }
    }
}

GDScript

# The Lingara autoload the plugin adds, reached by path and typed, so every
# call and signal below is checked against LingaraEmbed.
@onready var lingara: LingaraEmbed = get_node("/root/Lingara")

# Enable the plugin (Project > Project Settings > Plugins): it adds the
# Lingara autoload, which drains the core once per frame and emits one signal
# per event. Connect the signals your game needs; you never call drain.
func _ready() -> void:
	lingara.token_needed.connect(_on_token_needed)
	lingara.event_received.connect(_on_event)
	lingara.error_raised.connect(func(error: Dictionary) -> void: push_warning(error.message))
	lingara.practice_changed.connect(_on_practice_changed)
	lingara.practice_finished.connect(_on_practice_finished)
	mei.replied.connect(_on_mei_replied)


func _on_event(_id: String, event_type: String, _created_at: String, data: Dictionary) -> void:
	if event_type == "lesson_plan.ready":
		print("a plan is ready: ", data.get("plan_id"))