📡 Komunikacja skrypt ↔ host

KitsuneScript oferuje bogaty system komunikacji dwukierunkowej między skryptem a aplikacją hosta (Kotlin/Android). Możesz wysyłać dane i eventy w obie strony.

💡 Kluczowe pojęcia

🔄 Przepływ danych

// KIERUNEK: Host → Skrypt // global.params - Parametry wejściowe // emitToScript() - Eventy z hosta // KIERUNEK: Skrypt → Host // global.send() - Wysyłanie wartości // emit() - Emitowanie eventów

📤 Wysyłanie z skryptu do hosta

emit() - Emitowanie eventów

Funkcja emit(event, ...args) wysyła event do hosta z opcjonalnymi argumentami.

// Skrypt KitsuneScript // Prosty event bez argumentów emit("started"); // Event z argumentami emit("userAction", "click", 100, 200); // Event z mapą (obiektem) emit("dataReady", { status: "success", data: [1, 2, 3], timestamp: 1234567890 }); // Event z wieloma argumentami różnych typów emit("result", "processed", 42, ["a", "b"], {key: "value"});

global.send() - Wysyłanie wartości

Funkcja global.send(value) wysyła pojedynczą wartość do hosta. Wszystkie wysłane wartości są zbierane w result.sendResults.

// Skrypt KitsuneScript // Wysyłanie różnych typów global.send("Hello from script!"); global.send(42); global.send([1, 2, 3]); global.send({name: "Alice", age: 25}); // Typowy wzorzec - raportowanie postępu global.send({progress: 0, message: "Starting..."}); global.send({progress: 50, message: "Processing..."}); global.send({progress: 100, message: "Done!"});

📥 Odbieranie w skrypcie od hosta

global.params - Parametry wejściowe

Lista parametrów przekazanych z Kotlina przez runner.params.

// Skrypt KitsuneScript // Odczyt parametrów let name = global.params[0]; // Pierwszy parametr let age = global.params[1]; // Drugi parametr let config = global.params[2]; // Trzeci parametr (może być mapą) // Bezpieczny dostęp z wartością domyślną let timeout = global.params[3] ?? 5000; // Iterowanie po parametrach for (param in global.params) { log("Param: " + param); }

on() - Nasłuchiwanie na eventy

Konstrukcja on(event) { handler } rejestruje handler wywoływany gdy host wyśle event. Argumenty są dostępne przez obiekt event.

// Skrypt KitsuneScript // Prosty handler on("refresh") { log("Host requested refresh!"); // Wykonaj odświeżenie... emit("refreshDone"); } // Handler z argumentami - dostęp przez event.args on("updateUser") { let userId = event.args[0]; let newName = event.args[1]; log("Updating user " + userId + " to " + newName); log("Event name: " + event.name); // "updateUser" } // Wiele handlerów on("start") { log("Starting..."); } on("stop") { log("Stopping..."); } on("pause") { log("Pausing..."); }
💡 Obiekt event

W handlerze on() dostępny jest obiekt event z polami:

🔧 Strona Kotlin (Host)

Konfiguracja i uruchomienie

import rip.nerd.kitsunescript.api.KitsuneScriptRunner // 1. Utwórz instancję runnera val runner = KitsuneScriptRunner.createInstance("myScript") // 2. Zarejestruj własne host functions (np. logowanie) runner.register("log", HostFunction { args, _ -> println(args.joinToString(" ") { it.asString() }) Value.Null }) // 3. Ustaw parametry wejściowe runner.params = listOf("Alice", 25, mapOf("role" to "admin")) // 4. Nasłuchuj na global.send() ze skryptu runner.onSend { value -> println("Skrypt wysłał: ${value.asString()}") } // 5. Nasłuchuj na emit() ze skryptu runner.onScriptEvent("dataReady") { args -> val status = args.getOrNull(0)?.asMap()?.get("status") println("Dane gotowe, status: $status") } runner.onScriptEvent("userAction") { args -> val action = args.getOrNull(0)?.asString() val x = args.getOrNull(1)?.asDouble() val y = args.getOrNull(2)?.asDouble() println("Action: $action at ($x, $y)") } // 6. Uruchom skrypt val result = runner.execute(""" log("Started with params: " + global.params); on("refresh") { emit("dataReady", {status: "refreshed"}); } emit("dataReady", {status: "initial"}); "initialized"; """) // 7. Wyślij eventy do skryptu runner.emitToScript("refresh") runner.emitToScript("customEvent", "arg1", 42) // 8. Sprawdź wyniki println("Zwrócono: ${result.value}") println("Sukces: ${result.success}") println("Send results: ${result.sendResults}") // 8. Cleanup runner.dispose()

Wysyłanie eventów do skryptu - emitToScript()

// Kotlin // Bez argumentów runner.emitToScript("refresh") // Z argumentami runner.emitToScript("updateData", "newValue") runner.emitToScript("setPosition", 100, 200) runner.emitToScript("configure", mapOf("debug" to true))

Odbieranie eventów ze skryptu - onScriptEvent()

