Megapack: Hogyan oldotta meg a Factorio a 200 játékosos többjátékos problémát

Megapack: Hogyan oldotta meg a Factorio a 200 játékosos többjátékos problémát
Ez év májusában játékosként részt vettem a KatherineOfSky MMO események. Észrevettem, hogy amikor a játékosok száma elér egy bizonyos számot, néhány percenként "leesik". Szerencsédre (de nem nekem) én voltam az egyik ilyen játékos minden alkalommalmég jó kapcsolat mellett is. Személyes kihívásnak vettem, és elkezdtem keresni a probléma okait. Három hét hibakeresés, tesztelés és javítás után végre kijavították a hibát, de az utazás nem volt olyan egyszerű.

A többszereplős játékok problémáit nagyon nehéz nyomon követni. Általában nagyon specifikus hálózati paraméterek és nagyon specifikus játékállapotok mellett fordulnak elő (ebben az esetben több mint 200 játékos esetén). És még ha egy probléma reprodukálható is, nem lehet megfelelően hibakeresni, mert a töréspontok beszúrása leállítja a játékot, elrontja az időzítőket, és általában időtúllépés miatt a kapcsolat időtúllépést okoz. De hála a kitartásnak és egy csodálatos eszköznek ún ügyetlen Sikerült rájönnöm, hogy mi történik.

Röviden, egy hiba és a késleltetési állapot szimuláció nem teljes megvalósítása miatt a kliens olykor olyan helyzetbe került, hogy egy óraciklus alatt egy hálózati csomagot kellett küldenie, amely a játékosok által végrehajtott bemeneti műveletekből állt körülbelül 400 játék entitás kiválasztásához ( "megacsomagnak" hívjuk). Ezt követően a kiszolgálónak nemcsak helyesen kell fogadnia ezeket a bemeneti műveleteket, hanem el is kell küldenie azokat az összes többi ügyfélnek. Ha 200 ügyfele van, ez gyorsan problémát jelent. A szerverhez vezető csatorna gyorsan eltömődik, ami csomagvesztést és az újrakért csomagok sorozatát eredményezi. A beviteli műveletek elhalasztásával több ügyfél kezd megacsomagokat küldeni, és a lavina még erősebb lesz. A sikeres ügyfeleknek sikerül felépülniük, a többi „leesik”.

Megapack: Hogyan oldotta meg a Factorio a 200 játékosos többjátékos problémát
A probléma meglehetősen alapvető volt, és 2 hétbe telt, amíg kijavítottam. Elég technikás, ezért alább elmagyarázom a szaftos technikai részleteket. Először azonban tudnod kell, hogy a június 0.17.54-én megjelent 4-es verzió óta az átmeneti csatlakozási problémákkal szemben a többjátékos stabilabbá vált, a késleltetett elrejtés pedig sokkal kevésbé bugos (kevesebb fékezés és teleportálás). Ezenkívül megváltoztattam a harci késések elrejtésének módját, és remélhetőleg ez egy kicsit simábbá teszi őket.

Multiplayer Mega Pack – Technikai részletek

Leegyszerűsítve a többjátékos mód a játékban a következőképpen működik: minden kliens szimulálja a játék állapotát úgy, hogy csak a játékosok bemenetét fogadja és küldi el (az úgynevezett "beviteli műveletek"). Beviteli műveletek). A szerver fő feladata az átvitel Beviteli műveletek és annak biztosítása, hogy minden ügyfél ugyanazokat a műveleteket hajtsa végre ugyanabban a ciklusban. Erről bővebben a bejegyzésben olvashat. FFF-149.

Mivel a szervernek kell döntenie arról, hogy mit tegyen, a játékos akciói a következő útvonalon mozognak: játékos akció -> játékkliens -> hálózat -> szerver -> hálózat -> játékkliens. Ez azt jelenti, hogy a játékos minden egyes akcióját csak azután hajtja végre, hogy megtett egy körutat a hálózaton keresztül. Emiatt a játék rettenetesen lassúnak tűnt volna, így szinte azonnal a multiplayer megjelenése után bevezették a késések elrejtésére szolgáló mechanizmust. A késleltetési idő elrejtése szimulálja a játékosok bevitelét anélkül, hogy figyelembe venné a többi játékos tevékenységét és a szerver döntéshozatalát.

Megapack: Hogyan oldotta meg a Factorio a 200 játékosos többjátékos problémát
A Factorio játékállapottal rendelkezik játék állapota a térkép, a játékos, az entitások és minden más teljes állapota. Determinisztikusan szimulálja az összes kliensben a szervertől kapott műveletek alapján. A játék állapota szent, és ha valaha is kezd eltérni a szervertől vagy bármely más klienstől, akkor deszinkronizálás történik.

De játék állapota késések állapota van nálunk Lappangási állapot. A fő állapot egy kis részhalmazát tartalmazza. Lappangási állapot nem szent, és csak képet ad arról, hogyan fog kinézni a játék állapota a jövőben a játékos bemenetei alapján Beviteli műveletek.

Ehhez megőrizzük a generált másolatát Beviteli műveletek a késleltetési sorban.

Megapack: Hogyan oldotta meg a Factorio a 200 játékosos többjátékos problémát
Vagyis a folyamat végén a kliens oldalon a kép valahogy így néz ki:

  1. Alkalmaz Beviteli műveletek minden játékosnak játék állapota hogyan fogadták ezeket a bemeneti műveleteket a szervertől.
  2. Távolítson el mindent a késleltetési sorból Beviteli műveletek, amelyekre a szerver szerint már alkalmazták játék állapota.
  3. eltávolítás Lappangási állapot és állítsa vissza, hogy pontosan ugyanúgy nézzen ki, mint játék állapota.
  4. Alkalmazza az összes műveletet a késleltetési sortól a következőig Lappangási állapot.
  5. Adatok alapján játék állapota и Lappangási állapot adja át a játékot a játékosnak.

