Membuat Aplikasi Multiplayer Menggunakan Directplay

Membuat Aplikasi Multiplayer Menggunakan Directplay-Pada artikel kali ini, admin akan menggunakan istilah aplikasi multiplayer untuk mengacu pada jenis aplikasi yang digunakan oleh dua atau lebih user pada komputer-komputer yang terhubung melalui jaringan. Jadi selain game multiplayer online, aplikasi chat juga termasuk kategori ini. Penulis akan menitikberatkan pada penjelasan langkah-langkah dasar menciptakan aplikasi multiplayer memanfaatkan DirectPlay.

Apa Itu DirectPlay? 
DirectPlay yang merupakan bagian DirectX, adalah Application Programming Interface (API) yang khusus diciptakan untuk menyederhanakan pengembangan aplikasi jaringan seperti game multiplayer atau aplikasi chat pada operating system Windows. DirectPlay mengisolasi aplikasi multiplayer dari kerumitan jaringan di bawahnya serta menyederhanakan implementasi beberapa hal berikut :
  • Menciptakan dan manajemen sesi permainan. 
  • Manajemen pemain dan grup dalam sesi. 
  • Pengiriman data antarpemain dalam sesi. 
  • Koneksi melalui lobby. Komunikasi suara antara pemain dalam sesi.
Untuk artikel ini, penulis hanya memfokuskan pembahasan pada tiga poin teratas.
Service Provider.
DirectPlay menyembunyikan detail koneksi jaringan dari aplikasi. Abstraksi ini memungkinkan tiap aplikasi berkomunikasi dengan cara yang seragam tanpa peduli tipe jaringan yang terlibat, termasuk perbedaan perangkat keras dan perangkat lunak jaringan. Koneksi jaringan sesungguhnya dibuat melalui service provider. 
DirectPlay menyertakan service provider untuk protokol TCP/IP, IPX, modem, dan serial. Service provider bertanggung jawab terhadap detail cara komunikasi untuk masing-masing protokol. Pada saat inisialisasi, aplikasi harus menentukan service provider yang dipergunakan. Untuk detail bagaimana memilih service provider, silakan baca “Inisialisasi Alamat”.
Arsitektur Jaringan.
DirectPlay mendukung dua model koneksi jaringan, yakni model peer-to-peer dan client-server. Sobat harus menentukan dari awal, model mana yang cocok untuk aplikasi sobat. Model peer-to-peer dan client-server masing-masing dibungkus dalam interface IDirectPlay8Peer, IDirectPlay8Client, dan IDirectPlay8Server.
Peer-to-Peer.
Pada model peer-to-peer, tiap komputer terhubung ke komputer lain dalam sebuah sesi yang sama,  di mana tiap komputer (peer) dapat saling berkomunikasi langsung (Lihat gambar dibawah ini). 
Membuat Aplikasi Multiplayer Menggunakan Directplay
Tiap peer dalam sebuah sesi bertanggung jawab menyimpan status game dan status player lain dalam sesi. Tiap kali sebuah peer perlu melakukan update status game, informasi perubahan tersebut harus dikirim ke semua komputer lain yang ada di sesi tersebut, sehingga masing-masing peer dapat melakukan sinkronisasi status game. 
Pada model peer-to-peer, terdapat sebuah peer yang bertanggung jawab sebagai host, biasanya peer ini adalah yang menciptakan sesi. Host berfungsi menangani peer yang hendak bergabung atau meninggalkan sesi dan juga sebagai pengelola sesi. Status sebagai host dapat ditransfer ke peer lain bila host meninggalkan sebuah sesi, dengan syarat sesi tersebut dibuat dengan kemampuan untuk melakukan migrasi host. 
Tanpa kemampuan ini, jika sebuah host meninggalkan sesi permainan, sesi tersebut juga akan dihentikan. Walaupun dalam sebuah sesi terdapat sebuah peer yang bertindak sebagai host, tiap peer dapat berkomunikasi dengan peer lain tanpa melalui host.
Keuntungan.
  • Lebih sederhana karena tidak perlu menyediakan kode aplikasi yang berbeda. Tiap peer memiliki kode aplikasi yang sama dengan peer lain, termasuk peer yang bertindak sebagai host.