// Kotlin // Prosty handler runner.onScriptEvent("started") { _ -> println("Skrypt wystartował!") } // Handler z argumentami runner.onScriptEvent("result") { args -> val value = args.firstOrNull()?.asDouble() ?: 0.0 println("Wynik: $value") } // Handler z mapą runner.onScriptEvent("userData") { args -> val data = args.firstOrNull()?.asMap() val name = data?.get("name")?.asString() val age = data?.get("age")?.asDouble()?.toInt() println("User: $name ($age lat)") } // Usuwanie handlerów runner.removeScriptEventHandlers("result")

💡 Praktyczne przykłady

Przykład 1: Kalkulator z UI

// Kotlin - Activity val runner = KitsuneScriptRunner.createInstance("calculator") runner.onScriptEvent("result") { args -> val result = args.firstOrNull()?.asDouble() resultTextView.text = "Wynik: $result" } runner.onScriptEvent("error") { args -> val message = args.firstOrNull()?.asString() Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } runner.execute(""" on("calculate") { let a = global.params[0]; let op = global.params[1]; let b = global.params[2]; let result = 0; if (op == "+") result = a + b; else if (op == "-") result = a - b; else if (op == "*") result = a * b; else if (op == "/") { if (b == 0) { emit("error", "Nie można dzielić przez zero!"); return; } result = a / b; } emit("result", result); } """) // Użytkownik kliknął "=" calculateButton.setOnClickListener { runner.params = listOf(inputA.toDouble(), operator, inputB.toDouble()) runner.emitToScript("calculate") }

Przykład 2: Pobieranie danych z raportem postępu

// Kotlin runner.onScriptEvent("progress") { args -> val percent = args.getOrNull(0)?.asDouble()?.toInt() ?: 0 val message = args.getOrNull(1)?.asString() ?: "" progressBar.progress = percent statusText.text = message } runner.onScriptEvent("complete") { args -> val data = args.firstOrNull()?.asList() processData(data) } runner.execute(""" fn fetchData() { emit("progress", 0, "Inicjalizacja..."); // Symulacja pracy let items = []; for (i in 0..10) { emit("progress", i * 10, "Pobieranie elementu " + i + "..."); items.push({id: i, value: i * 2}); } emit("progress", 100, "Gotowe!"); emit("complete", items); } on("start") { fetchData(); } """) // Start pobierania runner.emitToScript("start")

Przykład 3: Chat/Messaging

// Kotlin runner.onScriptEvent("messageFromScript") { args -> val text = args.firstOrNull()?.asString() ?: "" addMessageToUI("🦊 Skrypt", text) } runner.execute(""" log("Chat bot initialized"); on("userMessage") { let message = global.params[0]; log("Otrzymano: " + message); // Prosta logika chatbota if (contains(toLowerCase(message), "cześć")) { emit("messageFromScript", "Cześć! Jak mogę pomóc?"); } else if (contains(toLowerCase(message), "pomoc")) { emit("messageFromScript", "Dostępne komendy: cześć, pomoc, czas, losuj"); } else if (contains(toLowerCase(message), "czas")) { emit("messageFromScript", "Niestety nie mam dostępu do zegara 😅"); } else if (contains(toLowerCase(message), "losuj")) { use "math"; let num = floor(random() * 100); emit("messageFromScript", "Wylosowano: " + num); } else { emit("messageFromScript", "Nie rozumiem. Napisz 'pomoc'"); } } emit("messageFromScript", "Witaj! Jestem botem KitsuneScript 🦊"); """) // Użytkownik wysłał wiadomość sendButton.setOnClickListener { val text = inputField.text.toString() runner.params = listOf(text) runner.emitToScript("userMessage") }

📋 Podsumowanie API

W skrypcie KitsuneScript

ElementKierunekOpis
emit(event, ...args)Skrypt → HostWyślij event z argumentami
global.send(value)Skrypt → HostWyślij wartość (zbierana w sendResults)
on(event) { handler }Host → SkryptNasłuchuj na event od hosta
event.argsW handlerze on()Lista argumentów z emitToScript()
event.nameW handlerze on()Nazwa eventu
global.paramsHost → SkryptParametry wejściowe z Kotlina
global.instanceIdHost → SkryptUnikalny ID instancji runnera

W Kotlin (Host)

MetodaKierunekOpis
runner.params = listOf(...)Host → SkryptUstaw parametry wejściowe
runner.emitToScript(event, ...)Host → SkryptWyślij event do skryptu
runner.withSourceLoader { }KonfiguracjaUstaw loader dla importów
runner.onScriptEvent(event) { }Skrypt → HostNasłuchuj na emit() ze skryptu
runner.onSend { }Skrypt → HostCallback dla global.send()
result.sendResultsSkrypt → HostLista wszystkich wysłanych wartości
📦 Import modułów

Aby używać import w skryptach, skonfiguruj sourceLoader:

val runner = KitsuneScriptRunner.createInstance("myScript") .withSourceLoader { path -> context.assets.open("scripts/$path").bufferedReader().readText() }
⚠️ Ważne