Ke lawe ʻana i kahi pāʻani multiplayer mai C++ i ka pūnaewele me Cheerp, WebRTC a me Firebase

Hōʻike

ko makou hui Leaning Technologies hāʻawi i nā hāʻina no ka lawe ʻana i nā noi papa maʻamau i ka pūnaewele. ʻO kā mākou C++ compiler ʻoliʻoli hoʻopuka i kahi hui o WebAssembly a me JavaScript, e hāʻawi ana i nā mea ʻelua ka launa pūnaewele maʻalahi, a me ka hana kiʻekiʻe.

Ma keʻano he laʻana o kāna noi, ua hoʻoholo mākou e lawe i kahi pāʻani multiplayer i ka pūnaewele a koho Kauweehu. ʻO Teeworlds kahi pāʻani XNUMXD retro multiplayer me kahi kaiāulu liʻiliʻi akā ikaika o nā mea pāʻani (me aʻu pū!). He mea liʻiliʻi ia ma nā ʻōlelo o nā kumuwaiwai i hoʻoiho ʻia a me nā koi CPU a me GPU - he moho kūpono.

Ke lawe ʻana i kahi pāʻani multiplayer mai C++ i ka pūnaewele me Cheerp, WebRTC a me Firebase
Ke holo nei ma ka polokalamu kele pūnaewele ʻo Teeworlds

Ua hoʻoholo mākou e hoʻohana i kēia papahana e hoʻokolohua nā hāʻina maʻamau no ka lawe ʻana i nā code pūnaewele i ka pūnaewele. Hana ʻia kēia ma nā ʻano penei:

  • XMLHttpRequest/fetch, inā he mau noi HTTP wale nō ka ʻāpana pūnaewele, a i ʻole
  • Pūnaewele Pūnaewele.

Pono nā hoʻonā ʻelua e hoʻokipa i kahi kikowaena kikowaena ma ka ʻaoʻao kikowaena, a ʻaʻole ʻae ʻia e hoʻohana ʻia ma ke ʻano he protocol transport UDP. He mea nui kēia no nā noi manawa maoli e like me nā polokalamu kūkā wikiō a me nā pāʻani, no ka mea e hōʻoiaʻiʻo i ka hāʻawi ʻana a me ke kauoha o nā ʻeke protocol. TCP hiki ke lilo i mea keakea i ka haʻahaʻa latency.

Aia kahi ala ʻekolu - e hoʻohana i ka pūnaewele mai ka polokalamu kele pūnaewele: WebRTC.

RTCDataChannel Kākoʻo ia i ka hoʻouna pono ʻole a me ka hilinaʻi ʻole (ma ka hihia hope e hoʻāʻo ai e hoʻohana i ka UDP ma ke ʻano he protocol transport ke hiki), a hiki ke hoʻohana ʻia me kahi kikowaena mamao a ma waena o nā polokalamu kele pūnaewele. 'O ia ho'i, hiki iā mākou ke ho'okomo i ka polokalamu holo'oko'a i ka polokalamu kele pūnaewele, me ka mea kikowaena!

Eia naʻe, hiki mai kēia me ka pilikia hou: ma mua o ka hiki ʻana o ʻelua mau hoa WebRTC ke kamaʻilio, pono lākou e hana i kahi lulu lima paʻakikī e hoʻopili ai, e koi ana i kekahi mau hui ʻaoʻao ʻekolu (kahi kikowaena hōʻailona a hoʻokahi a ʻoi aʻe paha mau kikowaena. STUN/ʻO TURN).

Ma ke kūpono, makemake mākou e hana i kahi API pūnaewele e hoʻohana ana i ka WebRTC i loko, akā kokoke loa i kahi UDP Sockets interface ʻaʻole pono e hoʻokumu i kahi pilina.

E ʻae kēia iā mākou e hoʻohana pono i ka WebRTC me ka ʻole e hōʻike i nā kikoʻī paʻakikī i ke code noi (a mākou i makemake ai e hoʻololi liʻiliʻi i kā mākou papahana).

WebRTC liʻiliʻi loa

ʻO WebRTC kahi pūʻulu o nā API i loaʻa i nā mākaʻikaʻi e hāʻawi ana i ka hoʻouna ʻana o nā hoa-a-peer o nā leo, wikiō a me nā ʻikepili ʻole.

Hoʻokumu ʻia ka pilina ma waena o nā hoa (ʻoiai inā he NAT ma kekahi ʻaoʻao a ʻelua paha) me ka hoʻohana ʻana i nā kikowaena STUN a/a i ʻole TURN ma o kahi mīkini i kapa ʻia ʻo ICE. Hoʻololi nā hoa i ka ʻike ICE a me nā ʻāpana kahawai ma o ka hāʻawi a me ka pane o ka protocol SDP.

Auwe! ʻEhia mau pōkole i ka manawa hoʻokahi? E wehewehe pōkole kākou i ke ʻano o kēia mau huaʻōlelo:

  • Nā mea hoʻohana no ka NAT (STUN) - he protocol no ke kāʻalo ʻana iā NAT a loaʻa i kahi pālua (IP, port) no ka hoʻololi pololei ʻana i ka ʻikepili me ka mea hoʻokipa. Inā hoʻokō ʻo ia i kāna hana, hiki i nā hoa ke hoʻololi kūʻokoʻa i ka ʻikepili me kekahi.
  • Kaʻahele e hoʻohana ana i nā Relay a puni NAT (ʻO TURN) hoʻohana ʻia no ka hele ʻana o NAT, akā hoʻokō ʻo ia i kēia ma ka hoʻouna ʻana i ka ʻikepili ma o kahi koho i ʻike ʻia e nā hoa ʻelua. Hoʻohui ia i ka latency a ʻoi aku ka pipiʻi o ka hoʻokō ʻana ma mua o STUN (no ka mea, ua hoʻohana ʻia i loko o ke kau kamaʻilio holoʻokoʻa), akā i kekahi manawa ʻo ia wale nō ke koho.
  • Hoʻokumu Hoʻohui Kūkākūkā (hau) hoʻohana ʻia e koho i ke ala maikaʻi loa o ka hoʻopili ʻana i ʻelua mau hoa ma muli o ka ʻike i loaʻa mai ka hoʻopili pololei ʻana i nā hoa, a me ka ʻike i loaʻa e kekahi helu o nā kikowaena STUN a me TURN.
  • Kūkākūkā wehewehe kau (SDP) he ʻano ia no ka wehewehe ʻana i nā ʻāpana alani pili, no ka laʻana, nā moho ICE, nā codec multimedia (i ke ʻano o kahi kaila leo/wikiō), a pēlā aku... Hoʻouna kekahi o nā hoa i kahi hāʻawi SDP, a pane ka lua me kahi pane SDP . Ma hope o kēia, hana ʻia kahi kanal.

No ka hana ʻana i ia pilina, pono nā hoa e hōʻiliʻili i ka ʻike i loaʻa iā lākou mai nā kikowaena STUN a me TURN a hoʻololi iā ia me kekahi.

ʻO ka pilikia, ʻaʻole hiki iā lākou ke kamaʻilio pololei, no laila pono e loaʻa kahi ʻano hana o waho e hoʻololi i kēia ʻikepili: kahi kikowaena hōʻailona.

Hiki ke maʻalahi ke kikowaena hōʻailona no ka mea ʻo kāna hana wale nō ka hoʻouna ʻana i ka ʻikepili ma waena o nā hoa i ka manawa lulu lima (e like me ka hōʻike ʻana ma ke kiʻikuhi ma lalo nei).

Ke lawe ʻana i kahi pāʻani multiplayer mai C++ i ka pūnaewele me Cheerp, WebRTC a me Firebase
Kiʻikuhi kaʻina lima WebRTC maʻalahi

Hōʻike Hōʻikeʻike ʻo Teeworlds Network Model

He mea maʻalahi loa ka hoʻolālā pūnaewele ʻo Teeworlds:

  • ʻO nā mea kūʻai a me nā mea kikowaena ʻelua mau papahana like ʻole.
  • Hoʻokomo nā mea kūʻai aku i ka pāʻani ma ka hoʻopili ʻana i kekahi o nā kikowaena, ʻo kēlā me kēia mea hoʻokipa hoʻokahi wale nō pāʻani i ka manawa.
  • Lawe ʻia nā hoʻoili ʻikepili āpau i ka pāʻani ma o ke kikowaena.
  • Hoʻohana ʻia kahi kikowaena haku kūikawā e hōʻiliʻili i kahi papa inoa o nā kikowaena lehulehu āpau i hōʻike ʻia ma ka mea kūʻai pāʻani.

Mahalo i ka hoʻohana ʻana o WebRTC no ka hoʻololi ʻana i ka ʻikepili, hiki iā mākou ke hoʻololi i ka ʻāpana kikowaena o ka pāʻani i ka polokalamu kele pūnaewele kahi i loaʻa ai ka mea kūʻai. Hāʻawi kēia iā mākou i kahi manawa kūpono ...

E hoʻopau i nā kikowaena

Loaʻa ka maikaʻi o ka nele o ka logic server: hiki iā mākou ke kau i ka noi holoʻokoʻa e like me ka ʻikepili static ma nā ʻaoʻao Github a i ʻole ma kā mākou lako ponoʻī ma hope o Cloudflare, no laila e hōʻoia i ka hoʻoiho wikiwiki ʻana a me ka manawa kiʻekiʻe no ka manuahi. ʻOiaʻiʻo, hiki iā mākou ke hoʻopoina iā lākou, a inā ua laki mākou a lilo ka pāʻani i mea kaulana, a laila ʻaʻole pono e hoʻoponopono hou ʻia ka ʻōnaehana.

Eia naʻe, no ka hana ʻana o ka ʻōnaehana, pono mākou e hoʻohana i kahi hoʻolālā waho:

  • Hoʻokahi a ʻoi aku paha nā kikowaena STUN: He nui nā koho manuahi e koho ai.
  • Ma kahi o hoʻokahi kikowaena TURN: ʻaʻohe koho manuahi ma aneʻi, no laila hiki iā mākou ke hoʻonohonoho iā mākou iho a i ʻole e uku no ka lawelawe. ʻO ka mea pōmaikaʻi, ʻo ka hapa nui o ka manawa hiki ke hoʻokumu ʻia ka pilina ma o nā kikowaena STUN (a hāʻawi i ka p2p ʻoiaʻiʻo), akā pono ʻo TURN ma ke ʻano he koho fallback.
  • Pūnaehana hōʻailona: ʻAʻole like me nā ʻano ʻelua ʻē aʻe, ʻaʻole i hoʻohālikelike ʻia ka hōʻailona. He aha ke kuleana o ke kikowaena hōʻailona e pili ana i ka noi. I kā mākou hihia, ma mua o ka hoʻokumu ʻana i kahi pilina, pono e hoʻololi i kahi ʻikepili liʻiliʻi.
  • Teeworlds Master Server: Hoʻohana ʻia ia e nā kikowaena ʻē aʻe e hoʻolaha i ko lākou ola ʻana a e nā mea kūʻai aku e ʻimi i nā kikowaena lehulehu. ʻOiai ʻaʻole koi ʻia (hiki i nā mea kūʻai aku ke hoʻopili mau i kahi kikowaena a lākou i ʻike ai e pili ana i ka lima), maikaʻi ke loaʻa i hiki i nā mea pāʻani ke komo i nā pāʻani me nā poʻe maʻamau.

Ua hoʻoholo mākou e hoʻohana i nā kikowaena STUN manuahi a Google, a ua kau mākou i hoʻokahi kikowaena TURN iā mākou iho.

No nā helu hope ʻelua a mākou i hoʻohana ai Firebase:

  • Hoʻokō maʻalahi ka Teeworlds master server: ma ke ʻano he papa inoa o nā mea i loaʻa ka ʻike (inoa, IP, palapala ʻāina, mode, ...) o kēlā me kēia kikowaena hana. Hoʻopuka a hōʻano hou nā kikowaena i kā lākou mea ponoʻī, a lawe nā mea kūʻai aku i ka papa inoa holoʻokoʻa a hōʻike i ka mea pāʻani. Hōʻike pū mākou i ka papa inoa ma ka ʻaoʻao home e like me HTML i hiki i nā mea pāʻani ke kaomi wale i ke kikowaena a lawe pololei ʻia i ka pāʻani.
  • Hoʻopili pili ka hōʻailona i kā mākou hoʻokō sockets, i wehewehe ʻia ma ka ʻāpana aʻe.

Ke lawe ʻana i kahi pāʻani multiplayer mai C++ i ka pūnaewele me Cheerp, WebRTC a me Firebase
Ka papa inoa o nā kikowaena i loko o ka pāʻani a ma ka ʻaoʻao home

Ka hoʻokō ʻana i nā kumu

Makemake mākou e hana i kahi API e pili kokoke ana iā Posix UDP Sockets e hiki ai ke hōʻemi i ka nui o nā loli e pono ai.

Makemake mākou e hoʻokō i ka palena liʻiliʻi e pono ai no ka hoʻololi ʻikepili maʻalahi ma luna o ka pūnaewele.

No ka laʻana, ʻaʻole pono mākou i ke ala ala maoli: aia nā hoa āpau ma ka "LAN virtual" hoʻokahi e pili ana me kahi laʻana waihona waihona Firebase.

No laila, ʻaʻole pono mākou i nā helu IP kūʻokoʻa: ua lawa nā waiwai kī Firebase kūikawā (e like me nā inoa domain) e ʻike kūʻokoʻa i nā hoa, a hāʻawi kēlā me kēia hoa i nā wahi IP "hoʻopunipuni" i kēlā me kēia kī pono e unuhi ʻia. Hoʻopau loa kēia i ka pono no ka hāʻawi ʻana i ka IP address honua, kahi hana ʻole.

Eia ka API haʻahaʻa e pono ai mākou e hoʻokō:

// Create and destroy a socket
int socket();
int close(int fd);
// Bind a socket to a port, and publish it on Firebase
int bind(int fd, AddrInfo* addr);
// Send a packet. This lazily create a WebRTC connection to the 
// peer when necessary
int sendto(int fd, uint8_t* buf, int len, const AddrInfo* addr);
// Receive the packets destined to this socket
int recvfrom(int fd, uint8_t* buf, int len, AddrInfo* addr);
// Be notified when new packets arrived
int recvCallback(Callback cb);
// Obtain a local ip address for this peer key
uint32_t resolve(client::String* key);
// Get the peer key for this ip
String* reverseResolve(uint32_t addr);
// Get the local peer key
String* local_key();
// Initialize the library with the given Firebase database and 
// WebRTc connection options
void init(client::FirebaseConfig* fb, client::RTCConfiguration* ice);

He maʻalahi ka API a like me ka Posix Sockets API, akā he mau ʻokoʻa koʻikoʻi. ka hoʻopaʻa inoa ʻana i nā callbacks, ka hāʻawi ʻana i nā IP kūloko, a me nā pili palaualelo.

Hoʻopaʻa inoa Callbacks

ʻOiai inā hoʻohana ka papahana mua i ka I/O pale ʻole, pono e hoʻihoʻi ʻia ke code e holo i kahi polokalamu kele pūnaewele.

ʻO ke kumu o kēia, ua hūnā ʻia ka hanana hanana ma ka polokalamu kele pūnaewele mai ka papahana (ʻo JavaScript a i ʻole WebAssembly).

Ma ka ʻāina maoli hiki iā mākou ke kākau i nā code e like me kēia

while(running) {
  select(...); // wait for I/O events
  while(true) {
    int r = readfrom(...); // try to read
    if (r < 0 && errno == EWOULDBLOCK) // no more data available
      break;
    ...
  }
  ...
}

Inā hūnā ʻia ka loop loop iā mākou, a laila pono mākou e hoʻohuli iā ia i mea e like me kēia:

auto cb = []() { // this will be called when new data is available
  while(true) {
    int r = readfrom(...); // try to read
    if (r < 0 && errno == EWOULDBLOCK) // no more data available
      break;
    ...
  }
  ...
};
recvCallback(cb); // register the callback

Hāʻawi IP kūloko

ʻO nā ID node i kā mākou "pūnaewele" ʻaʻole ia he IP address, akā ʻo nā kī Firebase (he mau kaula lākou e like me kēia: -LmEC50PYZLCiCP-vqde ).

He mea maʻalahi kēia no ka mea ʻaʻole pono mākou i kahi mīkini no ka hāʻawi ʻana i nā IP a nānā i ko lākou ʻokoʻa (a me ka hoʻokuʻu ʻana iā lākou ma hope o ka hemo ʻana o ka mea kūʻai aku), akā pono pinepine e ʻike i nā hoa ma ka helu helu.

ʻO kēia ka mea e hoʻohana ʻia ai nā hana. resolve и reverseResolve: Loaʻa ka palapala noi i ka waiwai string o ke kī (ma o ka hoʻokomo mea hoʻohana a i ʻole ma ke kikowaena master), a hiki ke hoʻololi iā ia i kahi IP address no ka hoʻohana kūloko. Loaʻa i ke koena o ka API kēia waiwai ma mua o kahi kaula no ka maʻalahi.

Ua like kēia me ka huli DNS, akā hana ʻia ma ka ʻāina ma ka mea kūʻai.

