Kami nyerat matchmaking pikeun Dota 2014

Sampurasun sadayana.

Musim semi ieu kuring mendakan proyék dimana budak lalaki diajar kumaha ngajalankeun versi server Dota 2 2014 sareng, sasuai, maén dina éta. Abdi kipas ageung tina kaulinan ieu, sareng kuring henteu tiasa ngantunkeun kasempetan unik ieu pikeun neuleumkeun diri dina budak leutik.

Kuring japati pisan deeply, sarta eta jadi kajadian nu kuring nulis bot Discord nu tanggung jawab ampir sakabéh pungsi nu teu dirojong dina versi heubeul game, nyaéta matchmaking.
Sateuacan sadaya inovasi sareng bot, lobi didamel sacara manual. Urang dikumpulkeun 10 réaksi kana pesen na sacara manual dirakit server a, atanapi hosted a lobi lokal.

Kami nyerat matchmaking pikeun Dota 2014

Sifat kuring salaku programmer teu bisa tahan jadi loba karya manual, sarta sapeuting kuring sketched kaluar versi pangbasajanna tina bot, nu otomatis ngangkat server lamun aya 10 jalma.

Kuring geuwat mutuskeun nulis dina nodejs, sabab kuring teu bener resep Python, sarta kuring ngarasa leuwih nyaman di lingkungan ieu.

Ieu mangrupikeun pangalaman munggaran kuring nyerat bot pikeun Discord, tapi tétéla saderhana pisan. Modul npm resmi discord.js nyayogikeun antarbeungeut anu cocog pikeun damel sareng pesen, ngumpulkeun réaksi, jsb.

Bantahan: Sadaya conto kode anu "ayeuna", hartina maranéhna geus ngaliwatan sababaraha iterasi nulis balik peuting.

Dasar matchmaking mangrupakeun "antrian" nu pamaén anu rék maén disimpen di na dihapus nalika maranéhna teu hayang atawa manggihan kaulinan.

Ieu naon hakekat "pamuter" Sigana mah. Mimitina éta ngan ukur id pangguna dina Discord, tapi aya rencana pikeun ngaluncurkeun / milarian kaulinan tina situs éta, tapi mimitina.

export enum Realm {
  DISCORD,
  EXTERNAL,
}

export default class QueuePlayer {
  constructor(public readonly realm: Realm, public readonly id: string) {}

  public is(qp: QueuePlayer): boolean {
    return this.realm === qp.realm && this.id === qp.id;
  }

  static Discord(id: string) {
    return new QueuePlayer(Realm.DISCORD, id);
  }

  static External(id: string) {
    return new QueuePlayer(Realm.EXTERNAL, id);
  }
}

Sareng ieu mangrupikeun antarmuka antrian. Di dieu, tinimbang "pamaén," abstraksi dina bentuk "grup" dipaké. Pikeun pamaén tunggal, grup diwangun ku dirina, sarta pikeun pamaén dina grup, masing-masing, sadaya pamaén dina grup.

export default interface IQueue extends EventEmitter {
  inQueue: QueuePlayer[]
  put(uid: Party): boolean;
  remove(uid: Party): boolean;
  removeAll(ids: Party[]): void;

  mode: MatchmakingMode
  roomSize: number;
  clear(): void
}

Kuring mutuskeun pikeun ngagunakeun acara pikeun tukeur konteks. Éta cocog pikeun kasus - dina acara "kaulinan pikeun 10 urang kapanggih", anjeun tiasa ngirim pesen anu dipikabutuh pikeun pamaén dina pesen pribadi, sareng ngalaksanakeun logika bisnis dasar - ngaluncurkeun tugas pikeun mariksa kesiapan, nyiapkeun lobi. pikeun peluncuran, jeung saterusna.

Pikeun IOC kuring nganggo InversifyJS. Kuring boga pangalaman pikaresepeun gawé bareng perpustakaan ieu. Gancang sareng gampang!

Kami ngagaduhan sababaraha antrian dina server kami - kami parantos nambihan 1x1, normal/dipeunteun, sareng sababaraha modeu khusus. Ku alatan éta, aya singleton RoomService anu perenahna antara pamaké sarta pilarian kaulinan.

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)
          }
        });
      }
    );
  }

(Kode mie pikeun masihan gambaran ngeunaan kumaha rupa prosésna)

Di dieu kuring initialize antrian pikeun tiap tina modus kaulinan dilaksanakeun, sarta ogé ngadangukeun parobahan dina "grup" guna nyaluyukeun antrian jeung nyingkahan sababaraha konflik.

