Rydym yn ysgrifennu paru ar gyfer Dota 2014

Helo pawb

Y gwanwyn hwn des i ar draws prosiect lle dysgodd y dynion sut i redeg fersiwn gweinydd Dota 2 2014 ac, yn unol â hynny, chwarae arno. Rwy'n gefnogwr mawr o'r gêm hon, ac ni allwn golli'r cyfle unigryw hwn i ymgolli yn fy mhlentyndod.

Rwy'n colomenu'n ddwfn iawn, ac felly digwyddodd imi ysgrifennu bot Discord sy'n gyfrifol am bron yr holl ymarferoldeb nad yw'n cael ei gefnogi yn hen fersiwn y gêm, sef paru.
Cyn yr holl ddatblygiadau arloesol gyda'r bot, crëwyd y lobi â llaw. Casglwyd 10 ymateb i neges a gosod gweinyddwr â llaw, neu gynnal lobi leol.

Rydym yn ysgrifennu paru ar gyfer Dota 2014

Ni allai fy natur fel rhaglennydd wrthsefyll cymaint o waith llaw, a thros nos fe wnes i fraslunio'r fersiwn symlaf o'r bot, a oedd yn codi'r gweinydd yn awtomatig pan oedd 10 o bobl.

Penderfynais ar unwaith ysgrifennu mewn nodejs, oherwydd nid wyf yn hoff iawn o Python, ac rwy'n teimlo'n fwy cyfforddus yn yr amgylchedd hwn.

Dyma fy mhrofiad cyntaf yn ysgrifennu bot ar gyfer Discord, ond trodd allan i fod yn syml iawn. Mae'r modiwl npm swyddogol discord.js yn darparu rhyngwyneb cyfleus ar gyfer gweithio gyda negeseuon, casglu adweithiau, ac ati.

Ymwadiad: Mae'r holl enghreifftiau cod yn “gyfredol”, sy'n golygu eu bod wedi mynd trwy sawl fersiwn o ailysgrifennu gyda'r nos.

Sail paru yw “ciw” lle mae chwaraewyr sydd eisiau chwarae yn cael eu gosod a'u tynnu pan nad ydyn nhw eisiau neu ddod o hyd i gêm.

Dyma sut olwg sydd ar hanfod “chwaraewr”. I ddechrau, dim ond ID defnyddiwr ydoedd yn Discord, ond mae cynlluniau i lansio / chwilio am gemau o'r wefan, ond pethau cyntaf yn gyntaf.

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

A dyma'r rhyngwyneb ciw. Yma, yn lle “chwaraewyr,” defnyddir tyniad ar ffurf “grŵp”. Ar gyfer un chwaraewr, mae'r grŵp yn cynnwys ei hun, ac ar gyfer chwaraewyr mewn grŵp, yn y drefn honno, o'r holl chwaraewyr yn y grŵp.

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
}

Penderfynais ddefnyddio digwyddiadau i gyfnewid cyd-destun. Roedd yn addas ar gyfer achosion - ar y digwyddiad "darganfuwyd gêm ar gyfer 10 o bobl", gallwch anfon y neges angenrheidiol at y chwaraewyr mewn negeseuon preifat, a chyflawni'r rhesymeg fusnes sylfaenol - lansio tasg i wirio parodrwydd, paratoi'r lobi ar gyfer lansio, ac ati.

Ar gyfer IOC rwy'n defnyddio InversifyJS. Rwy'n cael profiad pleserus yn gweithio gyda'r llyfrgell hon. Cyflym a hawdd!

Mae gennym ni sawl ciw ar ein gweinydd - rydym wedi ychwanegu 1x1, arferol / graddedig, a chwpl o foddau arferiad. Felly mae yna Ystafell Singleton Service sydd rhwng y defnyddiwr a'r chwiliad gêm.

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

(Codiwch nwdls i roi syniad o sut olwg sydd ar y prosesau yn fras)

Yma rwy'n cychwyn y ciw ar gyfer pob un o'r dulliau gêm a weithredwyd, a hefyd yn gwrando am newidiadau mewn “grwpiau” er mwyn addasu'r ciwiau ac osgoi rhai gwrthdaro.

Felly, da iawn chi, fe fewnosodais ddarnau o god nad oes a wnelont ddim â'r pwnc, a nawr gadewch i ni symud ymlaen yn uniongyrchol at baru.

Gadewch i ni ystyried yr achos:

1) Mae'r defnyddiwr eisiau chwarae.

2) Er mwyn cychwyn y chwiliad, mae'n defnyddio Gateway=Discord, hynny yw, yn rhoi ymateb i'r neges:

