اسان لکي رهيا آهيون ميچ ميڪنگ لاءِ Dota 2014

سڀني کي سلام.

هن بهار ۾ مون کي هڪ پروجيڪٽ نظر آيو جنهن ۾ ماڻهن سکيو ته ڪيئن هلائڻ لاءِ Dota 2 سرور ورجن 2014 ۽، مطابق، ان تي کيڏڻ. مان هن راند جو هڪ وڏو پرستار آهيان، ۽ مان پنهنجي ننڍپڻ ۾ پاڻ کي وسارڻ جو هي منفرد موقعو پاس نه ڪري سگهيو.

مون تمام گهڻي دل سان ڪبوتر ڪيو، ۽ ائين ئي ٿيو ته مون هڪ Discord bot لکيو جيڪو تقريبن سڀني ڪارڪردگي جو ذميوار آهي جيڪو راند جي پراڻي ورزن ۾ سپورٽ نه آهي، يعني ميچ ميڪنگ.
بوٽ سان سڀني جدت کان اڳ، لابي دستي طور تي ٺاهي وئي. اسان هڪ پيغام تي 10 ردعمل گڏ ڪيو ۽ دستي طور تي سرور گڏ ڪيو، يا مقامي لابي جي ميزباني ڪئي.

اسان لکي رهيا آهيون ميچ ميڪنگ لاءِ Dota 2014

هڪ پروگرامر جي حيثيت سان منهنجي طبيعت ايتري دستي ڪم کي برداشت نه ڪري سگهي، ۽ رات جو مون بوٽ جو آسان ترين نسخو ٺاهيو، جيڪو خودڪار طور تي سرور کي وڌايو جڏهن 10 ماڻهو هئا.

مون فوري طور تي nodejs ۾ لکڻ جو فيصلو ڪيو، ڇاڪاڻ ته مون کي پٿون پسند نه آهي، ۽ مان هن ماحول ۾ وڌيڪ آرام سان محسوس ڪريان ٿو.

هي منهنجو پهريون تجربو آهي Discord لاءِ بوٽ لکڻ جو، پر اهو نڪتو تمام سادو. سرڪاري npm ماڊل discord.js پيغامن سان ڪم ڪرڻ، رد عمل گڏ ڪرڻ وغيره لاءِ هڪ آسان انٽرفيس مهيا ڪري ٿو.

ڊسڪليمر: سڀئي ڪوڊ مثال "موجوده" آهن، مطلب ته اهي رات جي وقت ٻيهر لکڻ جي ڪيترن ئي ورهاڱي جي ذريعي گذري ويا آهن.

ميچ ميڪنگ جو بنياد هڪ "قطار" آهي جنهن ۾ رانديگر جيڪي کيڏڻ چاهيندا آهن انهن کي اندر رکيا ويندا آهن ۽ هٽايو ويندو آهي جڏهن اهي نه چاهيندا آهن يا راند ڳولڻ چاهيندا آهن.

هي اهو آهي جيڪو "پليئر" جو جوهر ڏسڻ جهڙو آهي. شروعات ۾ اهو Discord ۾ صرف هڪ صارف جي سڃاڻپ هو، پر اتي منصوبا آهن شروع ڪرڻ / سائيٽ مان رانديون ڳولڻ لاء، پر پهرين شيون پهرين.

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

۽ هتي قطار انٽرفيس آهي. هتي، "رانديگرن" جي بدران، "گروپ" جي صورت ۾ هڪ خلاصو استعمال ڪيو ويندو آهي. ھڪڙي رانديگر لاء، گروپ پاڻ تي مشتمل آھي، ۽ ھڪڙي گروپ ۾ رانديگرن لاء، ترتيب سان، گروپ جي سڀني رانديگرن مان.

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
}