Janten, saé, kuring nyelapkeun potongan kode anu teu aya hubunganana sareng topikna, sareng ayeuna hayu urang langsung ka matchmaking.

Hayu urang nganggap kasus:

1) pamaké hayang maénkeun.

2) Pikeun ngamimitian milarian, anjeunna nganggo Gateway=Discord, nyaéta, nempatkeun réaksi kana pesen:

Kami nyerat matchmaking pikeun Dota 2014

3) Gerbang ieu angkat ka RoomService sareng nyarios "Pamaké ti discord hoyong asup kana antrian, mode: kaulinan anu teu dipeunteun."

4) RoomService nampi pamundut gateway sareng ngadorong pangguna (langkung tepatna, grup pangguna) kana antrian anu dipikahoyong.

5) antrian cek unggal waktos aya cukup pamaén maén. Mun mungkin, emit hiji acara:

private onRoomFound(players: Party[]) {
    this.emit("room-found", {
      players,
    });
  }

6) RoomService écés happily ngadangukeun unggal antrian dina antisipasi hariwang tina acara ieu. Kami nampi daptar pamaén salaku input, ngabentuk "kamar" maya ti aranjeunna, sareng, tangtosna, ngaluarkeun acara:

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) Janten urang ngagaduhan otoritas "pangluhurna" - kelas bot. Sacara umum, anjeunna ngurus sambungan antara gateways (Kuring teu bisa ngarti kumaha lucu eta Sigana di Rusia) jeung logika bisnis matchmaking. Bot éta ngadéngé kajadian éta sareng maréntahkeun DiscordGateway pikeun ngirim cek kesiapan ka sadaya pangguna.

Kami nyerat matchmaking pikeun Dota 2014

8) Upami aya anu nampik atanapi henteu nampi pertandingan dina 3 menit, maka kami henteu uih deui kana antrian. Urang balik dulur sejenna ka antrian jeung antosan dugi aya 10 urang deui. Lamun kabeh pamaén geus narima kaulinan, lajeng bagian metot dimimitian.

Konfigurasi server dedicated

Kaulinan urang diayakeun dina VDS sareng server Windows 2012. Ti ieu urang tiasa ngagambar sababaraha kacindekan:

  1. Henteu aya docker dina éta, anu pencét kuring dina haté
  2. Urang nyimpen dina nyewa

Tugasna nyaéta ngajalankeun prosés dina VDS tina VPS dina Linux. Kuring nulis server basajan dina Flask. Leres, kuring henteu resep Python, tapi naon anu anjeun tiasa laksanakeun? Éta langkung gancang sareng langkung gampang nyerat server ieu dina éta.

Éta ngalaksanakeun 3 fungsi:

  1. Dimimitian server kalawan konfigurasi a - milih peta, Jumlah pamaén pikeun ngamimitian kaulinan, sarta susunan plugins. Kuring moal nulis ngeunaan plugins ayeuna - éta carita béda jeung liter kopi peuting dicampurkeun jeung lawon sarta bulu torn.
  2. Ngeureunkeun / ngabalikan deui server bisi sambungan gagal, nu urang ngan bisa nanganan sacara manual.

Sadayana saderhana di dieu, conto kode bahkan henteu pantes. 100 naskah garis

Janten, nalika 10 jalma ngumpul sareng nampi pertandingan, server diluncurkeun sareng sadayana hoyong pisan maén, tautan pikeun nyambung ka buruan dikirim dina pesen pribadi.

Kami nyerat matchmaking pikeun Dota 2014

Ku ngaklik on link, pamaén nyambung ka server kaulinan, lajeng éta. Saatos ~ 25 menit, "kamar" maya sareng pamaén diberesihan.

Hapunten sateuacanna pikeun kagok tulisan, kuring parantos lami henteu nyerat di dieu, sareng seueur teuing kode pikeun nyorot bagian penting. Mie, pondokna.

Upami kuring ningali minat topik, bakal aya bagian kadua - éta bakal ngandung siksa kuring sareng plugins pikeun srcds (Sumber dedicated server), sareng, sigana, sistem rating sareng mini-dotabuff, situs kalayan statistik kaulinan.

Sababaraha tumbu:

  1. Website kami (statistik, leaderboard, halaman badarat leutik sareng unduhan klien)
  2. server Discord

sumber: www.habr.com

Tambahkeun komentar