entry

package
v0.0.8-tcp Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2024 License: MIT Imports: 7 Imported by: 0

README

Entry Design

This repository contains the implementation of a matchmaking system designed to support different matching strategies and game modes. The project is organized into various components that facilitate the creation and management of player, group, team, and room entries using different matchmaking algorithms.

Directory Structure Demo

.
├── entry
│ ├── glicko2
│ │ ├── group.go
│ │ ├── player.go
│ │ ├── room.go
│ │ └── team.go
│ ├── goat_game
│ │ ├── group.go
│ │ ├── player.go
│ │ ├── room.go
│ │ └── team.go
│ ├── group.go
│ ├── player.go
│ ├── room.go
│ └── team.go
└── repository
  ├── group.go
  ├── player.go
  ├── room.go
  └── team.go

Components

the relastionship between entries

Root Directory

The entry root directory provides interfaces and base implementations for the four types of entries:

  • Interfaces:
    • Player
    • Group
    • Team
    • Room
  • Base Implementations:
    • PlayerBase
    • GroupBase
    • TeamBase
    • RoomBase

These interfaces define the core functionalities for different entities, while the bases provide foundational implementations that can be combinated.

Match Strategy (glicko2)

The glicko2 directory represents a specific match strategy based on the Glicko2 rating system. It includes implementations for the different types of entries, each combining the respective base class:

  • PlayerBaseGlicko2 (combines PlayerBase)
  • GroupBaseGlicko2 (combines GroupBase)
  • TeamBaseGlicko2 (combines TeamBase)
  • RoomBaseGlicko2 (combines RoomBase)
Game Mode (goat_game)

The goat_game directory represents a specific game mode. A game mode can support multiple match strategies. Here, it combines the Glicko2 strategy implementations to form its own entries:

  • goat_game.Player (combines PlayerBaseGlicko2, PlayerBaseGather)
  • goat_game.Group (combines GroupBaseGlicko2, GroupBaseGather)
  • goat_game.Team (combines TeamBaseGlicko2, TeamBaseGather)
  • goat_game.Room (combines RoomBaseGlicko2, RoomBaseGather)
Repository

In the repository directory, there are functions to create specific entry implementations based on provided parameters (game mode and match strategy). This allows for dynamic creation of entries like Player, Group, Team, and Room.

type PlayerMgr struct {
	*collection.Manager[string, entry.Player]
}

type GroupMgr struct {
	*collection.Manager[int64, entry.Group]
}

type TeamMgr struct {
	*collection.Manager[int64, entry.Team]
}

type RoomMgr struct {
	*collection.Manager[int64, entry.Room]
}

Factory Method

To use this matchmaking system, you can instantiate the desired base and strategy combinations using the factory method. Below is an example of how to create a player entry:

// repository/player.go
func (m *PlayerMgr) CreatePlayer(pInfo *pto.PlayerInfo) (p entry.Player, err error) {
	base := entry.NewPlayerBase(pInfo)

	switch base.GameMode {
	case constant.GameModeGoatGame:
		p, err = goat_game.CreatePlayer(base, pInfo)
	case constant.GameModeTest:
		p = base
	default:
		return nil, fmt.Errorf("unsupported game mode: %d", base.GameMode)
	}

	if err != nil {
		return nil, err
	}
	m.Add(p.UID(), p)
	return p, nil
}

// entry/goat_game/player.go
func CreatePlayer(base *entry.PlayerBase, pInfo *pto.PlayerInfo) entry.Player {
    p := &Player{}
    // ... other common fields

    p.withMatchStrategy(base, pInfo.Glicko2Info)
    return p
}

func (p *Player) withMatchStrategy(base *entry.PlayerBase, info *pto.Glicko2Info) {
    p.PlayerBaseGlicko2 = glicko2.CreatePlayerBase(base, info)
    // ... other match strategy initialization
}

Documentation

Index

Constants

View Source
const (
	InviteExpireSec = 60 * 5
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Group

type Group interface {
	// ID returns the unique group id.
	ID() int64

	// Base returns the base information of the group.
	// Here we define a concrete struct `GroupBase`
	// to hold the common fields to avoid lots getter and setter method.
	Base() *GroupBase

	// IsFull checks if the group is full.
	IsFull() bool

	// SetCaptain sets the captain of the group.
	SetCaptain(Player)

	// GetCaptain returns the captain in the group.
	GetCaptain() Player

	// CanPlayTogether checks if the player can play with the group's players.
	CanPlayTogether(*pto.PlayerInfo) error

	// GetPlayerInfos returns the player infos of the group.
	// This method usually used for sync group info to client.
	GetGroupInfo() *pto.GroupInfo

	// CanStartMatch checks if the group can start to match.
	// Maybe some game mode need to check if the group is full or not.
	// Maybe some game mode need all players to be ready.
	// If you have some special logics, please override this method.
	CanStartMatch() bool
}

Group represents a group of players.

type GroupBase

type GroupBase struct {
	// ReentrantLock is a reentrant lock support multiple locks in the same goroutine.
	// Use it to help avoid deadlock.
	*concurrent.ReentrantLock

	// GroupID is the unique id of the group.
	GroupID int64

	// IsAI indicates if the group is an AI group.
	IsAI bool

	// GameMode is the game mode of the group.
	GameMode constant.GameMode

	// ModeVersion is the version of the game mode of the group.
	// Only the same version of the players can be played together.
	ModeVersion int64

	// MatchStrategy is the current match strategy of the group.
	MatchStrategy constant.MatchStrategy

	// SupportMatchStrategies is the supported match strategies of the group.
	SupportMatchStrategies []constant.MatchStrategy

	// MatchID is a unique id to identify each match action.
	MatchID string

	Configs GroupConfig

	// ReadyPlayer holds the unready players in the group.
	// In the project, we assume that the default does not
	// require all players to prepare to start matching,
	// so the map will be empty by default,
	// and you will need to re-initialize this field in the game mode that requires preparation
	UnReadyPlayer map[string]struct{}

	// Settings holds the settings of the group.
	Settings GroupSettings
	// contains filtered or unexported fields
}

GroupBase holds the common fields of a Group for all kinds of game mode and match strategy.

func NewGroupBase

func NewGroupBase(
	groupID int64, playerLimit int, playerBase *PlayerBase,
) *GroupBase

NewGroupBase creates a new GroupBase.

func (*GroupBase) AddInviteRecord

func (g *GroupBase) AddInviteRecord(inviteeUID string, nowUnix int64)

func (*GroupBase) AddPlayer

func (g *GroupBase) AddPlayer(p Player) error

func (*GroupBase) AllowNearbyJoin

func (g *GroupBase) AllowNearbyJoin() bool

func (*GroupBase) AllowRecentJoin

func (g *GroupBase) AllowRecentJoin() bool

func (*GroupBase) Base

func (g *GroupBase) Base() *GroupBase

func (*GroupBase) CanPlayTogether

func (g *GroupBase) CanPlayTogether(info *pto.PlayerInfo) error

func (*GroupBase) CanStartMatch

func (g *GroupBase) CanStartMatch() bool

func (*GroupBase) CheckState

func (g *GroupBase) CheckState(valids ...GroupState) error

func (*GroupBase) ClearPlayers

func (g *GroupBase) ClearPlayers()

func (*GroupBase) DelInviteRecord

func (g *GroupBase) DelInviteRecord(inviteeUID string)

func (*GroupBase) GetCaptain

func (g *GroupBase) GetCaptain() Player

func (*GroupBase) GetGroupInfo

func (g *GroupBase) GetGroupInfo() *pto.GroupInfo

func (*GroupBase) GetInviteExpireTimeStamp

func (g *GroupBase) GetInviteExpireTimeStamp(uid string) int64

func (*GroupBase) GetInviteRecords

func (g *GroupBase) GetInviteRecords() map[string]int64

func (*GroupBase) GetPlayers

func (g *GroupBase) GetPlayers() []Player

func (*GroupBase) GetState

func (g *GroupBase) GetState() GroupState

func (*GroupBase) GetStateWithLock

func (g *GroupBase) GetStateWithLock() GroupState

func (*GroupBase) ID

func (g *GroupBase) ID() int64

func (*GroupBase) IsFull

func (g *GroupBase) IsFull() bool

func (*GroupBase) IsInviteExpired

func (g *GroupBase) IsInviteExpired(uid string, nowUnix int64) bool

func (*GroupBase) IsMatchStrategySupported

func (g *GroupBase) IsMatchStrategySupported() bool

IsMatchStrategySupported checks if the group supports the current match strategy.

func (*GroupBase) PlayerExists

func (g *GroupBase) PlayerExists(uid string) bool

func (*GroupBase) PlayerLimit

func (g *GroupBase) PlayerLimit() int

func (*GroupBase) RemovePlayer

func (g *GroupBase) RemovePlayer(p Player) (empty bool)

func (*GroupBase) SetAllowNearbyJoin

func (g *GroupBase) SetAllowNearbyJoin(allow bool)

func (*GroupBase) SetAllowRecentJoin

func (g *GroupBase) SetAllowRecentJoin(allow bool)

func (*GroupBase) SetCaptain

func (g *GroupBase) SetCaptain(p Player)

func (*GroupBase) SetState

func (g *GroupBase) SetState(s GroupState)

func (*GroupBase) SetStateWithLock

func (g *GroupBase) SetStateWithLock(s GroupState)

func (*GroupBase) UIDs

func (g *GroupBase) UIDs() []string

type GroupConfig

type GroupConfig struct {
	PlayerLimit     int
	InviteExpireSec int64
}

type GroupRole

type GroupRole int8
const (
	GroupRoleMember  GroupRole = 0
	GroupRoleCaptain GroupRole = 1
)

type GroupSettings

type GroupSettings struct {
	// contains filtered or unexported fields
}

GroupSettings defines the settings of a group.

type GroupState

type GroupState int8
const (
	GroupStateInvite    GroupState = 0
	GroupStateMatch     GroupState = 1
	GroupStateGame      GroupState = 2
	GroupStateDissolved GroupState = 3
)

type Player

type Player interface {
	Base() *PlayerBase
	UID() string
	GetPlayerInfo() *pto.PlayerInfo
	SetAttr(attr *pto.UploadPlayerAttr) error
}

Player represents a player in a Group.

type PlayerBase

type PlayerBase struct {
	// ReentrantLock is a reentrant lock support multiple locks in the same goroutine
	// Use it to help avoid deadlock.
	*concurrent.ReentrantLock

	IsAI    bool
	GroupID int64

	// TODO: other common attributes
	pto.PlayerInfo
	pto.Attribute
	// contains filtered or unexported fields
}

PlayerBase holds the common fields of a Player for all kinds of game mode and match strategy.

func NewPlayerBase

func NewPlayerBase(info *pto.PlayerInfo) *PlayerBase

func (*PlayerBase) Base

func (p *PlayerBase) Base() *PlayerBase

func (*PlayerBase) CheckOnlineState

func (p *PlayerBase) CheckOnlineState(valids ...PlayerOnlineState) error

CheckOnlineState checks if the player is in a valid online state.

func (*PlayerBase) GetOnlineState

func (p *PlayerBase) GetOnlineState() PlayerOnlineState

func (*PlayerBase) GetOnlineStateWithLock

func (p *PlayerBase) GetOnlineStateWithLock() PlayerOnlineState

func (*PlayerBase) GetPlayerInfo

func (p *PlayerBase) GetPlayerInfo() *pto.PlayerInfo

func (*PlayerBase) GetVoiceState

func (p *PlayerBase) GetVoiceState() PlayerVoiceState

func (*PlayerBase) SetAttr

func (p *PlayerBase) SetAttr(attr *pto.UploadPlayerAttr) error

func (*PlayerBase) SetOnlineState

func (p *PlayerBase) SetOnlineState(s PlayerOnlineState)

func (*PlayerBase) SetOnlineStateWithLock

func (p *PlayerBase) SetOnlineStateWithLock(s PlayerOnlineState)

func (*PlayerBase) SetVoiceState

func (p *PlayerBase) SetVoiceState(s PlayerVoiceState)

func (*PlayerBase) UID

func (p *PlayerBase) UID() string

type PlayerOnlineState

type PlayerOnlineState int8

PlayerOnlineState is the state of a player. TODO: try to use state machine to manage player state.

const (
	PlayerOnlineStateOffline  PlayerOnlineState = 0
	PlayerOnlineStateOnline   PlayerOnlineState = 1
	PlayerOnlineStateInGroup  PlayerOnlineState = 2
	PlayerOnlineStateInMatch  PlayerOnlineState = 3
	PlayerOnlineStateInGame   PlayerOnlineState = 4
	PlayerOnlineStateInSettle PlayerOnlineState = 5
)

type PlayerVoiceState

type PlayerVoiceState int8

PlayerVoiceState is the voice state of a player.

const (
	PlayerVoiceStateMute   PlayerVoiceState = 0
	PlayerVoiceStateUnmute PlayerVoiceState = 1
)

type Room

type Room interface {
	Base() *RoomBase
	ID() int64
	NeedAI() bool
	GetMatchInfo() *pto.MatchInfo
}

type RoomBase

type RoomBase struct {
	sync.RWMutex

	TeamLimit int

	GameMode       constant.GameMode
	MatchStrategy  constant.MatchStrategy
	ModeVersion    int64
	FinishMatchSec int64

	GameServerInfo pto.GameServerInfo
	// contains filtered or unexported fields
}

func NewRoomBase

func NewRoomBase(id int64, teamLimit int, t Team) *RoomBase

func (*RoomBase) AddEscapePlayer

func (r *RoomBase) AddEscapePlayer(uid string)

func (*RoomBase) AddTeam

func (r *RoomBase) AddTeam(t Team)

func (*RoomBase) Base

func (r *RoomBase) Base() *RoomBase

func (*RoomBase) GetEscapePlayers

func (r *RoomBase) GetEscapePlayers() []string

func (*RoomBase) GetMatchInfo

func (r *RoomBase) GetMatchInfo() *pto.MatchInfo

func (*RoomBase) GetTeams

func (r *RoomBase) GetTeams() []Team

func (*RoomBase) ID

func (r *RoomBase) ID() int64

func (*RoomBase) NeedAI

func (r *RoomBase) NeedAI() bool

func (*RoomBase) RemoveTeam

func (r *RoomBase) RemoveTeam(id int64)

func (*RoomBase) ShuffleTeamOrder

func (r *RoomBase) ShuffleTeamOrder()

func (*RoomBase) UIDs

func (r *RoomBase) UIDs() []string

type Team

type Team interface {
	Base() *TeamBase
	ID() int64
}

type TeamBase

type TeamBase struct {
	sync.RWMutex

	TeamID int // TeamID is the unique team id in one room, start from 1.
	IsAI   bool

	GameMode      constant.GameMode
	MatchStrategy constant.MatchStrategy
	ModeVersion   int64
	// contains filtered or unexported fields
}

func NewTeamBase

func NewTeamBase(id int64, g Group) *TeamBase

func (*TeamBase) AddGroup

func (t *TeamBase) AddGroup(g Group)

func (*TeamBase) Base

func (t *TeamBase) Base() *TeamBase

func (*TeamBase) GetGroups

func (t *TeamBase) GetGroups() []Group

func (*TeamBase) ID

func (t *TeamBase) ID() int64

func (*TeamBase) RemoveGroup

func (t *TeamBase) RemoveGroup(id int64)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL