Megapack: Bagaimana Factorio Memecahkan Masalah Multiplayer 200 Pemain

Megapack: Bagaimana Factorio Memecahkan Masalah Multiplayer 200 Pemain
Pada bulan Mei tahun ini, saya berpartisipasi sebagai pemain Acara MMO KatherineOfSky. Saya perhatikan ketika jumlah pemain mencapai jumlah tertentu, setiap beberapa menit beberapa dari mereka β€œjatuh”. Beruntung bagi Anda (tetapi tidak bagi saya), saya adalah salah satu pemain tersebut setiap saatbahkan dengan koneksi yang bagus. Saya menganggapnya sebagai tantangan pribadi dan mulai mencari penyebab masalahnya. Setelah tiga minggu melakukan debugging, pengujian, dan perbaikan, bug tersebut akhirnya diperbaiki, namun perjalanannya tidak semudah itu.

Masalah dalam game multipemain sangat sulit dilacak. Biasanya terjadi pada parameter jaringan yang sangat spesifik dan status permainan yang sangat spesifik (dalam hal ini, lebih dari 200 pemain). Dan meskipun masalah dapat muncul kembali, masalah tersebut tidak dapat di-debug dengan benar karena memasukkan breakpoint akan menghentikan permainan, mengacaukan pengatur waktu, dan biasanya menyebabkan koneksi terputus karena waktu habis. Namun berkat ketekunan dan alat yang luar biasa disebut kikuk Saya bisa mengetahui apa yang sedang terjadi.

Singkatnya, karena bug dan implementasi simulasi keadaan penundaan yang tidak lengkap, klien terkadang berada dalam situasi di mana ia harus mengirim paket jaringan dalam satu siklus jam, yang terdiri dari tindakan input pemain untuk memilih sekitar 400 entitas game ( kami menyebutnya "paket mega"). Setelah itu, server tidak hanya perlu menerima semua tindakan masukan ini dengan benar, tetapi juga mengirimkannya ke semua klien lainnya. Jika Anda memiliki 200 klien, ini dengan cepat menjadi masalah. Saluran ke server dengan cepat menjadi tersumbat, mengakibatkan hilangnya paket dan serangkaian paket yang diminta ulang. Menunda tindakan input kemudian menyebabkan lebih banyak klien mulai mengirimkan megapacket, dan longsoran salju mereka semakin kuat. Klien yang berhasil berhasil pulih, sisanya jatuh.

Megapack: Bagaimana Factorio Memecahkan Masalah Multiplayer 200 Pemain
Masalahnya cukup mendasar, dan saya butuh waktu 2 minggu untuk memperbaikinya. Ini cukup teknis, jadi saya akan menjelaskan detail teknis menariknya di bawah. Namun pertama-tama, Anda perlu tahu bahwa sejak versi 0.17.54, dirilis pada tanggal 4 Juni, dalam menghadapi masalah koneksi sementara, multipemain menjadi lebih stabil, dan penyembunyian penundaan menjadi jauh lebih sedikit bug (lebih sedikit pengereman dan teleportasi). Selain itu, saya telah mengubah cara penundaan pertempuran disembunyikan, dan semoga ini akan membuatnya sedikit lebih lancar.

Paket Mega Multi Pemain - Detail Teknis

Sederhananya, multipemain dalam sebuah game bekerja seperti ini: semua klien menyimulasikan keadaan game dengan hanya menerima dan mengirimkan masukan pemain (disebut "tindakan masukan" Tindakan Masukan). Tugas utama server adalah mentransfer Tindakan Masukan dan memastikan bahwa semua klien melakukan tindakan yang sama dalam siklus yang sama. Anda dapat membaca lebih lanjut tentang ini di postingan. FFF-149.

Karena server harus membuat keputusan tentang tindakan apa yang harus diambil, tindakan pemain bergerak sepanjang jalur berikut: aksi pemain -> klien game -> jaringan -> server -> jaringan -> klien game. Ini berarti bahwa setiap tindakan pemain dilakukan hanya setelah ia melakukan perjalanan bolak-balik melalui jaringan. Oleh karena itu, permainan akan terasa sangat lambat, jadi segera setelah munculnya multipemain dalam permainan, mekanisme untuk menyembunyikan penundaan diperkenalkan. Penyembunyian latensi mensimulasikan input pemain tanpa mempertimbangkan tindakan pemain lain dan pengambilan keputusan server.

Megapack: Bagaimana Factorio Memecahkan Masalah Multiplayer 200 Pemain
Factorio memiliki status permainan keadaan permainan adalah keadaan lengkap peta, pemain, entitas, dan lainnya. Ini disimulasikan secara deterministik di semua klien berdasarkan tindakan yang diterima dari server. Status permainan itu sakral, dan jika mulai berbeda dari server atau klien lain, maka desinkronisasi akan terjadi.

Tetapi keadaan permainan kami mengalami penundaan Status Latensi. Ini berisi sebagian kecil dari negara bagian utama. Status Latensi tidak sakral dan hanya mewakili gambaran seperti apa keadaan game kedepannya berdasarkan masukan dari pemain Tindakan Masukan.

Untuk melakukan ini, kami menyimpan salinan yang dihasilkan Tindakan Masukan dalam antrian penundaan.