ʻO ia hoʻi, ʻaʻole hiki ke kaʻana like i nā helu IP ma waena o nā mea kūʻai aku, a inā makemake ʻia kekahi ʻano ʻike honua, pono e hana ʻia ma kahi ʻano ʻokoʻa.

Pili palaualelo

ʻAʻole pono ka UDP i kahi pilina, akā e like me kā mākou i ʻike ai, pono ʻo WebRTC i kahi kaʻina pili lōʻihi ma mua o ka hiki ke hoʻomaka i ka hoʻoili ʻana i ka ʻikepili ma waena o nā hoa ʻelua.

Inā makemake mākou e hāʻawi i ka pae hoʻokahi o ka abstraction, (sendto/recvfrom me nā hoa like ʻole me ka ʻole o ka pilina mua), a laila pono lākou e hana i kahi pilina "palaualelo" (lohi) i loko o ka API.

ʻO kēia ka mea e hana nei i ka wā kamaʻilio maʻamau ma waena o ka "server" a me ka "client" i ka wā e hoʻohana ai i ka UDP, a me ka mea e pono ai kā mākou waihona:

  • Kahea kikowaena bind()e haʻi i ka ʻōnaehana hana e makemake ana e loaʻa nā packet ma ke awa i kuhikuhi ʻia.

Akā, e hoʻopuka mākou i kahi awa hāmama i Firebase ma lalo o ke kī kikowaena a hoʻolohe i nā hanana i kāna subtree.

  • Kahea kikowaena recvfrom(), e ʻae ana i nā ʻeke e hele mai ana mai nā mea hoʻokipa ma kēia awa.

I kā mākou hihia, pono mākou e nānā i ka laina komo o nā ʻeke i hoʻouna ʻia i kēia awa.

Loaʻa i kēlā me kēia awa kona pila ponoʻī, a hoʻohui mākou i ke kumu a me nā awa e hele ai i ka hoʻomaka ʻana o nā datagrams WebRTC i ʻike mākou i ka pila e hoʻouna ai i ka wā e hiki mai ai kahi ʻeke hou.

ʻAʻole pāpā ʻia ke kelepona, no laila inā ʻaʻohe ʻeke, hoʻihoʻi wale mākou -1 a hoʻonohonoho errno=EWOULDBLOCK.

  • Loaʻa i ka mea kūʻai aku ka IP a me ke awa o ke kikowaena e kekahi mau mea waho, a kāhea sendto(). Hana pū kēia i kahi kelepona kūloko. bind(), nolaila mahope recvfrom() e loaʻa ka pane me ka hoʻokō ʻole ʻana i ka bind.

I kā mākou hihia, loaʻa ka mea kūʻai aku ma waho i ke kī kaula a hoʻohana i ka hana resolve() e kiʻi i kahi helu IP.

I kēia manawa, hoʻomaka mākou i kahi lulu lima WebRTC inā ʻaʻole pili nā hoa ʻelua i kekahi i kekahi. Hoʻohana nā pilina i nā awa like ʻole o ka hoa like i ka WebRTC DataChannel like.

Hana pū mākou me ka ʻole bind()i hiki i ke kikowaena ke hoʻohui hou i ka wā e hiki mai ana sendto() ina ua pani ia no kekahi kumu.

Hoʻomaopopo ʻia ke kikowaena no ka pilina o ka mea kūʻai aku ke kākau ka mea kūʻai aku i kāna hāʻawi SDP ma lalo o ka ʻike awa kikowaena ma Firebase, a pane ke kikowaena me kāna pane ma laila.

Hōʻike ke kiʻikuhi ma lalo nei i kahi laʻana o ke kahe memo no kahi kumu kumu a me ka hoʻouna ʻana i ka memo mua mai ka mea kūʻai aku i ke kikowaena:

Ke lawe ʻana i kahi pāʻani multiplayer mai C++ i ka pūnaewele me Cheerp, WebRTC a me Firebase
Hoʻopiha piha i ka pae hoʻohui ma waena o ka mea kūʻai aku a me ke kikowaena

hopena

Inā ua heluhelu ʻoe i kēia mamao, makemake paha ʻoe e ʻike i ke kumumanaʻo i ka hana. Hiki ke pāʻani ma teeworlds.leaningtech.com, ho'āʻo!


Pāʻani aloha ma waena o nā hoa hana

Loaʻa ka code waihona waihona pūnaewele ma Github. E hui pū me ke kamaʻilio ʻana ma kā mākou channel ma Kuanui!

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka