Jak działa akcja
Co Vovó robi z akcją od chwili, gdy pokazuje ją scena: co gwarantuje i na co akcja nie może liczyć. Dla osób piszących akcje, żeby je komuś przekazać albo sprzedać; jak napisać akcję, mówi strona Akcje.
Własna strona
Każda akcja to osobny dokument, w ramce, którą daje jej strona sceny: jej HTML, z wpisanymi w niego style.css i script.js, skrypt na końcu, więc działa, gdy HTML już jest. Jedna zepsuta akcja nie wywraca pozostałych. Scena pokazuje swoje akcje jedna nad drugą, w swojej kolejności, pierwszą na spodzie.
Ramka nie przyjmuje kliknięć ani klawiszy: na nakładkę się patrzy, nigdy się jej nie naciska. To, co robi osoba prowadząca transmisję, robi na padzie, w panelu akcji albo w Dostosuj, i dociera to do akcji jako zdarzenie.
Akcja słyszy zdarzenie tylko wtedy, gdy pokazuje ją otwarta strona, i tylko w aktywnym profilu. Gdy żadna strona nie jest otwarta, nic nie liczy obserwacji.
Bez sieci, nic nie zostaje w przeglądarce
Akcja sięga do własnych plików i do tego, co podaje jej Vovó, i do niczego więcej. Obrazy, dźwięki, filmy i czcionki pochodzą z plików akcji, po nazwie, albo z adresu, który podało zdarzenie (emotka, okładka, plik wybrany w Dostosuj), nigdy z internetu. Jej kod i style to tylko script.js i style.css: żadnego skryptu ani arkusza stylów z pliku czy skądinąd, żadnego eval, żadnego workera. fetch, XMLHttpRequest i WebSocket są odrzucane, także dla własnych plików akcji, więc dane, których potrzebuje, idą do jej skryptu. Pamięci przeglądarki (localStorage, ciasteczka, IndexedDB) tam nie ma: to, co akcja przechowuje, przechowuje w vovo.state.
O to, czego potrzebuje z zewnątrz, prosi Vovó, w ramach uprawnień, które deklaruje: wiersz na czacie, webhook po nazwie, dźwięk z padu, klip w oficjalnym odtwarzaczu.
Uruchamia ją każda otwarta strona
Ta sama akcja działa wszędzie, gdzie otwarta jest jej scena: w OBS, w oknie podglądu sceny, w karcie przeglądarki, w dwóch źródłach naraz. Każda kopia dostaje te same zdarzenia i rysuje to samo. Dlatego strona tylko rysuje i odtwarza, a o to, co ma się stać raz, prosi Vovó, która robi to raz dla stron proszących podczas obsługi jednego zdarzenia: wiersz na czacie, losowanie, mowa, webhook, dźwięk z padu, źródło w OBS, własne zdarzenie akcji.
Vovó odróżnia wywołanie jednej strony od wywołania drugiej po zdarzeniu, które jest właśnie obsługiwane. Wywołanie zrobione po powrocie listenera (po await, gdy kończy się animacja, w timerze) wskazuje zdarzenie, na które odpowiada, przez { event: e }, czyli obiekt, który dostał listener; bez tego Vovó nie odróżni drugiej strony od drugiego razu.
vovo.on("raid", async (e) =>
{
const gift = await vovo.draw(["a hug", "a song", "a dance"]);
vovo.show("raid", { user: e.user, gift: gift.value });
vovo.chat.send(e.user + " gets " + gift.value + "!", { event: e });
});
To, co strona zaczyna sama, nie ma za sobą zdarzenia: setInterval akcji działa na każdej stronie, tak samo to, co robi przy ładowaniu. Vovó może wtedy kierować się tylko tym, o co się prosi (ten sam wiersz na czacie, ta sama mowa, ten sam webhook albo własne zdarzenie w ciągu 5 sekund to jedno), więc to, co liczy albo ma się stać raz, należy do wyzwalacza timer, który jest aplikacji i jeden dla wszystkich stron.
Stan, nigdy powtórka
vovo.state przechowuje Vovó, nie strona. Strona, która się ładuje (start OBS, odświeżone źródło, koniec paniki, ponowne otwarcie Vovó), ma go w całości, zanim ruszy jej skrypt, a klucz ustawiony na jednej stronie od razu dociera do pozostałych, bez słowa, bo same obsłużyły to samo zdarzenie. Zdarzeń nigdy nie odtwarza się ponownie: strona, której nie było, gdy przyszedł rajd, nie dowie się o nim później. Dlatego akcja trzyma w stanie wszystko, co ma pokazać ponownie (licznik celu, imiona w losowaniu, koniec odliczania), i przy ładowaniu rysuje z niego.
function draw()
{
document.getElementById("count").textContent = vovo.state.count || 0;
}
vovo.on("follow", () =>
{
vovo.state.count = (vovo.state.count || 0) + 1;
draw();
});
draw();
- Ustaw klucz ponownie, gdy zmienia się to, co przechowuje:
vovo.state.names = names.concat([user]). Lista albo obiekt zmienione w miejscu (push) nie zostają zapisane. - Zmieniaj stan w samym listenerze, przed jakimkolwiek
await: każda strona wychodzi wtedy z tego samego stanu i dochodzi do tego samego. Poawaitinna strona mogła już coś zapisać, więc zapisuj to, co nie zależy od tego, co tam jest (imię zwycięzcy, czas), nigdy o jeden więcej, niż przechowuje. - Klucz mieści najwyżej 64 KB, jako JSON, a jego nazwa 64 znaki.
To, co aktualne, i to, co mierzone na bieżąco
Cztery zdarzenia są wartością tak samo jak chwilą: obs.scene, media.track, twitch.viewers i screen.shared. Akcja, która się ładuje, od razu dostaje najnowsze z każdego, którego słucha, jakby właśnie się stało, więc pokazuje grany utwór, nie czekając na następny. Przychodzi ponownie przy każdym ładowaniu, na każdej stronie, bez zdarzenia za sobą: rysuj z niego i nie odpowiadaj na nie tym, co ma się stać raz.
audio.level, screen.color, input.move i speech.text to odczyty, do 60 na sekundę: dostarczane i zapominane, czytane tylko wtedy, gdy otwarta strona pokazuje słuchającą ich akcję. Niech ich listenery będą lekkie, a ruch zostaw CSS.
Ładowanie, przeładowanie i panika
Strona może się załadować w każdej chwili i więcej niż raz: OBS uruchamia źródło, gdy pokazuje się jego scena, może je wyłączyć, gdy jest ukryte, i odświeżyć, gdy pokaże się znowu, a Vovó ładuje akcję ponownie, gdy zmieni się jej kod albo pliki. Panika czyści wszystkie sceny naraz i ładuje ich akcje ponownie, co zatrzymuje wszystko, co robiły; gdy się kończy, ładują się jeszcze raz i zaczynają od swojego stanu. W czasie paniki nic nie dociera do akcji i nic, co przyszło w międzyczasie, nie jest potem odtwarzane; wartość kontrolki zostaje, bo jest stanem.
Akcja wraca więc poprawnie z samego stanu, w każdej chwili, nie licząc na nic, co poprzednia strona zostawiła w połowie.
Scena profilu
Akcja rysuje na scenie w pikselach CSS, której krótszy bok ma 1080: 1920 × 1080 dla transmisji 16:9 w dowolnej rozdzielczości (źródło 4K rysuje ją ostro w dwukrotnie większym rozmiarze), 1080 × 1920 dla pionowej, inny kształt dla ekranu o innym kształcie. Jej dokument ma rozmiar tej sceny i jest przezroczysty, więc 100vw na 100vh to cały obraz, a to, czego nie narysuje, pokazuje grę. Akcja robiona dla transmisji innych osób nie zakłada kształtu: rozmieszczaj rzeczy od krawędzi i w procentach, a dla pionowej transmisji użyj @media (orientation: portrait).
Przeglądarka OBS
OBS pokazuje sceny we własnej przeglądarce, starszej niż ta w edytorze i oknie podglądu Vovó (Chromium 127 w OBS 32), która może działać bez pomocy karty graficznej. Sprawdź nową funkcję CSS albo JavaScript z tą wersją, zanim na niej polegasz, i obejrzyj akcję w samym OBS, zanim ją przekażesz. Dźwięk gra tam od razu, bez kliknięcia, i idzie do transmisji: nic przeznaczonego tylko dla streamera nie należy do akcji.
Strona nie ma w OBS konsoli. Błędy, których akcja nie łapie, i to, co Vovó ma do powiedzenia o jej wywołaniach, trafiają do konsoli Vovó pod nazwą akcji, z numerem wiersza; console.log nie. Po to otwórz adres podglądu w przeglądarce (vovo dev go wypisuje) i użyj jej narzędzi dla programistów.
Tempo i limity
- Czat: jeden wiersz o 500 znakach; 20 wierszy w 30 sekund dla wszystkich akcji, jeden na sekundę dla każdej.
- Webhooki: 16 KB JSON; 30 na minutę, jeden na sekundę dla każdej akcji.
- Klipy i filmy: 3 czekające na zatwierdzenie dla każdej akcji.
- Kamery: 4 pokazywane naraz i 4 ustawienia kamery na akcję.
- Rozmowa głosowa: najwyżej 300 sekund.
- Przycisk pokazany jako w toku: najwyżej 15 minut.
- Stan: 64 KB na klucz.
- Paczka: 200 plików, 32 MB każdy i 128 MB razem;
index.html,style.cssiscript.jspo 2 MB.
Wywołanie ponad tempo zostaje pominięte, nigdy nie czeka w kolejce: jego promise zostaje odrzucony i mówi dlaczego.
Zanim ją przekażesz
- Przeładuj scenę w środku wszystkiego, co robi: wraca poprawnie, ze swojego stanu.
- Otwórz scenę dwa razy, w OBS i w oknie podglądu, i uruchom każdy wyzwalacz: jeden wiersz na czacie, jeden dźwięk, jedno zliczenie.
- Włącz i wyłącz panikę, gdy coś pokazuje.
- Wypróbuj ją na pionowym profilu i w samym OBS.
- Proś tylko o uprawnienia, których używa, i powiedz w Zachowaniu, czym jest: autor, strona i jeden wiersz.
- Nadaj jej id i wyższą wersję za każdym razem, gdy ją przekazujesz, żeby jej aktualizacja znalazła akcję, którą zastępuje, i powiedziała, jaką wersję przynosi.
- Powiedz, na jakiej licencji ją przekazujesz, z pełnym tekstem, gdy warunki są twoje własne.