Megapack: Bagaimana Factorio Memecahkan Masalah Multiplayer 200 Pemain
Artinya, di akhir proses di sisi klien, gambarnya terlihat seperti ini:

  1. Berlaku Tindakan Masukan semua pemain untuk keadaan permainan cara tindakan masukan ini diterima dari server.
  2. Hapus semuanya dari antrian penundaan Tindakan Masukan, yang menurut server telah diterapkan keadaan permainan.
  3. Menghapus Status Latensi dan atur ulang agar terlihat sama persis keadaan permainan.
  4. Terapkan semua tindakan dari antrian penundaan hingga Status Latensi.
  5. Berdasarkan data keadaan permainan ΠΈ Status Latensi merender game ke pemain.

Semua ini diulangi dalam setiap pengukuran.

Terlalu sulit? Jangan santai, bukan itu saja. Untuk mengimbangi koneksi Internet yang tidak dapat diandalkan, kami telah menciptakan dua mekanisme:

  • Kutu yang dilewati: ketika server memutuskan hal itu Tindakan Masukan akan dieksekusi sesuai kebijaksanaan permainan, lalu jika dia belum menerimanya Tindakan Masukan beberapa pemain (misalnya, karena penundaan yang meningkat), dia tidak akan menunggu, tetapi akan memberi tahu klien ini β€œSaya tidak memperhitungkan Anda Tindakan Masukan, saya akan mencoba menambahkannya di bilah berikutnya. Hal ini dilakukan agar karena masalah koneksi (atau dengan komputer) salah satu pemain, pembaruan peta tidak melambat untuk pemain lainnya. Perlu dicatat bahwa Tindakan Masukan bukan diabaikan, tapi ditunda begitu saja.
  • Latensi bolak-balik penuh: Server mencoba menebak latensi bolak-balik antara klien dan server untuk setiap klien. Setiap 5 detik, ia menegosiasikan penundaan baru dengan klien sesuai kebutuhan (tergantung pada bagaimana perilaku koneksi di masa lalu), dan menambah atau mengurangi penundaan pulang pergi.

Mekanisme ini sendiri cukup sederhana, tetapi ketika digunakan bersama-sama (yang sering terjadi ketika ada masalah koneksi), logika kode menjadi sulit untuk dikelola dan dengan banyak kasus edge. Selain itu, ketika mekanisme ini mulai berlaku, server dan antrian penundaan harus menerapkan mekanisme khusus dengan benar Tindakan Masukan bernama Hentikan Gerakan Di Berikutnya Centang. Berkat ini, jika terjadi masalah koneksi, karakter tidak akan berjalan sendiri (misalnya, di bawah kereta).

Sekarang saya perlu menjelaskan kepada Anda cara kerja pemilihan entitas. Salah satu tipe yang lulus Tindakan Masukan adalah perubahan keadaan pemilihan suatu entitas. Ini memberi tahu semua orang entitas mana yang diarahkan oleh pemain dengan mouse. Seperti yang Anda lihat, ini adalah salah satu tindakan masukan yang paling sering dikirim oleh klien, jadi untuk menghemat bandwidth, kami telah mengoptimalkannya sehingga menggunakan ruang sesedikit mungkin. Ini diterapkan seperti ini: ketika setiap entitas dipilih, alih-alih menyimpan koordinat peta absolut dan berpresisi tinggi, game menyimpan offset relatif berpresisi rendah dari pilihan sebelumnya. Ini berfungsi dengan baik karena pemilihan mouse biasanya terjadi sangat dekat dengan pemilihan sebelumnya. Hal ini menimbulkan dua persyaratan penting: Tindakan Masukan tidak boleh dilewati dan harus dilakukan dalam urutan yang benar. Persyaratan ini dipenuhi untuk keadaan permainan. Tapi sejak tugas itu keadaan latensi dalam "terlihat cukup baik" bagi pemain, mereka tidak puas dalam keadaan penundaan. Status Latensi tidak memperhitungkan banyak kasus yang berada di ambang batasterkait dengan melewatkan jam dan mengubah penundaan transmisi pulang pergi.

Anda sudah bisa menebak ke mana arahnya. Akhirnya, kami mulai melihat penyebab masalah megapackage. Akar masalahnya adalah logika pemilihan entitas bergantung pada Status Latensi, dan keadaan ini tidak selalu berisi informasi yang benar. Jadi megapacket dihasilkan seperti ini:

  1. Pemain mengalami masalah koneksi.
  2. Mekanisme untuk melewatkan siklus dan mengatur penundaan transmisi pulang pergi ikut berperan.
  3. Antrean status penundaan tidak memperhitungkan mekanisme ini. Hal ini menyebabkan beberapa tindakan dihapus sebelum waktunya atau dijalankan dalam urutan yang salah, sehingga menghasilkan kesalahan Status Latensi.
  4. Pemain tidak memiliki masalah koneksi dan mensimulasikan hingga 400 siklus untuk mengejar server.
  5. Di setiap siklus, tindakan baru dihasilkan dan disiapkan untuk dikirim ke server, mengubah pilihan entitas.
  6. Klien mengirimkan megapacket berisi 400+ perubahan pemilihan entitas ke server (dan dengan tindakan lain: status aktif, status berjalan, dll. juga mengalami masalah ini).
  7. Server menerima 400 tindakan input. Karena tidak diperbolehkan untuk melewatkan satu tindakan masukan pun, ia memerintahkan semua klien untuk melakukan tindakan ini dan mengirimkannya melalui jaringan.

Ironisnya, mekanisme yang dirancang untuk menghemat bandwidth menghasilkan paket jaringan yang sangat besar.

Kami telah mengatasi masalah ini dengan memperbaiki semua kasus edge pembaruan dan dukungan antrian penundaan. Meskipun memakan waktu cukup lama, pada akhirnya ada baiknya untuk memperbaikinya daripada mengandalkan peretasan cepat.

Sumber: www.habr.com

Tambah komentar