Megapaket: Hur utvecklarna av Factorio lyckades lösa problemet med multiplayer för 200 spelare

Megapaket: Hur utvecklarna av Factorio lyckades lösa problemet med multiplayer för 200 spelare
I maj mÄnad deltog jag som spelare i MMO-evenemanget KatherineOfSky. Jag mÀrkte att nÀr antalet spelare nÄr ett visst antal, sÄ kopplar en del av dem "bort" var nÄgra minuter. Lyckligtvis för er (men inte för mig) var jag en av de spelare som kopplades bort varje gÄng, trots att jag hade en bra uppkoppling. Jag tog detta som en personlig utmaning och började leta efter orsaken till problemet. Efter tre veckors felsökning, testning och reparationer var felet Àntligen ÄtgÀrdat, men denna resa var inte sÄ enkel.

Problem i multiplayer-spel Ă€r vĂ€ldigt svĂ„ra att spĂ„ra. De uppstĂ„r vanligtvis under mycket specifika förhĂ„llanden i nĂ€tverksinstĂ€llningar och under vĂ€ldigt specifika spelsituationer (i det hĂ€r fallet – mer Ă€n 200 spelare). Och Ă€ven nĂ€r man lyckas Ă„terskapa problemet kan det vara omöjligt att debugga det ordentligt, eftersom insĂ€ttning av kontrollpunkter stoppar spelet, förvirrar tidtagarna och vanligtvis leder till att anslutningen avslutas pĂ„ grund av tidsöverskridning. Men tack vare ihĂ€rdighet och ett fantastiskt verktyg som heter clumsy , lyckades jag lista ut vad som hĂ€nde.

Kort sagt: pÄ grund av ett fel och ofullstÀndig implementering av simuleringsförhÄllandet för fördröjning hamnade klienten ibland i en situation dÀr den mÄste skicka ett nÀtverkspaket bestÄende av spelarinmatningar som involverar cirka 400 spelstruktur (vi kallar det "megapaket"). Efter detta mÄste servern inte bara ta emot alla dessa inmatningar korrekt, utan ocksÄ skicka dem till alla andra klienter. Om du har 200 klienter blir detta snabbt ett problem. Kanalen till servern blir snabbt överfull, vilket leder till paketförlust och en kaskad av begÀrda paket pÄ nytt. Fördröjningen av inmatningar leder sedan till att Ànnu fler klienter börjar skicka megapaket, och deras lavin blir Ànnu starkare. Lyckas kunderna ÄterhÀmta sig gÄr alla andra "bort".

Megapaket: Hur utvecklarna av Factorio lyckades lösa problemet med multiplayer för 200 spelare
Problemet var ganska grundlÀggande och jag tog tvÄ veckor för att ÄtgÀrda det. Det Àr ganska tekniskt, sÄ nedan kommer jag att förklara detaljerna. Men först behöver du veta att med version 0.17.54 som slÀpptes den 4 juni, har multiplayer blivit mer stabilt under tidsproblem med anslutning, och fördröjningsdoldning Àr mycket mindre glitchigt (mindre lagg och teleportering). Dessutom har jag Àndrat sÀttet att dölja fördröjningar i strid och hoppas att de kommer att vara lite mer smidiga.

Multiplayer Megapaket – tekniska detaljer

Förenklat kan man sÀga att multiplayer i spelet fungerar sÄ hÀr: alla klienter simulerar spelets tillstÄnd, genom att ta emot och skicka endast spelarens inmatning (kallas "inmatningsÄtgÀrder", Input Actions). Huvuduppgiften för servern Àr att överföra Input Actions och kontrollera att alla klienter utför samma ÄtgÀrder under ett taktslag. Mer om detta kan du lÀsa i inlÀgget FFF-149.

