Inne projekty

ServerModSync

Klient dociąga mody serwera sam, po haszu pliku.

Problem

Wejście na serwer z modami zaczyna się od ręcznego dopasowania paczki: link gdzieś na Discordzie, wersje się rozjeżdżają, a jeden plik inny niż na serwerze to wyrzucenie przy drzwiach.

Rozwiązanie

Serwer po starcie liczy skrót SHA-256 każdego swojego moda i wystawia listę pod własnym adresem HTTP razem z plikami. Klient dorysowuje ikonę przy każdym wpisie na liście serwerów; po kliknięciu porównuje listę serwera z tym, co ma u siebie, i ściąga wyłącznie to, czego brakuje albo co się różni skrótem. Plik trafia na dysk dopiero po sprawdzeniu skrótu.

Co robi

  • Ikona przy każdym wpisie na liście serwerów, wstrzyknięta mixinem w ekran gry
  • Lista modów serwera jako JSON, pliki pod osobnym adresem
  • Porównanie po identyfikatorze moda i skrócie SHA-256, nie po nazwie pliku
  • Pasek postępu na pobieranym pliku, odświeżany co 48 kilobajtów
  • Skrót sprawdzany po pobraniu; niezgodny plik jest kasowany, nie instalowany
  • Trzy podejścia na plik z sekundą przerwy, zanim pobieranie zostanie uznane za nieudane
  • Lista modów pomijanych przy synchronizacji, w pliku konfiguracyjnym

Na czym zbudowane

  • Moduł wspólny nic nie wie o loaderze; Fabric i NeoForge to cztery cienkie warstwy nad nim
  • Serwer HTTP z biblioteki standardowej Javy, dwa adresy: lista modów i pliki
  • Lista budowana przy starcie serwera z tego, co widzi loader, każdy JAR haszowany
  • Klient pobiera strumieniowo przez HttpClient z Javy 21, bez wczytywania pliku do pamięci
  • Plik leci do .tmp, potem skrót, dopiero potem atomowa podmiana pod właściwą nazwę
  • Watchdog na ciszę w strumieniu: brak bajtów przez ustalony czas zamyka połączenie
  • Ekran klienta jako automat stanów: pobieranie listy, lista, pobieranie, błąd, koniec

Co to zmieniło

  • Ręczne składanie paczki modów znika: klient porównuje listę po SHA-256 i ściąga wyłącznie to, czego brakuje albo co się różni
  • Dwadzieścia osób tego używa; wydanie na CurseForge i Modrinth w przygotowaniu
  • Poprawka idzie raz, nie cztery razy: jeden rdzeń obsługuje Fabric i NeoForge, po stronie serwera i klienta
  • 29 testów i 40 asercji, wszystkie działające bez uruchamiania Minecrafta
  • Transport bez jednej zależności zewnętrznej: serwer i klient HTTP z biblioteki standardowej Javy

Stack

  • Java 21
  • Fabric
  • NeoForge
  • Mixin
  • Gradle
  • Gson

Historia

Wyjście poza katalog jest zablokowane dwa razy, niezależnie po obu stronach. Serwer odrzuca nazwy ze znakami przejścia po katalogach i oddaje wyłącznie pliki ze swojej listy. Klient osobno odrzuca adres bezwzględny i każdą ścieżkę, która po rozwinięciu wypada poza katalog modów. Jedna z tych kontroli wystarczyłaby przy uczciwym drugim końcu — obie są po to, żeby uczciwość drugiego końca nie była założeniem. Poza liczbą osób, które tego używają, wpis nie podaje żadnych pomiarów z prawdziwego serwera — są tu wyłącznie rzeczy sprawdzalne w kodzie i w testach.