مون فيصلو ڪيو ته ايونٽس استعمال ڪرڻ جي حوالي سان مٽائڻ لاءِ. اهو ڪيسن لاءِ موزون هو - ايونٽ تي ”10 ماڻهن لاءِ هڪ راند ملي وئي“، توهان رانديگرن کي ذاتي پيغامن ۾ ضروري پيغام موڪلي سگهو ٿا، ۽ بنيادي ڪاروباري منطق انجام ڏئي سگهو ٿا - تياري کي جانچڻ لاءِ هڪ ٽاسڪ شروع ڪريو، لابي تيار ڪريو لانچ لاء، وغيره.

IOC لاءِ آئون استعمال ڪريان ٿو InversifyJS. مون کي هن لائبريري سان ڪم ڪرڻ جو هڪ خوشگوار تجربو آهي. تيز ۽ آسان!

اسان وٽ اسان جي سرور تي ڪيتريون ئي قطارون آھن - اسان 1x1 شامل ڪيو آھي، عام / درجه بندي، ۽ ڪجھ ڪسٽم طريقا. تنهن ڪري، اتي هڪ سنگلٽن RoomService آهي جيڪو صارف ۽ راند جي ڳولا جي وچ ۾ آهي.

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

(ڪوڊ نوڊلز هڪ خيال ڏيڻ لاءِ ته اهو عمل تقريباً ڪهڙو نظر اچي ٿو)

هتي مان هر هڪ لاڳو ٿيل راند جي طريقن لاءِ قطار کي شروع ڪريان ٿو، ۽ قطار کي ترتيب ڏيڻ ۽ ڪجهه تڪرار کان بچڻ لاءِ ”گروپ“ ۾ تبديلين لاءِ پڻ ٻڌان ٿو.

تنهن ڪري، تمام سٺو، مون ڪوڊ جا ٽڪرا داخل ڪيا جن جو موضوع سان ڪو به تعلق ناهي، ۽ هاڻي اچو ته سڌو سنئون ميچ ميڪنگ ڏانهن وڃو.

اچو ته ڪيس تي غور ڪريون:

1) صارف کيڏڻ چاهي ٿو.

2) ڳولها شروع ڪرڻ لاءِ، هو استعمال ڪري ٿو Gateway=Discord، يعني پيغام تي ردِ عمل ڏيکاري ٿو:

اسان لکي رهيا آهيون ميچ ميڪنگ لاءِ Dota 2014

3) هي گيٽ وي روم سروس ڏانهن وڃي ٿو ۽ چوي ٿو "هڪ صارف کان اختلاف آهي قطار ۾ داخل ٿيڻ چاهي ٿو، موڊ: اڻ ڄاڻايل راند."

4) روم سروس گيٽ وي جي درخواست قبول ڪري ٿي ۽ استعمال ڪندڙ کي (وڌيڪ صحيح طور تي، صارف گروپ) کي گهربل قطار ۾ ڌڪي ٿو.

5) قطار چيڪ ڪري ٿو هر وقت اتي ڪافي رانديگر آهن راند ڪرڻ لاء. جيڪڏهن ممڪن هجي، هڪ واقعو پيش ڪريو:

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

6) RoomService واضح طور تي هن واقعي جي پريشاني جي انتظار ۾ هر قطار کي خوشيء سان ٻڌي رهيو آهي. اسان حاصل ڪريون ٿا رانديگرن جي هڪ فهرست ان پٽ جي طور تي، انهن مان هڪ ورچوئل ”ڪمرو“ ٺاهيو، ۽ يقيناً هڪ واقعو جاري ڪيو:

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) تنهنڪري اسان کي "اعليٰ" اختيار ملي ويو - ڪلاس بوٽ. عام طور تي، هو گيٽ ويز جي وچ ۾ ڪنيڪشن سان معاملو ڪري ٿو (مان سمجهي نٿو سگهان ته اهو روسي ۾ ڪيترو مزاحيه نظر اچي ٿو) ۽ ميچ ميڪنگ جي ڪاروباري منطق. بوٽو ايونٽ کي ٻڌي ٿو ۽ حڪم ڪري ٿو DiscordGateway سڀني صارفين کي تياري جي چيڪ موڪلڻ لاءِ.

اسان لکي رهيا آهيون ميچ ميڪنگ لاءِ Dota 2014

