Lingara Lingara Belgeler Rehberler API Kütüphaneler Uygulamalar Oluştur Gömme Web uygulaması
Dil: Türkçe

Godot

Bu sayfa İngilizceden çevrilmiştir. İkisi arasında fark varsa İngilizce sayfa doğrudur. İngilizce sayfayı oku

Godot iki dil sunar ve Lingara’nın her biri için bir kiti vardır. Bir GDScript oyunu Lingara eklentisini kullanır. Bir Godot C# oyunu ise bir Unity oyununun kullandığı paketin aynısı olan Lingara.Embed paketini kullanır. Bir projede ikisinden yalnızca birini kullanın, asla ikisini birden kullanmayın. Aşağıdaki sekmeler her birini gösterir.

Kurulum

GDScript. Lingara eklentisini Godot Asset Library’den kurun, ardından Project Settings, Plugins altında etkinleştirin. Etkinleştirmek Lingara adında bir autoload ekler; her sahne ona /root/Lingara yolundan ulaşır.

C#. Lingara.Embed paketini projenize bir paket başvurusu olarak ekleyin. Aşağıdaki örnek düğüm LingaraEmbedNode paketin bir parçası değildir: kaynağını projenize ekleyin ve bir sahneye yerleştirin.

Belirteçleri sunucunuzdan alın

Kitlerin hiçbiri gizli anahtar tutmaz. Çekirdeğin bir belirtece ihtiyacı olduğunda kendi sunucunuza sorar; sunucunuz bir sunucu kiti ile bir belirteç üretir ve belirteci ve son kullanma zamanını yanıt olarak döndürür.

Eklentiyle, sunucunuzun belirteç rotasını Project Settings altında ayarlayın; Lingara onu kendi iş parçacığında çağırır. Rota oyuncunun oturumunu gerektiriyorsa onu bunun yerine çalışma zamanında ayarlayın, çünkü proje ayarları dışa aktarımınızın içinde gönderilir. Ya da token_needed sinyaline bağlanın ve her isteği kendiniz yanıtlayın. C# ile örnek düğüm, istemci bir belirteç istediğinde belirteç rotanıza istek gönderir. Her iki durumda da bir hatayı token_unavailable veya TokenUnavailable ile bildirin; böylece bekleyen çağrılar hemen başarısız olur.

Olayları her karede işleyin

Çekirdek ağ I/O’sunu kendi iş parçacığında yürütür. Eklentinin autoload’u onu her karede bir kez boşaltır ve her olay için bir sinyal yayar; böylece oyununuzun ihtiyaç duyduğu sinyallere bağlanırsınız ve hiçbir şeyi kendiniz boşaltmazsınız. C# düğümü _process içinde karede en fazla 256 olay boşaltır ve her birini bir Godot sinyali olarak yeniden yayar.

Aynı sinyaller, akışla gelen NPC yanıtlarını (bkz. NPC diyaloğu) ve alıştırma güncellemelerini (bkz. alıştırma sonuçları) taşır.

<PackageReference Include="Lingara.Embed" Version="0.1.0-alpha.6" />
Kod örneğinin dili

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])
Kod örneğinin dili

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"))