Mega-pakket: hoe Factorio-ontwikkelaars de multiplayerproblemen met 200 spelers oplosten

Mega-pakket: hoe Factorio-ontwikkelaars de multiplayerproblemen met 200 spelers oplosten
In mei van dit jaar nam ik deel als speler aan het MMO-evenement KatherineOfSky. Ik merkte dat wanneer het aantal spelers een bepaald aantal bereikt, na enkele minuten een deel van hen "afhaakt". Gelukkig voor jullie (maar niet voor mij) was ik een van die spelers die elke keer afhaakten, zelfs met een goede verbinding. Ik beschouwde dit als een persoonlijke uitdaging en begon naar de oorzaken van het probleem te zoeken. Na drie weken debuggen, testen en corrigeren was de fout eindelijk verholpen, maar deze reis was lang niet zo eenvoudig. De problemen van multiplayergames zijn erg moeilijk te traceren. Ze doen zich meestal voor onder zeer specifieke netwerkparameters en specifieke spelsituaties (in dit geval met meer dan 200 spelers). En zelfs als je het probleem kunt reproduceren, is het moeilijk om het goed te debuggen, omdat het invoegen van controlepunten het spel stopt, de timers verstoort en vaak leidt tot het beƫindigen van de verbinding vanwege een time-out. Maar dankzij doorzettingsvermogen en een geweldig hulpmiddel genaamdclumsy

is het me gelukt om te achterhalen wat er aan de hand is. Kortom: door een bug en een onvolledige implementatie van de simulatie van vertragingstoestand bevond de client zich soms in een situatie waarin hij in ƩƩn cyclus een netwerkpakket moest verzenden dat bestond uit de invoeracties van spelers voor ongeveer 400 game-entiteiten (we noemen het "megapakket"). Daarna moest de server niet alleen al deze invoeracties correct ontvangen, maar ook aan al de andere clients verzenden. Als je 200 clients hebt, wordt dit snel problematisch. De verbinding naar de server raakt snel verzadigd, wat leidt tot pakketverlies en een cascade van opnieuw opgevraagde pakketten. Het uitstellen van invoeracties leidt er vervolgens toe dat nog meer clients megapakketten te verzenden, en hun avalanche wordt nog sterker. Gelukkige clients slagen erin om zich te herstellen, de anderen "vallen af". deze reis was lang niet zo eenvoudig.

gelukkig voor jullie (maar niet voor mij) was ik een van die spelers die elke keer afhaakten, zelfs met een goede verbinding.

Mega-pakket: hoe Factorio-ontwikkelaars de multiplayerproblemen met 200 spelers oplosten
Het probleem was behoorlijk fundamenteel, en het kostte me 2 weken om het op te lossen. Het is vrij technisch, dus hieronder zal ik de sappige technische details uitleggen. Maar eerst moet je weten dat met versie 0.17.54, uitgebracht op 4 juni, de multiplayer onder tijdelijke verbindingsproblemen stabieler werd, en de latency-verberging veel minder glitchy (minder haperingen en teleportatie). Bovendien heb ik de manier van latency-verberging in gevechten aangepast en hoop dat ze hierdoor iets soepeler zullen zijn.

Multiplayer megapakket - technische details

Als ik het eenvoudig moet uitleggen, werkt de multiplayer in het spel als volgt: alle cliƫnten simuleren de toestand van het spel, waarbij ze alleen de invoer van de speler ontvangen en verzenden (de zogenaamde "input actions" Input Actions). De belangrijkste taak van de server is het overdragen Input Actions en controleren dat alle cliƫnten dezelfde acties uitvoeren in ƩƩn tijdseenheid. Meer hierover kun je lezen in de post FFF-149.

Aangezien de server beslissingen moet nemen over welke acties moeten worden uitgevoerd, bewegen de acties van de speler ongeveer zo: actie van de speler -> spelclient -> netwerk -> server -> netwerk -> spelclient. Dit betekent dat elke actie van de speler pas wordt uitgevoerd nadat deze een heen-en-terugreis door het netwerk heeft gemaakt. Hierdoor zou het spel vreselijk traag lijken, daarom werd er vrijwel onmiddellijk na de introductie van de multiplayer een mechanisme voor latency-verberging geĆÆntroduceerd. Latency-verberging imiteert de invoer van de speler zonder rekening te houden met de acties van andere spelers en het nemen van beslissingen door de server.

Mega-pakket: hoe Factorio-ontwikkelaars de multiplayerproblemen met 200 spelers oplosten
In Factorio is er een speltoestand Game State — dit is de volledige staat van de kaart, de speler, entiteiten en alles wat erbij hoort. Het wordt deterministisch gesimuleerd in alle cliĆ«nten op basis van de acties die van de server zijn ontvangen. De speltoestand is heilig, en als deze ooit begint af te wijken van de server of een andere cliĆ«nt, ontstaat er desynchronisatie.

Bovendien Game State hebben we een latency-toestand Latency State. Dit bevat een klein subset van de belangrijkste toestand. Latency State is niet heilig en vertegenwoordigt eenvoudig een beeld van hoe de toestand van het spel er in de toekomst uit zal zien op basis van de invoer van de speler Input Actions.

Hiervoor bewaren we een kopie van de aangemaakte Input Actions in de latency-queue.

