Skip to content

[Cookbook] Simple Matchmaker Demo

Jamie edited this page Aug 21, 2018 · 2 revisions

Introduction

The following is a very trivial example of how to use the matchmaking in DarkRift. It demonstrates a simple command line interface where integers can be queued and dequeued.

Running the Code

To run the code you will need the following in the <plugins> element of your server to configure the matchmaker.

<plugin type="RoomSystemDemoMatchmaker" load="true">
  <settings discardThreshold="0.2"
            groupDiscardThreshold="0.2"
            entitiesPerGroup="4"
            tickPeriod="1000" />
</plugin>

Once your server is running with the plugin loaded you can use the queue and cancel commands to play with the matchmaker. For the purposes of demonstration the matchmaker is setup to consider every pairing perfect in its ranking function (i.e. a ranking metric of 1 for all).

Queue

The queue command adds a group of integers into the matchmaker, for example:

queue 1 2 3 4

adds a single group composed of 4 integers (1, 2, 3, 4).

Typing that should show that a group was added and then immediately removed (because we're trying to make groups of 4!)

[Info]    RoomSystemDemoPlugin  Group 0 are now Queued.
[Info]    RoomSystemDemoPlugin  Group 0 are now Success.

As a further example, adding a group of 3 integers would only show the Success line once you also add a group of 1 integer to combine with.

Cancel

The cancel command allows you to dequeue a queued group by the group ID, for example:

queue 1 2 3
[Info]    RoomSystemDemoPlugin  -> 4
cancel 4

would dequeue the group of three integers you just added.

Code

There are two files to this plugin, one is the matchmaker and the other accepts the commands and queues/cancels the groups.

Matchmaker

using DarkRift.Server;
using DarkRift.Server.Plugins.Matchmaking;
using System;
using System.Collections.Generic;
using System.Text;

namespace RoomSystemDemo
{
    public class RoomSystemDemoMatchmaker : RankingMatchmaker<int>
    {
        public override bool ThreadSafe => true;

        public override Version Version => new Version(1, 0, 0);

        public RoomSystemDemoMatchmaker(PluginLoadData pluginLoadData) : base(pluginLoadData)
        {
        }

        public override float GetSuitabilityMetric(int entity1, int entity2, MatchRankingContext<int> context)
        {
            return 1;
        }
    }
}

Command Handler

using DarkRift;
using DarkRift.Server;
using DarkRift.Server.Plugins.Matchmaking;
using System;
using System.Collections.Generic;
using System.Linq;

namespace RoomSystemDemo
{
    public class RoomSystemDemoPlugin : Plugin
    {
        public override bool ThreadSafe => false;

        public override Version Version => new Version(1, 0, 0);

        public override Command[] Commands => new Command[] {
            new Command("queue", "Queues a new entity.", "queue <number...>", QueueHandler),
            new Command("cancel", "Dequeues a new entity.", "cancel <number...>", CancelHandler)
        };

        IMatchmaker<int> matchmaker;

        List<IMatchmakerQueueTask<int>> tasks = new List<IMatchmakerQueueTask<int>>();

        public RoomSystemDemoPlugin(PluginLoadData pluginLoadData) : base(pluginLoadData)
        {
        }

        protected override void Loaded(LoadedEventArgs args)
        {
            matchmaker = PluginManager.GetPluginByType<RankingMatchmaker<int>>();

            matchmaker.GroupFormed += GroupFormed;
        }

        private void GroupFormed(object sender, GroupFormedEventArgs<int> e)
        {
            WriteEvent("Formed new group of " + string.Join(", ", e.Group), LogType.Info);
        }

        void QueueHandler(object sender, CommandEventArgs e)
        {
            WriteEvent("Queueing entities...", LogType.Info);

            int groupID = tasks.Count;

            IMatchmakerQueueTask<int> task = matchmaker.EnqueueGroup(
                e.Arguments.Select(a => int.Parse(a)),
                (_, e2) => WriteEvent("Group " + groupID + " are now " + e2.MatchmakingState + ".", LogType.Info)
            );

            WriteEvent("-> " + groupID, LogType.Info);
            tasks.Add(task);
        }

        void CancelHandler(object sender, CommandEventArgs e)
        {
            WriteEvent("Dequeueing entities...", LogType.Info);

            foreach (string argument in e.Arguments)
                tasks[int.Parse(argument)].Cancel();
        }
    }
}