Eftersom servern mÄste fatta beslut om vilka ÄtgÀrder som ska utföras, rör sig spelarens ÄtgÀrd ungefÀr enligt denna vÀg: spelarens ÄtgÀrd -> spelklienten -> nÀtverk -> server -> nÀtverk -> spelklienten. Det betyder att varje spelarÄtgÀrd utförs först efter att den har gjort resan fram och tillbaka genom nÀtverket. PÄ grund av detta skulle spelet verka fruktansvÀrt laggigt, sÄ nÀstan omedelbart efter att multiplayer introducerades i spelet, implementerades en mekanism för att dölja fördröjningar. Död fördröjning simulerar spelarens inmatning utan att ta hÀnsyn till andra spelares ÄtgÀrder eller serverns beslut.

Megapaket: Hur utvecklarna av Factorio lyckades lösa problemet med multiplayer för 200 spelare
I Factorio finns det ett speltilstĂ„nd Game State – det fullstĂ€ndiga tillstĂ„ndet av kartan, spelaren, enheterna och allt annat. Det simuleras deterministiskt i alla klienter baserat pĂ„ Ă„tgĂ€rder som tas emot frĂ„n servern. SpelstĂ„ndet Ă€r heligt, och om det nĂ„gonsin börjar skilja sig frĂ„n servern eller nĂ„gon annan klient uppstĂ„r det en desynkronisering.

Förutom Game State har vi ett fördröjnings tillstÄnd Latency State. Det innehÄller en liten delmÀngd av det grundlÀggande tillstÄndet. Latency State det Àr inte heligt och representerar helt enkelt en bild av hur spelets tillstÄnd kommer att se ut i framtiden baserat pÄ spelarens inmatningar. Input Actions.

För detta lagrar vi en kopia av skapade Input Actions i fördröjningskön.

Megapaket: Hur utvecklarna av Factorio lyckades lösa problemet med multiplayer för 200 spelare
Det vill sÀga, i slutet av processen ser bilden pÄ klientsidan ut ungefÀr sÄ hÀr:

  1. TillÀmpa Input Actions alla ÄtgÀrder pÄ Game State sÄ som dessa indata har mottagits frÄn servern.
  2. Ta bort alla ÄtgÀrder frÄn fördröjningskön Input Actions, som enligt servern redan har tillÀmpats pÄ Game State.
  3. Ta bort Latency State och ÄterstÀll det sÄ att det ser exakt ut som Game State.
  4. TillÀmpa alla ÄtgÀrder frÄn fördröjningskön pÄ Latency State.
  5. Baserat pÄ data Game State och Latency State renderar vi spelet för spelaren.

Allt detta upprepas i varje takt.

För svÄrt? Slappna av, det Àr Ànnu inte allt. För att kompensera för den opÄlitliga internetanslutningen har vi skapat tvÄ mekanismer:

  • Missade takter: nĂ€r servern beslutar att Input Actions Ă„tgĂ€rder kommer att genomföras i speltakten, om den inte har fĂ„tt Input Actions nĂ„got frĂ„n en spelare (till exempel pĂ„ grund av ökad fördröjning), kommer den inte att vĂ€nta, utan meddelar den klienten "jag har inte tagit hĂ€nsyn till dina Input Actions, jag ska försöka lĂ€gga till dem i nĂ€sta takt". Detta görs för att sĂ€kerstĂ€lla att uppdateringen av kartan inte fördröjs för alla andra pĂ„ grund av anslutningsproblem (eller en enskild spelares dator). Det Ă€r vĂ€rt att notera att Input Actions inte ignoreras, utan bara skjuts upp.
  • FullstĂ€ndig tur-och-retur-fördröjning: servern försöker förutsĂ€ga vad fördröjningen för dataöverföring tur och retur mellan klienten och servern Ă€r för varje klient. Var femte sekund diskuterar den vid behov en ny fördröjning med klienten (beroende pĂ„ hur anslutningen betett sig tidigare) och justerar tur-och-retur-fördröjningen dĂ€refter.

