Túto jar som narazil na projekt, v ktorom sa chlapci naučili, ako spustiť server Dota 2 verzie 2014, a podľa toho na ňom hrať. Som veľkým fanúšikom tejto hry a nemohol som si nechať ujsť túto jedinečnú príležitosť ponoriť sa do detstva.
Ponoril som sa veľmi hlboko, a tak sa stalo, že som napísal Discord bota, ktorý je zodpovedný za takmer všetky funkcie, ktoré nie sú podporované v starej verzii hry, konkrétne matchmaking.
Pred všetkými inováciami s robotom bola lobby vytvorená ručne. Zozbierali sme 10 reakcií na správu a ručne sme zostavili server alebo sme hostili miestnu lobby.
Moja povaha programátora nevydržala toľko ručnej práce a cez noc som načrtol najjednoduchšiu verziu bota, ktorý automaticky zdvihol server, keď tam bolo 10 ľudí.
Okamžite som sa rozhodol písať v nodejs, pretože nemám veľmi rád Python a v tomto prostredí sa cítim pohodlnejšie.
Toto je moja prvá skúsenosť s písaním robota pre Discord, ale ukázalo sa, že je to veľmi jednoduché. Oficiálny npm modul discord.js poskytuje pohodlné rozhranie pre prácu so správami, zbieranie reakcií atď.
Zrieknutie sa zodpovednosti: Všetky príklady kódu sú „aktuálne“, čo znamená, že prešli niekoľkými iteráciami prepisovania v noci.
Základom matchmakingu je „poradie“, v ktorom sú hráči, ktorí chcú hrať, umiestnení a odstránení, keď nechcú alebo nájdu hru.
Takto vyzerá podstata „hráča“. Spočiatku to bolo len ID používateľa v Discord, ale existujú plány na spustenie/vyhľadanie hier zo stránky, ale najprv.
A tu je rozhranie frontu. Tu sa namiesto „hráčov“ používa abstrakcia vo forme „skupiny“. Pre jedného hráča sa skupina skladá z neho samého a pre hráčov v skupine zo všetkých hráčov v skupine.
Rozhodol som sa využiť udalosti na výmenu kontextu. Bolo to vhodné pre prípady - pri udalosti „našla sa hra pre 10 ľudí“, môžete hráčom poslať potrebnú správu v súkromných správach a vykonať základnú obchodnú logiku - spustiť úlohu na kontrolu pripravenosti, pripraviť lobby na spustenie a pod.
Pre IOC používam InversifyJS. Mám príjemné skúsenosti s prácou s touto knižnicou. Rýchle a jednoduché!
Na našom serveri máme niekoľko frontov – pridali sme 1x1, normálny/hodnotený a niekoľko vlastných režimov. Preto existuje singleton RoomService, ktorý leží medzi používateľom a vyhľadávaním hry.
constructor(
@inject(GameServers) private gameServers: GameServers,
@inject(MatchStatsService) private stats: MatchStatsService,
@inject(PartyService) private partyService: PartyService
) {
super();
this.initQueue(MatchmakingMode.RANKED);
this.initQueue(MatchmakingMode.UNRANKED);
this.initQueue(MatchmakingMode.SOLOMID);
this.initQueue(MatchmakingMode.DIRETIDE);
this.initQueue(MatchmakingMode.GREEVILING);
this.partyService.addListener(
"party-update",
(event: PartyUpdatedEvent) => {
this.queues.forEach((q) => {
if (has(q.queue, (t) => t.is(event.party))) {
// if queue has this party, we re-add party
this.leaveQueue(event.qp, q.mode)
this.enterQueue(event.qp, q.mode)
}
});
}
);
this.partyService.addListener(
"party-removed",
(event: PartyUpdatedEvent) => {
this.queues.forEach((q) => {
if (has(q.queue, (t) => t.is(event.party))) {
// if queue has this party, we re-add party
q.remove(event.party)
}
});
}
);
}
(Napíšte rezance, aby ste získali predstavu o tom, ako procesy zhruba vyzerajú)
Tu inicializujem front pre každý z implementovaných herných režimov a tiež počúvam zmeny v „skupinách“, aby som upravil fronty a predišiel niektorým konfliktom.
Takže výborne, vložil som kúsky kódu, ktoré nemajú nič spoločné s témou, a teraz prejdime priamo k matchmakingu.
Zoberme si prípad:
1) Používateľ chce hrať.
2) Na spustenie vyhľadávania použije Gateway=Discord, to znamená, že zareaguje na správu:
3) Táto brána prejde do RoomService a povie „Používateľ z discordu chce vstúpiť do frontu, režim: neohodnotená hra.“
4) RoomService prijme požiadavku brány a zatlačí používateľa (presnejšie skupinu používateľov) do požadovaného poradia.
5) Fronta kontroluje vždy, keď je dostatok hráčov na hranie. Ak je to možné, vygenerujte udalosť:
6) RoomService zjavne s radosťou počúva každý rad v napätom očakávaní tejto udalosti. Ako vstup dostaneme zoznam hráčov, vytvoríme z nich virtuálnu „miestnosť“ a, samozrejme, vydáme udalosť:
queue.addListener("room-found", (event: RoomFoundEvent) => {
console.log(
`Room found mode: [${mode}]. Time to get free room for these guys`
);
const room = this.getFreeRoom(mode);
room.fill(event.players);
this.onRoomFormed(room);
});
7) Tak sme sa dostali k „najvyššej“ autorite – triede Bot. Vo všeobecnosti sa zaoberá prepojením medzi bránami (nechápem, ako vtipne to vyzerá v ruštine) a obchodnou logikou matchmakingu. Robot si vypočuje udalosť a nariadi DiscordGateway, aby poslala kontrolu pripravenosti všetkým používateľom.
8) Ak niekto hru odmietne alebo neprijme do 3 minút, NEVRÁTAME ho do poradia. Všetkých ostatných vraciame do radu a čakáme, kým bude opäť 10 ľudí. Ak všetci hráči prijali hru, začína sa zaujímavá časť.
Konfigurácia dedikovaného servera
Naše hry sú hosťované na VDS s Windows serverom 2012. Z toho môžeme vyvodiť niekoľko záverov:
Nie je na ňom žiadny doker, čo ma zasiahlo do srdca
Šetríme na nájomnom
Úlohou je spustiť proces na VDS z VPS na Linuxe. Napísal som jednoduchý server vo Flasku. Áno, nemám rád Python, ale čo môžete robiť? Napísať tento server na ňom je rýchlejšie a jednoduchšie.
Vykonáva 3 funkcie:
Spustenie servera s konfiguráciou - výber mapy, počtu hráčov na spustenie hry a sady pluginov. Nebudem teraz písať o pluginoch - to je iný príbeh s litrami kávy v noci zmiešanými so slzami a vytrhanými vlasmi.
Zastavenie/reštart servera v prípade neúspešných spojení, ktoré môžeme riešiť iba manuálne.
Všetko je tu jednoduché, príklady kódu nie sú ani vhodné. 100 riadkový skript
Keď sa teda 10 ľudí zišlo a prijalo hru, server bol spustený a všetci sa chystali hrať, v súkromných správach bol odoslaný odkaz na pripojenie k hre.
Kliknutím na odkaz sa hráč pripojí k hernému serveru a je to. Po ~25 minútach sa virtuálna „miestnosť“ s hráčmi vyčistí.
Vopred sa ospravedlňujem za nešikovnosť článku, dlho som sem nepísal a je tu príliš veľa kódu na zvýraznenie dôležitých častí. Skrátka rezance.
Ak uvidím záujem o tému, bude aj druhá časť - bude obsahovať moje trápenie s pluginmi pre srcds (Source dedikovaný server) a pravdepodobne aj systém hodnotenia a mini-dotabuff, stránku s hernými štatistikami.