Rydym yn ysgrifennu paru ar gyfer Dota 2014

3) Mae'r porth hwn yn mynd i RoomService ac yn dweud “Mae defnyddiwr anghytgord eisiau mynd i mewn i'r ciw, modd: gêm heb sgôr.”

4) Mae RoomService yn derbyn cais y porth ac yn gwthio'r defnyddiwr (yn fwy manwl gywir, y grŵp defnyddwyr) i'r ciw a ddymunir.

5) Mae'r ciw yn gwirio bob tro mae digon o chwaraewyr i chwarae. Os yn bosibl, allyrru digwyddiad:

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

6) Mae RoomService yn amlwg yn hapus yn gwrando ar bob ciw gan ragweld y digwyddiad hwn yn bryderus. Rydyn ni'n derbyn rhestr o chwaraewyr fel mewnbwn, yn ffurfio “ystafell” rithwir ganddyn nhw, ac, wrth gwrs, yn cyhoeddi digwyddiad:

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) Felly dyma gyrraedd yr awdurdod “uchaf” – y dosbarth bot. Yn gyffredinol, mae'n delio â'r cysylltiad rhwng pyrth (ni allaf ddeall pa mor ddoniol y mae'n edrych yn Rwsieg) a rhesymeg busnes paru. Mae'r bot yn clywed y digwyddiad ac yn gorchymyn i DiscordGateway anfon siec parodrwydd at bob defnyddiwr.

Rydym yn ysgrifennu paru ar gyfer Dota 2014

8) Os bydd rhywun yn gwrthod neu ddim yn derbyn y gêm o fewn 3 munud, yna PEIDIWCH â'u dychwelyd i'r ciw. Rydyn ni'n dychwelyd pawb arall i'r ciw ac yn aros nes bod 10 o bobl eto. Os yw pob chwaraewr wedi derbyn y gêm, yna mae'r rhan ddiddorol yn dechrau.

Ffurfweddiad gweinydd pwrpasol

Mae ein gemau yn cael eu cynnal ar VDS gyda gweinydd Windows 2012. O hyn gallwn ddod i nifer o gasgliadau:

  1. Nid oes unrhyw dociwr arno, sy'n taro fi yn y galon
  2. Rydym yn arbed ar rent

Y dasg yw rhedeg proses ar VDS o VPS ar Linux. Ysgrifennais weinydd syml yn Fflasg. Ydw, dydw i ddim yn hoffi Python, ond beth allwch chi ei wneud? Mae'n gyflymach ac yn haws ysgrifennu'r gweinydd hwn arno.

Mae'n cyflawni 3 swyddogaeth:

  1. Dechrau gweinydd gyda chyfluniad - dewis map, nifer y chwaraewyr i gychwyn y gêm, a set o ategion. Wna i ddim sgwennu am ategion nawr - mae honno'n stori wahanol gyda litrau o goffi yn y nos yn gymysg â dagrau a gwallt wedi'i rwygo.
  2. Stopio/ailgychwyn y gweinydd rhag ofn y bydd cysylltiadau aflwyddiannus, y gallwn eu trin â llaw yn unig.

Mae popeth yn syml yma, nid yw enghreifftiau cod hyd yn oed yn briodol. Sgript 100 llinell

Felly, pan ddaeth 10 o bobl at ei gilydd a derbyn y gêm, lansiwyd y gweinydd ac roedd pawb yn awyddus i chwarae, anfonwyd dolen i gysylltu â'r gêm mewn negeseuon preifat.

Rydym yn ysgrifennu paru ar gyfer Dota 2014

Trwy glicio ar y ddolen, mae'r chwaraewr yn cysylltu â'r gweinydd gêm, ac yna dyna ni. Ar ôl ~25 munud, mae'r “ystafell” rithwir gyda chwaraewyr yn cael ei chlirio.

Ymddiheuraf ymlaen llaw am lletchwithdod yr erthygl, nid wyf wedi ysgrifennu yma ers amser maith, ac mae gormod o god i dynnu sylw at adrannau pwysig. Nwdls, yn fyr.

Os gwelaf ddiddordeb yn y pwnc, bydd ail ran - bydd yn cynnwys fy mhoenyd gydag ategion ar gyfer srcds (gweinydd pwrpasol Ffynhonnell), ac, yn ôl pob tebyg, system raddio a mini-dotabuff, safle gydag ystadegau gêm.

Rhai dolenni:

  1. Ein gwefan (ystadegau, bwrdd arweinwyr, tudalen lanio fach a lawrlwythiad cleient)
  2. Gweinydd discord

Ffynhonnell: hab.com

Ychwanegu sylw