Mega-pakket: hoe Factorio-ontwikkelaars de multiplayerproblemen met 200 spelers oplosten
Dus aan het einde van het proces ziet het plaatje er aan de kant van de klant ongeveer zo uit:

  1. Toepassen Input Actions op alle spelers met Game State zoals deze invoeracties van de server zijn ontvangen.
  2. Verwijder alle Input Actions, die volgens de server al zijn toegepast op Game State.
  3. Verwijder Latency State en reset deze, zodat deze er precies zo uitziet als Game State.
  4. Pas alle acties uit de wachtrij van vertragingen toe op Latency State.
  5. Op basis van de gegevens Game State en Latency State renderen we het spel voor de speler.

Dit herhaalt zich in elke cyclus.

Te moeilijk? Maak je geen zorgen, dit is nog niet alles. Om de onbetrouwbaarheid van internetverbindingen te compenseren, hebben we twee mechanismen gemaakt:

  • Gemiste cycli: wanneer de server besluit dat Input Actions uitgevoerd worden in de spelsessie, en als hij geen bepaalde speler heeft ontvangen (bijvoorbeeld vanwege verhoogde vertraging), zal hij niet wachten, maar deze client laten weten: ā€˜ik heb je Input Actions , ik zal proberen ze in de volgende cyclus toe te voegen’. Dit is gedaan zodat de kaartupdates voor alle andere spelers niet vertraging oplopen door verbindingsproblemen (of computerproblemen) van ƩƩn speler. Opmerking: deze Input Actionsworden niet genegeerd, maar gewoon uitgesteld. Input Actions Volledige round-trip vertraging: de server probeert te schatten wat de round-trip verzendvertraging is tussen de klant en de server voor elke klant. Elke 5 seconden bespreekt hij indien nodig met de klant de nieuwe vertraging (afhankelijk van hoe de verbinding zich in het verleden heeft gedragen) en verhoogt of verlaagt de round-trip verzendvertraging dienovereenkomstig.
  • Deze mechanismen zijn op zichzelf vrij eenvoudig, maar wanneer ze samen worden gebruikt (wat vaak gebeurt bij verbindingsproblemen), wordt de logica van de code moeilijk te beheren en zijn er talloze randgevallen. Bovendien moeten wanneer deze mechanismen betrokken zijn de server en de wachtrij van vertragingen de bijzondere

Input Action met de naam StopMovementInTheNextTick . Hierdoor zal het personage niet uit zichzelf rennen bij verbindingsproblemen (bijvoorbeeld onder een trein).Nu moet ik je uitleggen hoe de selectie van entiteiten werkt. Een van de overgedragen types

. met de naam — dit is de wijziging van de status van de geselecteerde entiteit. Het geeft aan iedereen door op welke entiteit de speler met de muis wijst. Zoals je kunt zien, is dit een van de meest voorkomende invoeracties die door de clients worden verzonden, daarom hebben we dit geoptimaliseerd om zo min mogelijk bandbreedte te gebruiken. Dit is gerealiseerd door bij het selecteren van elke entiteit in plaats van de absolute, hoogprecisie coƶrdinaten van de kaart, de relatieve lage-precisie offset ten opzichte van de vorige selectie op te slaan. Dit werkt goed omdat de muisselectie meestal erg dichtbij de vorige selectie gebeurt. Dit brengt twee belangrijke vereisten met zich mee: Input Actions mag nooit worden overslagen en moet in de juiste volgorde worden uitgevoerd. Deze vereisten worden vervuld voor Game State. Maar aangezien de taak Latentie-status erop gericht is om 'goed genoeg eruit te zien' voor de speler, worden ze in latentie-omstandigheden niet vervuld. Latency State houdt geen rekening met veel grensgevallen, gerelateerd aan het overslaan van klokken en het veranderen van de round-trip latentie.

Je kunt je waarschijnlijk al voorstellen waar dit naartoe leidt. Eindelijk beginnen we de oorzaken van het megapakketprobleem te zien. De wortel van het probleem ligt in het feit dat bij het nemen van de beslissing of de actie van wijziging van selectie moet worden verzonden, de logica van entiteitselectie afhankelijk is van Latency State, en deze status bevat niet altijd de juiste informatie. Daarom wordt het megapakket als volgt gegenereerd:

  1. De speler heeft verbindingsproblemen.
  2. Mechanismen voor het overslaan van klokken en het regelen van de round-trip-latentie komen in beeld.
  3. De wachtrij van de latentie-status houdt geen rekening met deze mechanismen. Dit leidt ertoe dat sommige acties voortijdig worden verwijderd of in de verkeerde volgorde worden uitgevoerd, wat resulteert in een verkeerde Latency State.
  4. De speler verliest het verbindingsprobleem en simuleert 400 klokken om de server bij te benen.
  5. Bij elke klok wordt een nieuwe actie gegenereerd en voorbereid om naar de server te worden verzonden, waarbij de wijziging van de entiteitselectie plaatsvindt.
  6. De client stuurt een megapakket van meer dan 400 wijzigingen van entiteitselecties naar de server (en andere acties: de schietstatus, lopen, enz. hadden ook last van dit probleem).
  7. De server ontvangt 400 invoerhandelingen. Omdat hij niet is toegestaan enige invoerhandeling over te slaan, beveelt hij alle klanten aan deze handelingen uit te voeren en verzendt ze via het netwerk.

De ironie is dat het mechanisme dat bedoeld was om de bandbreedte te sparen, uiteindelijk enorme netwerkpakketten genereerde.

We hebben dit probleem opgelost door alle randgevallen van updates en queue-ondersteuning te corrigeren. Hoewel het behoorlijk wat tijd kostte, was het uiteindelijk de moeite waard om alles goed te implementeren in plaats van te vertrouwen op snelle hacks.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster