Jak używać hot-reload i kiedy nie warto?
Nie musisz restartować Gothica!
Budowanie na platformie uruchamia zazwyczaj 3 aplikacje: Gothic2.exe, serwer NodeJS z naszym trybem gry oraz lokalny serwer HTTP hostujący stronę nakładki. Wszystkie te aplikacje posiadają tak zwany hot-reload, czyli przeładowanie kodu bez potrzeby restartowania aplikacji. Wyobraź sobie sytuację, w której szukasz odpowiedniej metody uniona do zaktualizowania życia gracza. Najprościej jest stworzyć testową komendę np. /test i w jej ciało wrzucać metodę, której szukasz. Zmiana treści metody, zapisanie, reload – wszystko trwa mniej niż sekundę i możesz ponownie sprawdzić wykonanie swojego kodu w Gothicu.
Pułapki hot-reloadu
Niestety, przy bardziej skomplikowanych sytuacjach mogą pojawić się oczywiste, lecz trudne do wyłapania problemy. Stan trybu gry jest trzymany w procesie NodeJS, a stan świata Gothic oczywiście w grze. Jeżeli utworzysz sobie zmienną globalną "CaptainGarondNpc" i podczas uruchomienia serwera przypiszesz do niej NPCta, to po zmianie kodu serwer NodeJS się przeładuje, a zmienne globalne zostaną zrestartowane. Sprawi to, że pomimo iż NPC Garonda jest w grze, Twoja zmienna będzie zawierać null. Jak to rozwiązać? Łatwiejsze dla początkujących może być po prostu restartowanie gry albo używanie hot-reloadu tylko do debugowania prostych kawałków kodu (tak jak wcześniej wspomniałem, np. komendą /test). Natomiast gdy złapiesz trochę wprawy, możliwość hot-reloadu naprawdę przyspieszy Ci pracę. W następnym punkcie opiszę, jak używaliśmy go podczas budowy trybu Castle Defense.
Hot-reload a globalny stan gry
W trybie Castle Defense posiadamy zmienną "faza gry", która reprezentuje etap rozgrywki, np. "w trakcie przygotowania", "w trakcie aktywnej fali" itp. Powiedzmy, że odpalamy falę i chcemy testować kod, który odnosi się tylko do fazy aktywnej fali. Każda zmiana kodu i hot-reload ustawiałaby nam fazę znowu na domyślną. Jak sobie z tym poradziliśmy? Cały stan gry trzymamy w specjalnym storze, używając znanej ze świata web developmentu biblioteki Zustand, a w trybie lokalnego developmentu zapisujemy co każdą zmianę całą zawartość store do pliku. Dzięki temu przy hot-reloadzie wczytujemy poprzedni stan sesji i całość działa spójnie.
Jak zbudowaliśmy nasz store, możesz zobaczyć tutaj:
https://gitlab.com/gothictogether/castle-defense-gamemode/-/blob/master/src/store.ts
Jest to dość dużo kodu, natomiast bardzo prostego w użyciu. W trybie gry to potem tylko np.: this.state.setGamePhase('ACTIVE')