Lingara Lingara ឯកសារ មគ្គុទ្ទេសក៍សិក្សា API បណ្ណាល័យ កម្មវិធី បង្កើត បង្កប់ កម្មវិធីលើបណ្ដាញ
ភាសា: ខ្មែរ

Godot

ទំព័រនេះត្រូវបានបកប្រែពីភាសាអង់គ្លេស។ ប្រសិនបើទាំងពីរខុសគ្នា ទំព័រភាសាអង់គ្លេសគឺត្រឹមត្រូវ។ អានទំព័រភាសាអង់គ្លេស

Godot ផ្ដល់ភាសាពីរ ហើយ Lingara មានកញ្ចប់ឧបករណ៍មួយសម្រាប់ភាសានីមួយៗ។ ហ្គេម GDScript ប្រើ addon របស់ Lingara។ ហ្គេម Godot C# ប្រើ Lingara.Embed ដែលជាកញ្ចប់ដូចគ្នាដែលហ្គេម Unity ប្រើ។ ប្រើមួយ ឬមួយទៀតនៅក្នុងគម្រោងមួយ មិនដែលប្រើទាំងពីរទេ។ ផ្ទាំង (tab) ខាងក្រោមបង្ហាញនីមួយៗ។

ដំឡើង

GDScript. ដំឡើង addon របស់ Lingara ពី Godot Asset Library បន្ទាប់មកបើកវានៅក្រោម Project Settings, Plugins។ ការបើកវាបន្ថែម autoload មួយឈ្មោះ Lingara ដែលឈុតឆាក (scene) នីមួយៗអាចទៅដល់នៅ /root/Lingara។

C#. បន្ថែម Lingara.Embed ទៅក្នុងគម្រោងរបស់អ្នកជា package reference។ node គំរូខាងក្រោម LingaraEmbedNode មិនមែនជាផ្នែកមួយនៃកញ្ចប់ទេ៖ បន្ថែមកូដប្រភពរបស់វាទៅក្នុងគម្រោងរបស់អ្នក ហើយដាក់វានៅក្នុងឈុតឆាកមួយ។

យកតូខិនពីម៉ាស៊ីនមេរបស់អ្នក

គ្មានកញ្ចប់ឧបករណ៍ណាមួយកាន់សម្ងាត់ទេ។ នៅពេលស្នូលត្រូវការតូខិន វាសុំពីម៉ាស៊ីនមេផ្ទាល់ខ្លួនរបស់អ្នក ដែលបង្កើតតូខិនមួយដោយប្រើ កញ្ចប់ឧបករណ៍ម៉ាស៊ីនមេ ហើយឆ្លើយតបដោយតូខិន និងពេលផុតកំណត់របស់វា។

ជាមួយ addon សូមកំណត់ផ្លូវតូខិន (token route) នៃម៉ាស៊ីនមេរបស់អ្នកនៅក្រោម Project Settings ហើយ Lingara ហៅវានៅលើ thread ផ្ទាល់ខ្លួនរបស់វា។ ប្រសិនបើផ្លូវនោះត្រូវការសម័យរបស់អ្នកលេង សូមកំណត់វានៅពេលដំណើរការជំនួសវិញ ព្រោះការកំណត់គម្រោងត្រូវបានដាក់ភ្ជាប់ទៅក្នុង export របស់អ្នក។ ឬភ្ជាប់ token_needed ហើយឆ្លើយតបសំណើនីមួយៗដោយខ្លួនឯង។ ជាមួយ C# node គំរូផ្ញើទៅផ្លូវតូខិនរបស់អ្នក រាល់ពេលដែលក្លាយអិនសុំតូខិន។ មិនថាវិធីណាក៏ដោយ សូមរាយការណ៍ការបរាជ័យដោយប្រើ token_unavailable ឬ TokenUnavailable ដើម្បីឲ្យការហៅដែលកំពុងរង់ចាំបរាជ័យភ្លាមៗ។

ដំណើរការព្រឹត្តិការណ៍គ្រប់ហ្វ្រេម

ស្នូលដំណើរការ I/O បណ្ដាញរបស់វានៅលើ thread ផ្ទាល់ខ្លួនរបស់វា។ autoload របស់ addon បង្ហូរវាម្ដងក្នុងមួយហ្វ្រេម ហើយបញ្ចេញ signal មួយក្នុងមួយព្រឹត្តិការណ៍ ដូច្នេះអ្នកភ្ជាប់ signal ដែលហ្គេមរបស់អ្នកត្រូវការ ហើយមិនដែលបង្ហូរអ្វីដោយខ្លួនឯងទេ។ node C# បង្ហូរនៅក្នុង _process យ៉ាងច្រើនបំផុត 256 ព្រឹត្តិការណ៍ក្នុងមួយហ្វ្រេម ហើយបញ្ចេញព្រឹត្តិការណ៍នីមួយៗឡើងវិញជា signal របស់ Godot។

signal ដដែលទាំងនោះនាំមកនូវការឆ្លើយតប 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"))