Kerugian.
  • Jika tidak diimplementasikan dengan benar, model ini berpotensi menghambat kinerja, terutama karena tiap peer yang bergabung menyebabkan jumlah trafik jaringan juga akan meningkat sangat drastis sehingga hanya cocok untuk aplikasi multiplayer dengan jumlah pemain sedikit. 
  • Keamanan lebih sulit dikontrol karena tiap peer dapat berkomunikasi langsung dengan peer lain.

Client-Server.
Pada model client-server, satu komputer (atau lebih pada game online berskala besar) bertindak sebagai server dan komputer lain (client) harus terhubung ke server untuk bisa bergabung dalam sebuah sesi permainan (Lihat gambar dibawah ini). 
Membuat Aplikasi Multiplayer Menggunakan Directplay
Tiap client hanya berkomunikasi dengan server dan tidak dengan klien lain. Ketika klien hendak melakukan update status game, klien mengirimkan pesan ke server. Server kemudian mendistribusikan pesan dari klien ke semua klien lain dalam satu sesi. 
Kode aplikasi untuk klien dan server biasanya dipisahkan. Aplikasi untuk server biasanya menangani semua manajemen status game namun tanpa fitur grafis dan suara, sedangkan aplikasi klien hanya berfungsi menyusun tampilan interface pengguna (user-interface game), menerima input dari pengguna dan fitur suara dan tentu saja mengatur agar status game sinkron dengan status game yang ada di server.
Keuntungan.
  • Model client-server menghasilkan skalabilitas yang lebih baik. Jika jumlah klien bertambah, jumlah trafik data naik secara linier karena tiap klien hanya berkomunikasi dengan server.
  • Karena aplikasi server dan client terpisah, server dapat dibuat menggunakan sistem yang berdaya tinggi dan fokus ke bagaimana menangani pemrosesan logika, sedangkan aplikasi klien bisa dibuat fokus pada grafik dan suara yang menawan. 
  • Keamanan lebih baik karena tiap klien hanya berkomunikasi dengan server, sehingga lebih mudah dikontrol. 
  • Memudahkan penyusunan dunia dalam game, karena terpusat di server. Update dan bug fix terhadap kode yang menyusun game lebih mudah.
Baca Juga :   Cara Screenshot Panjang Satu Halaman Penuh DI Android Paling Mudah

Kerugian.
  • Butuh usaha dan perencanaan lebih panjang. 
  • Lebih rumit karena aplikasi harus dibuat terpisah, untuk server dan client.

Bekerja dengan Pemain dan Grup.
Pemain.
Istilah pemain (player) pada pemrograman DirectPlay mengacu pada koneksi tunggal yang terhubung ke komputer lain melalui jaringan. Sebuah komputer dapat terdiri atas satu atau lebih pemain, bahkan sebuah server oleh DirectPlay juga dianggap sebagai pemain. 
Tiap pemain yang tergabung dalam sebuah sesi permainan, diidentifikasi menggunakan pengenal bertipe DPNID (atau TDPNID di header konversi Delphi). Tipe ini sejatinya adalah tipe Dword. Pengenal ini dihasilkan oleh DirectPlay ketika seorang pemain tergabung ke sebuah sesi permainan dan akan diinformasikan semua pemain yang tergabung dalam sesi permainan. Sobat bisa menggunakan pengenal ini untuk meminta data rinci seorang pemain seperti nama dan data terkait pemain tersebut dan juga untuk mengirim data ke pemain tersebut.
Grup.
Untuk game dengan skala lebih besar di mana jumlah pemain yang terhubung sangat banyak, sobat mungkin perlu membuat grup-grup untuk mengelompokkan pemain guna memudahkan penanganannya. Penggunaan grup, sedikit mempermudah proses pengiriman pesan untuk sekelompok pemain. 
Sobat bisa mengirim pesan ke sebuah grup dari pada harus mengirim pesan tersebut satu per satu ke tiap pemain. Tidak ada batasan berapa grup yang dapat sobat buat atau berapa pemain yang dapat sobat kelompokkan dalam satu grup. 
Sebuah grup juga dapat berisi grup lain seperti terlihat pada gmbar dibawah ini. Pemain dapat juga berdiri sendiri, tidak tergabung dalam grup manapun.
Membuat Aplikasi Multiplayer Menggunakan Directplay
Globally Unique Identifier (GUID). 
Globally Unique Identifier (GUID) sesuai namanya adalah pengenal yang unik secara global yang tersusun atas string alfanumerik. Karena besarnya ukuran data dan kompleksnya algoritma penyusunan GUID, GUID dijamin unik secara global. Jika sobat membuat GUID baru, dijamin tidak ada orang lain yang akan menghasilkan GUID yang sama.

