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 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).
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.
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:
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!