Mindez minden ütemben megismétlődik.

Túl nehéz? Ne lazíts, ez még nem minden. A megbízhatatlan internetkapcsolatok kompenzálására két mechanizmust hoztunk létre:

  • Kihagyott pipák: amikor a szerver úgy dönt Beviteli műveletek a játék tapintatában hajtják végre, akkor ha nem kapta meg Beviteli műveletek néhány játékos (például a megnövekedett késés miatt), nem vár, hanem értesíti ezt az ügyfelet: „Nem vettem figyelembe Beviteli műveletek, megpróbálom hozzáadni őket a következő sávban. Ez azért történik, hogy az egyik játékos kapcsolatával (vagy számítógépével) kapcsolatos problémák miatt a térképfrissítés ne lassuljon le mindenkinél. Érdemes megjegyezni, hogy Beviteli műveletek nem hagyják figyelmen kívül, hanem egyszerűen elhalasztják.
  • Teljes oda-vissza késés: A szerver megpróbálja kitalálni, hogy mennyi az ügyfél és a kiszolgáló közötti oda-vissza késés az egyes klienseknél. 5 másodpercenként szükség szerint új késleltetést egyeztet az ügyféllel (attól függően, hogy a kapcsolat hogyan viselkedett a múltban), és ennek megfelelően növeli vagy csökkenti az oda-vissza út késleltetését.

Önmagukban ezek a mechanizmusok meglehetősen egyszerűek, de ha együtt használják őket (ami gyakran előfordul csatlakozási problémákkal), a kódlogika nehezen kezelhetővé válik, és sok szélső eset áll fenn. Ezen túlmenően, amikor ezek a mechanizmusok működésbe lépnek, a kiszolgálónak és a késleltetési sornak megfelelően kell végrehajtania egy speciális Beviteli művelet hívott StopMovementInTheNextTick. Ennek köszönhetően csatlakozási problémák esetén a karakter nem fog magától futni (például vonat alatt).

Most el kell magyaráznom, hogyan működik az entitás kiválasztása. Az egyik átadott típus Beviteli művelet egy entitás kiválasztási állapotának változása. Mindenkinek elmondja, melyik entitás fölé vitte a játékos az egeret. Mint látható, ez az egyik leggyakrabban küldött beviteli művelet a kliensek által, ezért a sávszélesség megtakarítása érdekében úgy optimalizáltuk, hogy a lehető legkevesebb helyet foglaljon. Ez a következőképpen valósul meg: az egyes entitások kiválasztásakor a játék ahelyett, hogy abszolút, nagy pontosságú térképkoordinátákat tárolna, egy kis pontosságú relatív eltolást tárol az előző kijelöléshez képest. Ez jól működik, mert az egér kijelölése általában nagyon közel történik az előző kijelöléshez. Ez két fontos követelményt vet fel: Beviteli műveletek soha nem szabad kihagyni, és a megfelelő sorrendben kell elvégezni. Ezek a követelmények teljesülnek játék állapota. De mivel a feladat látencia állapot abban, hogy "elég jól néz ki" a játékos számára, nem elégedettek a késleltetett állapotban. Lappangási állapot nem veszi figyelembe sok határesetaz órák átugrásával és az oda-vissza átviteli késleltetések módosításával kapcsolatos.

Már sejtheti, hová vezet ez. Végül kezdjük látni a megapackage probléma okait. A probléma gyökere az, hogy az entitáskiválasztási logika támaszkodik Lappangási állapot, és ez az állapot nem mindig tartalmazza a helyes információkat. Tehát a megacsomag a következőképpen jön létre:

  1. A lejátszó csatlakozási problémákat tapasztal.
  2. A ciklusok kihagyására és az oda-vissza átviteli késleltetés szabályozására szolgáló mechanizmusok lépnek működésbe.
  3. A késleltetési állapotsor nem veszi figyelembe ezeket a mechanizmusokat. Emiatt bizonyos műveletek idő előtt törlődnek, vagy rossz sorrendben futnak le, ami helytelen eredményt eredményez Lappangási állapot.
  4. A lejátszónak nincs kapcsolati problémája, és akár 400 ciklust szimulál, hogy utolérje a szervert.
  5. Minden ciklusban egy új művelet jön létre, és készül elküldésre a kiszolgálónak, megváltoztatva az entitás kiválasztását.
  6. A kliens 400+ entitáskiválasztási változásból álló megacsomagot küld a szervernek (és egyéb műveletekkel: tüzelési állapot, járási állapot stb. is szenvedett ettől a problémától).
  7. A szerver 400 beviteli műveletet kap. Mivel nem megengedett egyetlen beviteli művelet kihagyása, az összes klienst utasítja ezen műveletek végrehajtására, és elküldi őket a hálózaton keresztül.

Az irónia az, hogy a sávszélesség megtakarítására tervezett mechanizmus hatalmas hálózati csomagokat eredményezett.

Megoldottuk ezt a problémát az összes frissítési szélső eset és a késleltetési sor támogatásának javításával. Bár elég sokáig tartott, érdemes volt a végén rendbe tenni, nem pedig a gyors hackelésekre hagyatkozni.

Forrás: will.com

Hozzászólás