GUID pada DirectPlay digunakan untuk identifikasi aplikasi. Jika membuat aplikasi baru, sobat perlu membuat GUID baru untuk aplikasi tersebut. Sobat bisa membuat GUID pada saat runtime, namun hal ini tidak perlu. sobat bisa menghasilkan GUID di Delphi dengan menekan kombinasi keyboard shortcut Shift+Ctrl+G.

Operasi Asynchronous dan Synchronous.
Operasi yang sobat kerjakan menggunakan DirectPlay dapat dibuat asynchronous atau synchronous. Pada operasi asynchronous, DirectPlay akan menjalankan operasi yang diminta dan segera mengembalikan kontrol ke aplikasi tanpa menunggu operasi tersebut selesai. DirectPlay akan mengembalikan nilai DPNSUCCESS_PENDING pada operasi asynchronous yang belum selesai.

Operasi asynchronous membuat aplikasi lebih responsif, namun prosesnya lebih rumit. Pada operasi synchronous, DirectPlay akan menunggu operasi hingga selesai baru kemudian mengembalikan kontrol ke aplikasi. Selama menunggu operasi selesai, aplikasi kita akan terlihat “hang” dan tidak responsif, namun prosesnya lebih sederhana.

Isu tentang Pengiriman.
Data Secara default, DirectPlay tidak menjamin data yang sobat kirim akan diterima oleh penerima. Paket data mungkin hilang pada saat dikirimkan ke jaringan dan ini sering kali terjadi. Untuk data yang tidak boleh hilang, sobat dapat memilih menggunakan pengiriman terjamin. Pada mode pengiriman terjamin, selama pemain masih terkoneksi, DirectPlay akan berusaha mengirim ulang paket-paket data yang drop sampai data lengkap terkirim.

Sisi buruknya, performa menurun karena membutuhkan waktu lebih banyak, terutama bila banyak paket data yang hilang. Pengiriman data juga tidak dienkripsi. Sobat dapat juga mengenkripsi data yang sobat kirim untuk mengamankan data tersebut. Enkripsi data juga menurunkan performa karena DirectPlay harus melakukan enkripsi data ketika mengirim dan dekripsi ketika menerimanya. Untungnya bagi kita, untuk memastikan data terkirim dan mengenkripsi data sangat mudah. Hanya masalah mengatur flag-flag yang sesuai.

Inisialisasi Peer-to-peer.
Karena topik DirectPlay ini cukup luas, di artikel ini, admin akan membatasi pada penjelasan bagaimana menciptakan sesi peer-to-peer. Untuk menciptakan IDirectPlay8Peer, sobat menggunakan CoCreateInstance() yang dideklarasi di unit ActiveX.pas. Sebelum memanggil CoCreateInstance(), sobat perlu memastikan COM telah diinisialisasi dengan CoInitialize(). Contoh bagaimana mendapatkan instance IDirectPlay8Peer adalah seperti Listing 1.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Jika sukses, FPeerNet, seperti yang tercantum pada Listing 1, akan diisi dengan alamat ke instance IDirectPlay8Peer. Jika gagal, maka FPeerNet berisi nil. Bila sukses, sobat bisa melanjutkan proses inisialisasi peer-to-peer dengan memanggil metode Initialize() milik IDirectPlay8Peer (Listing 2).

Membuat Aplikasi Multiplayer Menggunakan Directplay

Fungsi ini berguna untuk mendaftarkan fungsi callback yang akan dipanggil tiap kali instance IDirectPlay8Peer menerima pesan. Parameter pvUserContext adalah data yang akan dikirimkan melalui message handler yang alamatnya ada pada parameter pfn. dwFlags adalah flag inisialisasi seperti yang tercantum pada gambar dibawah ini.

Membuat Aplikasi Multiplayer Menggunakan Directplay
Message Callback Parameter pfn pada Listing 2 mendeskripsikan fungsi callback yang digunakan untuk komunikasi antara DirectPlay dan aplikasi kita. Parameter pfn bertipe TFNDPNMessageHandler atau PFNDPNMESSAGEHANDLER, deklarasinya adalah seperti Listing3.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Karena semua pesan yang dikirim jaringan akan melalui callback ini, fungsi callback ini sangat vital menentukan performa aplikasi sobat. Sangat tidak disarankan untuk meletakkan kode yang eksekusinya lambat dalam callback ini. Parameter pvUserContext pada Listing 3 adalah pointer ke data milik aplikasi kita. Isi parameter ini sama dengan isi parameter pvUserContext yang kita set pada saat pemanggilan Initialize() (Listing 2).

Baca Juga :   Cara Membuat Game Sederhana Dikomputer Menggunakan Notepad

Parameter dwMessageType adalah tipe pesan yang dikirim DirectPlay ke aplikasi kita. Tabel 2 berisi tipe-tipe pesan yang dikirim ke aplikasi. Kita akan membahas bagaimana meng-handle beberapa pesan umum pada artikel bagian ke-3 di bagian “Menangani Pesan Jaringan”. Parameter pMessage adalah pointer yang menunjuk ke struktur data yang terkait dengan sebuah pesan.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Penamaan struktur data terkait sebuah pesan, sama dengan nama tipe pesannya, kecuali bahwa DPN_MSGID diganti dengan DPNMSG. Contoh, pesan DPN_MSGID_CREATE_PLAYER terkait dengan struktur data DPNMSG_CREATE_PLAYER. Sesuai konvensi di Delphi, struktur data tersebut dinamai ulang menjadi TDPNMsgCreatePlayer. Membuat callback untuk menangani pesan dari DirectPlay cukup mudah.

Sobat tinggal mendeklarasikan sebuah fungsi bertipe TFNDPNMessageHandler dan memproses masing-masing data berdasarkan tipe pesannya. Callback ini, meskipun sobat yang membuat implementasinya, tidak dipanggil oleh aplikasi sobat secara langsung. DirectPlay yang akan memanggil callback ini ketika pesan dari jaringan perlu diproses aplikasi.

Yang sobat harus pastikan ketika menyusun implementasinya adalah fungsi tersebut harus berupa fungsi biasa (bukan fungsi bagian dalam sebuah kelas), karena cara melewatkan parameternya berbeda, dan jangan lupa menggunakan direktif stdcall. Kecuali untuk tipe pesan tertentu, biasanya sobat cukup mengembalikan nilai S_OK sebagai return value.

Contohnya deklarasi callback seperti pada Listing 4. Fungsi callback akan dipanggil dalam thread yang terpisah dari thread aplikasi, sehingga fungsi callback ini harus threadsafe. Sobat  mungkin perlu membuat mekanisme untuk mengontrol akses terhadap resource dalam callback ini.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Isu Multiple Thread DirectPlay menggunakan banyak thread untuk menangani message yang diterima dari jaringan. Pada saat kita melakukan inisialisasi objek peer-to-peer dan menentukan callback yang akan dipanggil DirectPlay, DirectPlay akan menciptakan sebuah thread baru, terpisah dari thread aplikasi utama, di mana callback akan dipanggil tiap kali ada pesan dari jaringan harus diproses aplikasi kita.

Manajemen thread-thread tersebut ditangani oleh DirectPlay dan untuk tingkat tertentu, transparan bagi aplikasi kita. Namun karena thread utama aplikasi dan thread yang diciptakan DirectPlay berada dalam satu proses, maka thread-thread tersebut juga berada dalam memory yang sama. Oleh karena itu, threadthread tersebut harus berbagi resource di memory ini.

Hal ini bisa menjadi masalah. Katakanlah sobat  memiliki dua thread yang harus mengakses sebuah variabel yang sama. Jika sebuah thread tersebut sedang membaca variabel tersebut dan thread lainnya berusaha menulis data ke variabel yang sama pada saat bersamaan, hasilnya mungkin tidak seperti yang diinginkan.

Untuk memecahkan masalah ini, kita bisa menggunakan critical section untuk melindungi suatu resource agar tidak dapat diakses oleh thread lain. Tiap kali sebuah thread hendak mengeksekusi bagian kode yang mengakses resource yang juga diakses oleh thread lain, akses ke resource tersebut kita blok dengan menguncinya.

Selama masih kita kunci dengan critical section, thread dapat dengan bebas memanipulasi isi resource tersebut. Thread lain yang hendak mengunci  bagian kode yang ditandai sebagai critical section harus menunggu sampai critical section dibebaskan. Segera setelah selesai, penguncian kita buka, sehingga thread lain dapat menggunakan resource tersebut.

Untuk masuk dan keluar critical section, kita menggunakan EnterCriticalSection() dan LeaveCriticalSection() (Listing 5). Variabel csData pada Listing 5 bertipe TRTLCriticalSection. Sebelum digunakan, csData harus diinisialiasasi menggunakan InitializeCriticalSection(). Setelah critical section tidak lagi dibutuhkan, bisa dihapus dengan memanggil DeleteCriticalSection().

Membuat Aplikasi Multiplayer Menggunakan Directplay

Apa yang kode sobat lakukan di antara pemanggilan EnterCriticalSection() dan LeaveCriticalSection() sebisa mungkin dipersingkat. Jika tidak, critical section bisa menghambat eksekusi thread lain sehingga menyebabkan turunnya performa aplikasi secara keseluruhan. Hal lain yang perlu dihindari adalah meletakkan critical section dalam critical section lain.

Baca Juga :   Cara Setting Dual Monitor di windows 10 dan Windows 7

Sobat  sebaiknya menghindari pemanggilan EnterCriticalSection() pada Listing 6. Kode pada Listing 6 sangat berpeluang menyebabkan deadlock. Jika thread A mencoba memasuki critical section csData2 yang sebelumnya sudah dimasuki thread B dan pada saat bersamaan thread B berusaha memasuki critical section csData yang sebelumnya sudah dimasuki thread A, kedua thread akan saling mengunci sehingga terjadilah deadlock.

Membuat Aplikasi Multiplayer Menggunakan Directplay
Inisialiasasi Alamat dan Memilih Service Provider.
Untuk bisa berkomunikasi dengan komputer-komputer lain, tiap komputer harus memiliki alamat  unik. Alamat komputer di mana aplikasi berjalan disebut sebagai alamat device (device address), sedangkan untuk alamat komputer yang hendak dituju diistilahkan sebagai alamat host (host address).

DirectPlay menggunakan string URL untuk mengacu pada alamat suatu komputer yang dibungkus dalam interface IDirectPlay8Address. Untuk memanipulasi URL, sobat  dapat menggunakan metode-metode yang disediakan interface ini.

Listing 7 berisi contoh bagaimana mendapatkan alamat instance IDirectPlay8Address. Kegunaan lain interface ini adalah untuk memilih service provider yang diinginkan menggunakan metode SetSP().

Membuat Aplikasi Multiplayer Menggunakan Directplay

Deklarasinya adalah seperti Listing 8. pguidSP berisi GUID service provider. Sobat bisa menggunakan nilai-nilai yang sudah tertentu seperti tercantum pada Tabel 3.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Untuk tiap-tiap service provider, sobat mungkin perlu mengubah beberapa parameter terkait protokol yang dipilih.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Untuk TCP/IP atau IPX, sobat mungkin perlu mengubah port yang digunakan, atau untuk koneksi melalui serial, sobat mungkin ingin mengubah baud rate, stop bits, parity, dan fl ow control perangkat serial. Untuk mengubah parameter service provider, sobat menggunakan metode AddComponent() milik interface IDirectPlay8Address (Listing 9). pwszName berisi nama komponen yang akan ditambahkan.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Jika sudah ada, nilainya akan diubah. Sobat bisa menggunakan beberapa nilai-nilai terdefinisi seperti pada Tabel 4.

Membuat Aplikasi Multiplayer Menggunakan Directplay

lpvData berisi pointer ke data. dwDataSize berisi ukuran data lpvData, sedangkan tipenya ditentukan parameter dwDataType. Tabel 5 berisi daftar tipe-tipe data. Listing 10 berisi contoh bagaimana mengubah port untuk TCP/IP.

Membuat Aplikasi Multiplayer Menggunakan Directplay

FAddrNet diasumsikan bertipe IDirectPlay8Address dan FPort adalah variabel bertipe Dword yang menyimpan data nomor port yang diinginkan.

Membuat Aplikasi Multiplayer Menggunakan Directplay
Mengatur Deskripsi Peer.
Informasi mengenai peer seperti nama dan data yang kita asosiasikan dengan suatu player perlu diset untuk identifi kasi bagi peer lain. Sobat harus mengatur deskripsi peer sebelum membuat sesi atau bergabung ke sesi yang sudah ada. Untuk mengatur deskripsi peer, sobat memanggil SetPeerInfo() milik  IDirectPlay8Peer. Deklarasi fungsi ini ada pada Listing 11.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Deklarasi tipe TDPNPlayerInfo tercantum pada Listing 12. Field-fi eld tipe data ini adalah :

Membuat Aplikasi Multiplayer Menggunakan Directplay
Membuat Aplikasi Multiplayer Menggunakan Directplay
Membuat Aplikasi Multiplayer Menggunakan Directplay
  • dwSize, ukuran struktur data ini. Field ini harus sobat isi dengan sizeof(TDPNPlayerInfo).
  • dwInfoFlags, flag berisi data apa yang dikandung. Ada dua nilai untuk flag ini : 

1. DPNINFO_NAME, jika flag ini digunakan, field pwszName berisi data yang valid.
2. DPNINFO_DATA., field pvData berisi data yang valid.

  • pwszName, nama player dalam format Unicode. 
  • pvData, data player. 
  • dwDataSize, ukuran yang tersimpan dalam pvData. 
  • dwPlayerFlags, flag status player apakah sebagai host atau player biasa. Isinya salah satu dari nilai berikut : 

1. DPNPLAYER_LOCAL, player biasa.

2. DPNPLAYER_HOST, player yang juga bertugas sebagai host.

Contoh bagaimana mengatur nama player dapat sobat pelajari di Listing 13. Seperti biasa, kita perlu mengisi struktur data ini dengan nol, lalu mengisi field dwSize dengan ukuran tipe TDPNPlayerInfo. Variabel PlayerName diasumsikan bertipe string berisi nama player, wName bertipe widestring.

Membuat Aplikasi Multiplayer Menggunakan Directplay

Di sini kita perlu mengonversi string ke widestring agar dapat kita typecast ke PWideChar. Untuk mendapatkan nama player dengan akurat, sobat perlu memanggil GetPeerInfo() dua kali. Pertama untuk mendapatkan ukuran data player dan kedua untuk mengambil data player. Listing 14 berisi contoh bagaimana mendapatkan nama player menggunakan ID player (DPNID).

Membuat Aplikasi Multiplayer Menggunakan Directplay
Ringkasan DirectPlay memungkinkan sobat membangun aplikasi jaringan terutama game online multiplayer dengan lebih mudah. Membebaskan sobat dari detail perbedaan protokol dan perangkat keras jaringan yang menghubungkan masing-masing komputer sehingga bisa fokus ke logika aplikasi.

Di di bagian pertama artikel ini, sobat sudah memperoleh informasi tentang konsep dasar DirectPlay, bagaimana inisialisasi DirectPlay untuk model peer-to-peer pada bagian akhir sobat juga telah mengetahui bagaimana mengatur deksripsi peer. Pada artikel berikutnya, kita akan membahas bagaimana mengelola sesi permainan meliputi menciptakan dan bergabung dengan sebuah sesi.

Leave a Comment