SjÀlva dessa mekanismer Àr ganska enkla, men nÀr de anvÀnds tillsammans (vilket ofta hÀnder vid anslutningsproblem) blir logiken i koden svÄrhanterlig med mÄnga grÀnsfall. Dessutom, nÀr dessa mekanismer Àr inblandade, mÄste servern och fördröjningskön korrekt implementera den speciella Input Action som kallas StopMovementInTheNextTick. Tack vare detta kommer karaktÀren inte att springa av sig sjÀlv vid anslutningsproblem (till exempel under ett tÄg).

Nu mĂ„ste jag förklara för dig hur enhetsvalet fungerar. En av de överförda typerna Input Action — detta Ă€r förĂ€ndringen av tillstĂ„ndet för entitetsval. Det informerar alla om vilken entitet spelaren har pekat pĂ„ med musen. Som man kan förstĂ„ Ă€r detta en av de vanligaste inmatningsĂ„tgĂ€rderna som skickas av klienterna, dĂ€rför har vi optimerat den sĂ„ att den tar sĂ„ lite bandbredd som möjligt. Detta har genomförts pĂ„ det sĂ€ttet att vid val av varje entitet istĂ€llet för att spara absoluta, högprecisionskartkoordinater, sparar spelet lĂ„gprecisions relativa förskjutningar frĂ„n den föregĂ„ende valet. Detta fungerar bra eftersom musmarkeringen vanligtvis sker nĂ€ra den tidigare markeringen. PĂ„ grund av detta finns det tvĂ„ viktiga krav: Input Actions fĂ„r aldrig hoppas över och mĂ„ste utföras i rĂ€tt ordning. Dessa krav uppfylls för Game State. Men eftersom uppgiften Latency state Ă€r att "se tillrĂ€ckligt bra ut" för spelaren, uppfylls de inte i latenslĂ€get. Latency State tar inte hĂ€nsyn till mĂ„nga grĂ€nsfall, relaterade till takthopp och förĂ€ndringar i tvĂ„vĂ€gs latens.

Du kan redan gissa vart det hĂ€r leder. Äntligen börjar vi se orsakerna till megapaketproblemet. Roten till problemet ligger i att beslutslogiken om huruvida Ă„tgĂ€rden för att förĂ€ndra valet ska överföras, Ă€r beroende av Latency State, och detta tillstĂ„nd innehĂ„ller inte alltid korrekt information. DĂ€rför genereras megapaketet pĂ„ följande sĂ€tt:

  1. Spelaren har problem med anslutningen.
  2. Taktjump och justering av tvÄvÀgs latens kommer in i bilden.
  3. Kö av latensstatus tar inte hÀnsyn till dessa mekanismer. Detta leder till att vissa ÄtgÀrder tas bort för tidigt eller utförs i fel ordning, vilket resulterar i felaktig Latency State.
  4. Spelaren tappade anslutningen och simulerar upp till 400 takter för att hinna ikapp servern.
  5. Vid varje takt genereras och förbereds en ny ÄtgÀrd för att förÀndra entitetsvalet för att skickas till servern.
  6. Klienten skickar ett megapaket med över 400 förÀndringar av entitetsval (och andra ÄtgÀrder: tillstÄndet för skjutande, gÄng osv. led ocksÄ av detta problem).
  7. Servern fÄr 400 inmatningsÄtgÀrder. Eftersom den inte har tillÄtelse att hoppa över en enda ÄtgÀrd beordrar den alla klienter att utföra dessa ÄtgÀrder och skickar dem över nÀtverket.

Ironin Àr att mekanismen som Àr avsedd att spara bandbredd i kanalen istÀllet skapade enorma nÀtverkspaket.

Vi löste detta problem genom att Ă„tgĂ€rda alla grĂ€nsfall för uppdatering och hantering av fördröjningsköer. Även om det tog ganska lĂ„ng tid var det vĂ€rt att genomföra allt korrekt istĂ€llet för att förlita sig pĂ„ snabba lösningar.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster