Commit 6272ebe3 authored by Andrei Mihu's avatar Andrei Mihu
Browse files

Matchmaker improvements, support for party matchmaking. (#521)

parent ec12afad
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -4,7 +4,12 @@ All notable changes to this project are documented below.
The format is based on [keep a changelog](http://keepachangelog.com) and this project uses [semantic versioning](http://semver.org).

## [Unreleased]
### Added
- Add party matching support to matchmaker.
- Add options to matchmaker to control how long tickets are allowed to wait for their preferred match.

### Changed
- Matchmaker improvements to quality of matching and player count range handling.
- Build with Go 1.15.6 release.

## [2.15.0] - 2020-11-28
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ require (
	github.com/gorilla/mux v1.7.4
	github.com/gorilla/websocket v1.4.2
	github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1
	github.com/heroiclabs/nakama-common v1.10.1-0.20201216142705-136e6c0d214f
	github.com/heroiclabs/nakama-common v1.10.1-0.20210112124918-da701a0f7020
	github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
	github.com/jackc/pgx v3.5.0+incompatible
	github.com/jmhodges/levigo v1.0.0 // indirect
+2 −0
Original line number Diff line number Diff line
@@ -207,6 +207,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/heroiclabs/nakama-common v1.10.1-0.20201216142705-136e6c0d214f h1:RTKN7L8sWQjsyBEv4fW65MsHbLxnO/NbgR/l+M3uaF4=
github.com/heroiclabs/nakama-common v1.10.1-0.20201216142705-136e6c0d214f/go.mod h1:li7bMQwOYA0NjT3DM4NKQBNruULPa2hrqdiSaaTwui4=
github.com/heroiclabs/nakama-common v1.10.1-0.20210112124918-da701a0f7020 h1:6jaVk2j7QSdSb4APKMQjDDa/s6FgxcZF+vAKszoCbkg=
github.com/heroiclabs/nakama-common v1.10.1-0.20210112124918-da701a0f7020/go.mod h1:li7bMQwOYA0NjT3DM4NKQBNruULPa2hrqdiSaaTwui4=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+2 −1
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@ func main() {

	// Start up server components.
	metrics := server.NewMetrics(logger, startupLogger, config)
	matchmaker := server.NewLocalMatchmaker(startupLogger, config.GetName())
	sessionRegistry := server.NewLocalSessionRegistry(metrics)
	tracker := server.StartLocalTracker(logger, config, sessionRegistry, metrics, jsonpbMarshaler)
	router := server.NewLocalMessageRouter(sessionRegistry, tracker, jsonpbMarshaler)
@@ -142,6 +141,7 @@ func main() {
	if err != nil {
		startupLogger.Fatal("Failed initializing runtime modules", zap.Error(err))
	}
	matchmaker := server.NewLocalMatchmaker(logger, startupLogger, config, router, runtime)

	leaderboardScheduler.Start(runtime)

@@ -207,6 +207,7 @@ func main() {
	apiServer.Stop()
	consoleServer.Stop()
	metrics.Stop(logger)
	matchmaker.Stop()
	leaderboardScheduler.Stop()
	tracker.Stop()
	sessionRegistry.Stop()
+32 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ type Config interface {
	GetTracker() *TrackerConfig
	GetConsole() *ConsoleConfig
	GetLeaderboard() *LeaderboardConfig
	GetMatchmaker() *MatchmakerConfig

	Clone() (Config, error)
}
@@ -238,6 +239,15 @@ func CheckConfig(logger *zap.Logger, config Config) map[string]string {
	if config.GetLeaderboard().CallbackQueueWorkers < 1 {
		logger.Fatal("Leaderboard callback queue workers must be >= 1", zap.Int("leaderboard.callback_queue_workers", config.GetLeaderboard().CallbackQueueWorkers))
	}
	if config.GetMatchmaker().MaxTickets < 1 {
		logger.Fatal("Matchmaker maximum ticket count must be >= 1", zap.Int("matchmaker.max_tickets", config.GetMatchmaker().MaxTickets))
	}
	if config.GetMatchmaker().IntervalSec < 1 {
		logger.Fatal("Matchmaker interval time seconds must be >= 1", zap.Int("matchmaker.interval_sec", config.GetMatchmaker().IntervalSec))
	}
	if config.GetMatchmaker().MaxIntervals < 1 {
		logger.Fatal("Matchmaker max intervals must be >= 1", zap.Int("matchmaker.max_intervals", config.GetMatchmaker().MaxIntervals))
	}

	// If the runtime path is not overridden, set it to `datadir/modules`.
	if config.GetRuntime().Path == "" {
@@ -358,6 +368,7 @@ type config struct {
	Tracker          *TrackerConfig     `yaml:"tracker" json:"tracker" usage:"Presence tracker properties."`
	Console          *ConsoleConfig     `yaml:"console" json:"console" usage:"Console settings."`
	Leaderboard      *LeaderboardConfig `yaml:"leaderboard" json:"leaderboard" usage:"Leaderboard settings."`
	Matchmaker       *MatchmakerConfig  `yaml:"matchmaker" json:"matchmaker" usage:"Matchmaker settings."`
}

// NewConfig constructs a Config struct which represents server settings, and populates it with default values.
@@ -381,6 +392,7 @@ func NewConfig(logger *zap.Logger) *config {
		Tracker:          NewTrackerConfig(),
		Console:          NewConsoleConfig(),
		Leaderboard:      NewLeaderboardConfig(),
		Matchmaker:       NewMatchmakerConfig(),
	}
}

@@ -396,6 +408,7 @@ func (c *config) Clone() (Config, error) {
	configTracker := *(c.Tracker)
	configConsole := *(c.Console)
	configLeaderboard := *(c.Leaderboard)
	configMatchmaker := *(c.Matchmaker)
	nc := &config{
		Name:             c.Name,
		Datadir:          c.Datadir,
@@ -411,6 +424,7 @@ func (c *config) Clone() (Config, error) {
		Tracker:          &configTracker,
		Console:          &configConsole,
		Leaderboard:      &configLeaderboard,
		Matchmaker:       &configMatchmaker,
	}
	nc.Socket.CertPEMBlock = make([]byte, len(c.Socket.CertPEMBlock))
	copy(nc.Socket.CertPEMBlock, c.Socket.CertPEMBlock)
@@ -493,6 +507,10 @@ func (c *config) GetLeaderboard() *LeaderboardConfig {
	return c.Leaderboard
}

func (c *config) GetMatchmaker() *MatchmakerConfig {
	return c.Matchmaker
}

// LoggerConfig is configuration relevant to logging levels and output.
type LoggerConfig struct {
	Level    string `yaml:"level" json:"level" usage:"Log level to set. Valid values are 'debug', 'info', 'warn', 'error'. Default 'info'."`
@@ -823,3 +841,17 @@ func NewLeaderboardConfig() *LeaderboardConfig {
		CallbackQueueWorkers: 8,
	}
}

type MatchmakerConfig struct {
	MaxTickets   int `yaml:"max_tickets" json:"max_tickets" usage:"Maximum number of concurrent matchmaking tickets allowed per session. Default 3."`
	IntervalSec  int `yaml:"interval_sec" json:"interval_sec" usage:"How quickly the matchmaker attempts to form matches, in seconds. Default 15."`
	MaxIntervals int `yaml:"max_intervals" json:"max_intervals" usage:"How many intervals the matchmaker attempts to find matches at the max player count, before allowing min count. Default 2."`
}

func NewMatchmakerConfig() *MatchmakerConfig {
	return &MatchmakerConfig{
		MaxTickets:   3,
		IntervalSec:  15,
		MaxIntervals: 2,
	}
}
Loading