8) جيڪڏهن ڪو ماڻهو 3 منٽن اندر راند کي رد ڪري يا قبول نه ڪري، ته پوءِ اسان انهن کي قطار ۾ واپس نه ٿا ڏيون. اسان ٻين سڀني کي قطار ۾ واپس آڻينداسين ۽ انتظار ڪريو جيستائين 10 ماڻهو ٻيهر آهن. جيڪڏهن سڀني رانديگرن راند کي قبول ڪيو آهي، پوء دلچسپ حصو شروع ٿئي ٿو.

وقف سرور جي تشڪيل

اسان جون رانديون ونڊوز سرور 2012 سان VDS تي ميزباني ڪيون ويون آهن. ان مان اسان ڪيترائي نتيجا ڪڍي سگهون ٿا:

  1. اُن تي ڪو به ڊوڪر نه آهي، جو دل ۾ ٽهڪ ڏئي
  2. اسان ڪرائي تي بچائيندا آهيون

اهو ڪم لينڪس تي VPS کان VDS تي عمل هلائڻ آهي. مون فلاسڪ ۾ هڪ سادي سرور لکيو. ها، مون کي پٿون پسند نه آهي، پر توهان ڇا ڪري سگهو ٿا؟ هن سرور تي لکڻ تيز ۽ آسان آهي.

اهو 3 افعال انجام ڏئي ٿو:

  1. ھڪڙي ترتيب سان سرور شروع ڪرڻ - ھڪڙي نقشي کي چونڊڻ، راند کي شروع ڪرڻ لاء رانديگرن جو تعداد، ۽ پلگ ان جو ھڪڙو سيٽ. مان هاڻي پلگ ان جي باري ۾ نه لکندس - اها هڪ مختلف ڪهاڻي آهي جيڪا رات ۾ ڪافي جي ليٽر سان ڳوڙها ۽ ڦاٽل وارن سان ملي ٿي.
  2. ناڪامي ڪنيڪشن جي صورت ۾ سرور کي روڪڻ / ٻيهر شروع ڪرڻ، جيڪو اسان صرف دستي طور تي سنڀالي سگھون ٿا.

هتي سڀ ڪجهه سادو آهي، ڪوڊ جا مثال به مناسب نه آهن. 100 لائن اسڪرپٽ

تنهن ڪري، جڏهن 10 ماڻهو گڏ ٿيا ۽ راند کي قبول ڪيو، سرور شروع ڪيو ويو ۽ هرڪو کيڏڻ جو شوق هو، راند سان ڳنڍڻ لاء هڪ لنڪ نجي پيغامن ۾ موڪليو ويو.

اسان لکي رهيا آهيون ميچ ميڪنگ لاءِ Dota 2014

لنڪ تي ڪلڪ ڪندي، پليئر راند سرور سان ڳنڍيندو آهي، ۽ پوء اهو ئي آهي. ~ 25 منٽن کان پوء، مجازي "ڪمرو" رانديگرن سان صاف ڪيو ويو آهي.

مان آرٽيڪل جي بيچيني لاءِ اڳ ۾ معافي وٺان ٿو، مون هتي گهڻو وقت نه لکيو آهي، ۽ اهم حصن کي اجاگر ڪرڻ لاءِ تمام گهڻو ڪوڊ آهي. نوڊلز، مختصر ۾.

جيڪڏهن مون کي موضوع ۾ دلچسپي نظر اچي ٿي، اتي هڪ ٻيو حصو هوندو - اهو منهنجي عذاب تي مشتمل هوندو پلگ ان سان srcds (ذريعو سرشار سرور)، ۽ شايد، هڪ ريٽنگ سسٽم ۽ ميني ڊاٽابف، سائيٽ جي انگن اکرن سان.

ڪجھ لنڪس:

  1. اسان جي ويب سائيٽ (انگريزي، ليڊر بورڊ، ننڍو لينڊنگ صفحو ۽ ڪلائنٽ ڊائون لوڊ)
  2. ڊسڪور سرور

جو ذريعو: www.habr.com

تبصرو شامل ڪريو