අපි Dota 2014 සඳහා Matchmaking ලියන්නෙමු

හැමෝටම ආයුබෝවන්.

මෙම වසන්තයේ දී මට ඩෝටා 2 සේවාදායක අනුවාදය 2014 ධාවනය කරන්නේ කෙසේදැයි ඉගෙන ගත් ව්‍යාපෘතියක් මට හමු විය, ඒ අනුව එය මත සෙල්ලම් කරන්න. මම මෙම ක්‍රීඩාවේ විශාල රසිකයෙක් වන අතර, මගේ ළමා කාලය තුළ ගිලී යාමට මට මෙම සුවිශේෂී අවස්ථාව මග හැරිය නොහැකි විය.

මම ඉතා ගැඹුරින් පරෙවියා කළ අතර, ක්‍රීඩාවේ පැරණි අනුවාදයේ, එනම් ගැලපීම සඳහා සහය නොදක්වන සියලුම ක්‍රියාකාරීත්වයන් සඳහා වගකිව යුතු Discord bot එකක් ලිවීය.
බොට් සමඟ ඇති සියලුම නවෝත්පාදනයන්ට පෙර, ලොබිය අතින් නිර්මාණය කරන ලදී. අපි පණිවිඩයකට ප්‍රතික්‍රියා 10ක් එකතු කර සේවාදායකයක් අතින් එකලස් කළෙමු, නැතහොත් දේශීය ලොබියකට සත්කාරකත්වය ලබා දුන්නෙමු.

අපි Dota 2014 සඳහා Matchmaking ලියන්නෙමු

ක්‍රමලේඛකයෙකු ලෙස මගේ ස්වභාවයට එතරම් අතින් වැඩකට ඔරොත්තු දිය නොහැකි වූ අතර, පුද්ගලයන් 10 දෙනෙකු සිටින විට ස්වයංක්‍රීයව සේවාදායකය ඉහළ දැමූ බොට් හි සරලම අනුවාදය එක රැයකින් මම සිතුවම් කළෙමි.

මම වහාම nodejs හි ලිවීමට තීරණය කළෙමි, මන්ද මම ඇත්තටම Python වලට කැමති නැති නිසා සහ මෙම පරිසරය තුළ මට වඩාත් සුවපහසුවක් දැනෙනවා.

මෙය Discord සඳහා bot ලිවීමේ මගේ පළමු අත්දැකීමයි, නමුත් එය ඉතා සරල විය. නිල 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, සාමාන්‍ය/ශ්‍රේණිගත, ​​සහ අභිරුචි මාදිලි කිහිපයක් එකතු කර ඇත. එබැවින්, පරිශීලකයා සහ ක්‍රීඩා සෙවුම අතර තනි කාමර සේවාවක් ඇත.

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 සඳහා Matchmaking ලියන්නෙමු

3) මෙම ද්වාරය RoomService වෙත ගොස් "විසංවාදයෙන් සිටින පරිශීලකයෙකුට පෝලිම, මාදිලිය: ශ්‍රේණිගත නොකළ ක්‍රීඩාවට ඇතුළු වීමට අවශ්‍යයි" යනුවෙන් පවසයි.

4) RoomService ද්වාරයෙහි ඉල්ලීම පිළිගෙන පරිශීලකයා (වඩාත් නිවැරදිව, පරිශීලක කණ්ඩායම) අපේක්ෂිත පෝලිමට තල්ලු කරයි.

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 සඳහා Matchmaking ලියන්නෙමු

8) යමෙක් මිනිත්තු 3ක් ඇතුළත ක්‍රීඩාව ප්‍රතික්ෂේප කළහොත් හෝ නොපිළිගන්නේ නම්, අපි ඔවුන්ව පෝලිමට ආපසු නොයන්නෙමු. අපි අනෙක් සියල්ලන්ම පෝලිමට ගොස් නැවත පුද්ගලයින් 10 දෙනෙකු සිටින තෙක් බලා සිටිමු. සියලුම ක්‍රීඩකයින් ක්‍රීඩාව පිළිගෙන තිබේ නම්, සිත්ගන්නා කොටස ආරම්භ වේ.

කැපවූ සේවාදායක වින්‍යාසය

අපගේ ක්‍රීඩා වින්ඩෝස් සර්වර් 2012 සමඟ VDS මත සත්කාරකත්වය සපයයි. මෙයින් අපට නිගමන කිහිපයක් ගත හැකිය:

  1. ඒකේ ඩොකර් කෙනෙක් නැහැ, ඒක මගේ හිතට වැදුණා
  2. අපි කුලියට ඉතිරි කරනවා

කාර්යය වන්නේ ලිනක්ස් හි VPS එකකින් VDS මත ක්‍රියාවලියක් ක්‍රියාත්මක කිරීමයි. මම Flask හි සරල සේවාදායකයක් ලිව්වෙමි. ඔව්, මම Python වලට කැමති නැහැ, නමුත් ඔබට කුමක් කළ හැකිද? මෙම සේවාදායකය එහි ලිවීම වේගවත් සහ පහසු වේ.

එය කාර්යයන් 3 ක් ඉටු කරයි:

  1. වින්‍යාසය සමඟ සේවාදායකයක් ආරම්භ කිරීම - සිතියමක් තේරීම, ක්‍රීඩාව ආරම්භ කිරීමට ක්‍රීඩකයින් ගණන සහ ප්ලගීන කට්ටලයක්. මම දැන් ප්ලගීන ගැන ලියන්නේ නැහැ - එය රාත්‍රියේදී කඳුළු සහ ඉරා දැමූ හිසකෙස් සමඟ මිශ්‍ර වූ කෝපි ලීටර් සමඟ වෙනස් කතාවකි.
  2. අසාර්ථක සම්බන්ධතා වලදී සේවාදායකය නැවැත්වීම/නැවත ආරම්භ කිරීම, අපට හැසිරවිය හැක්කේ අතින් පමණි.

මෙහි සෑම දෙයක්ම සරලයි, කේත උදාහරණ පවා සුදුසු නොවේ. පේළි 100 පිටපත

ඔන්න ඉතින් 10 දෙනෙක් එකතු වෙලා ගේම් එක බාර ගත්තම server එක Launch වෙලා හැමෝම සෙල්ලම් කරන්න ආසාවෙන් ඉන්නකොට ගේම් එකට connect වෙන්න ලින්ක් එකක් private messages වලින් එව්වා.

අපි Dota 2014 සඳහා Matchmaking ලියන්නෙමු

සබැඳිය ක්ලික් කිරීමෙන්, ක්‍රීඩකයා ක්‍රීඩා සේවාදායකයට සම්බන්ධ කරයි, පසුව එය එයයි. මිනිත්තු ~ 25 කට පසු, ක්‍රීඩකයන් සමඟ අතථ්‍ය “කාමරය” ඉවත් කරනු ලැබේ.

ලිපියේ ඇති අපහසුතාවයට මම කල්තියා සමාව අයදිමි, මම දිගු කලක් මෙහි ලියා නැත, වැදගත් කොටස් ඉස්මතු කිරීමට ඕනෑවට වඩා කේතයක් ඇත. නූඩ්ල්ස්, කෙටියෙන්.

මම මාතෘකාව ගැන උනන්දුවක් දක්වන්නේ නම්, දෙවන කොටස වනු ඇත - එහි srcds (මූලාශ්‍රය කැප වූ සේවාදායකය) සඳහා ප්ලගීන සමඟ මගේ වධ හිංසා අඩංගු වනු ඇත, සහ, බොහෝ විට, ශ්‍රේණිගත කිරීමේ පද්ධතියක් සහ කුඩා-ඩොටබෆ්, ක්‍රීඩා සංඛ්‍යාලේඛන සහිත වෙබ් අඩවියකි.

සමහර සබැඳි:

  1. අපගේ වෙබ් අඩවිය (සංඛ්‍යාලේඛන, ප්‍රමුඛ පුවරුව, කුඩා ගොඩබෑමේ පිටුව සහ සේවාදායක බාගත කිරීම)
  2. Discord සේවාදායකය

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න