func Add(mid, uqid, tag string, props map[string]int, value map[string]interface{}, ttl int64, limit int) error
Add Adds a searchable matching candidate data.
[NOTE] In order to have long lasting (TTL longer than 60 seconds) searable items, the application must "add" searchable items repeatedly with TTL=60.
Error Cases
╒═════════════════════╤══════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞═════════════════════╪══════════════════════════════════════════════════════════╡ │ Invalid profile IDs │ Either missing or invalid matchmaking profile IDs given. │ ├─────────────────────┼──────────────────────────────────────────────────────────┤ │ Unique ID missing │ Unique ID must not be an empty string. │ ├─────────────────────┼──────────────────────────────────────────────────────────┤ │ Properties missing │ Properties must not be a nil. │ ├─────────────────────┼──────────────────────────────────────────────────────────┤ │ Invalid limit value │ Limit must be greater than 1. │ ╘═════════════════════╧══════════════════════════════════════════════════════════╛
Parameters
mid - Matching profile ID to add the searchable data to. unqiueID - Unique ID of the searchable ID. tag - Tag is used to isolate and group add and search of matchmaking. If an empty string is given, it will be ignored. props - Searchable condition properties. value - Searchable data to be returned along with the search resilts. ttl - TTL of the searchable item to be added in seconds. Maximum 60 seconds. limit - Number of search node to propagate the searchable item data at a time.
func CancelTicket(ticketType uint8, userData *user.User) error
CancelTicket stops ticket-based matchmaking started by StartTicket.
Canceling a ticket will disband the matchmaking and remove already-matched users from it.
[IMPORTANT] Only the owner user of the ticket are allowed to cancel the ticket. [IMPORTANT] CancelTicket will fail after the completion of the ticket.
Error Cases
+-----------------------+-----------------------------------------------------------+ | Error | Reason | +-----------------------+-----------------------------------------------------------+ | Ticket not found | The ticket to cancel is not available. | | Ticket failed to stop | The ticket is not active (already completed or canceled). | +-----------------------+-----------------------------------------------------------+
Parameters
ticketType - Ticket type of the ticket to cancel. userData - The owner user of the ticket to cancel.
func ClearDefinition(matchingID string)
ClearDefinition clears already defined match making definition
matchingID - Matching profile ID to clear the definition.
func ControlTicketParams(params *TicketParams) (int64, int64)
ControlTicketParams [INTERNALLY USED ONLY]
func CreateKeyByProperties(matchingID string, tag string, properties map[string]int) string
CreateKeyByProperties generates a key from a tag and search or add properties.
This is meant to be used along with DebugDataDump for test and debugging.
The key generated is the actual search condition data used internally to find matches.
func DebugDataDump() (map[string][]*searchItem, error)
DebugDataDump returns the entire matchmaking data held in memory of the server.
[IMPORTANT] This is a debug function and must NOT be used in production code at all. [NOTE] In order to evaluate key, use CreateKeyByProperties to reproduce the same key with property values that match.
Example of evaluating the dump data keys:
dump := matching.DebugDataDump() for key, searchItems := range dump { // expected key expectedKey := matching.CreateKeyByProperties(matchingID, tag, expectedProperties) // check to see if the key matches the expected key if key == expectedKey { // good } else { // bad... } }
func DebugDataDumpWriter(writer io.Writer) error
DebugDataDumpWriter writes the entire matchmaking data held in memory of the server to io.Writer stream.
[IMPORTANT] This is a debug function and must NOT be used in production code at all. [NOTE] In order to evaluate key, use CreateKeyByProperties to reproduce the same key with property values that match.
func Define(matchingID string, props map[string]int)
Define defines a match making search schema:
[IMPORTANT] This must be defined on the server that is specified by "targetNodeType" configuration because all match making data is stored on those servers. [IMPORATNT] Matching ID must not contain "\t".
Parameters
matchingID - Unique matching profile ID. props - Matching profile condition properties.
In order to perform matchmaking, you must define the rules for matchmakings.
The matchmaking rules are called profiles.
These rules will dictate how matchmaking should be conditioned.
You may combine multiple matchmaking rules and create more complex matchmaking conditions as well.
You must define matchmaking rule profiles before invoking diarkis.Start.
The example below shows a matchmaking rule that uese level and creates bukets of matchmaking pools by the range of 10.
With this profile, each level bucket will pool users with level 0 to 10, 11 to 20, 21 to 30 and so forth...
The string name given as LevelMatch is the unique ID to represents the profile.
levelMatchProfile := make(map[string]int) levelMatchProfile["level"] = 10 matching.Define("LevelMatch", levelMatchProfile)
You may define as many matching definition as you require as long as each matchingID is unique.
func DefineByJSON(jsonBytes []byte)
DefineByJSON defines multiple match making definitions from JSON string.
$(...) represents a variable.
{ "$(matching ID)": { "$(property name)": $(property value as int) "$(property name)": $(property value as int) "$(property name)": $(property value as int) } } jsonBytes - Matching profile byte array data to be used to define the profile.
func ExposeCommands()
func GetTicketMemberIDs(ticketType uint8, userData *user.User) ([]string, bool)
GetTicketMemberIDs returns the list of matched member user IDs.
Cases for the second return value to be false
When the internal room is missing.
When non-owner user executes the function.
[IMPORTANT] This function is aviable ONLY for the owner of the ticket.
func GetTicketMemberSIDs(ticketType uint8, userData *user.User) ([]string, bool)
GetTicketMemberSIDs returns the list of matched member user SIDs.
Cases for the second return value to be false
Highlights
[IMPORTANT] This function is aviable ONLY for the owner of the ticket. [IMPORTANT] If non-user uses this function it returns an empty array.
func GetTicketProperties(ticketType uint8, userData *user.User, keys []string) (map[string]interface{}, bool)
GetTicketProperties returns key and value pairs as a map.
Cases for the second return value to be false
Uses mutex lock internally.
[IMPORTANT] This function is avilable ONLY for the owner of the ticket. [IMPORTANT] Properties are only premitive values and does not support reference type data such as array and map. [IMPORTANT] If a value of a given key does not exist, the returned map will have a nil as a value of the key. [IMPORTANT] The returned property value is an interface{}, in order to type assert safely, please use Diarkis' util package functions.
Example
values, ok := GetTicketProperties(ticketType, userData, []string{ "someKey" }) if !ok { // handle error here } for key, v := range values { // If the value data type is an uint8, of course ;) value, ok := util.ToUint8(v) }
func GetTicketProperty(ticketType uint8, userData *user.User, key string) (interface{}, bool)
GetTicketProperty returns the value of the given key and if the key does not exist, the second return value will be a false.
Cases for the second return value to be false
Uses mutex lock internally.
[IMPORTANT] This function is avilable ONLY for the owner of the ticket. [IMPORTANT] Properties are only premitive values and does not support reference type data such as array and map. [IMPORTANT] The returned property value is an interface{}, in order to type assert safely, please use Diarkis' util package functions.
Example
v, ok := GetTicketProperty(ticketType, userData, "someKey") if !ok { // handle error here } // If the value data type is an uint8, of course ;) v, ok := util.ToUint8(v)
func HasTicket(ticketType uint8, userData *user.User) bool
HasTicket returns true if the user given has a matchmaking ticket of the given type in progress.
func IsTicketOwner(ticketType uint8, userData *user.User) bool
IsTicketOwner returns true if the given user is the owner of its ticket
func IsUserInTicketMatchmaking(ticketType uint8, userData *user.User) bool
IsUserInTicketMatchmaking returns true if the user is matched with at least one another user in ticket matchmaking of the given ticket type.
The function returns true when:
1. The ticket the user created moves to "waiting" phase.
2. The ticket finds and joins another ticket.
[NOTE] If the user is in a ticket matchmaking, the user is able to send and receive TicketBroadcast messages and perform other ticket-related operations.
func JoinRoomByID(ticketType uint8, id string, userData *user.User, cb func(error))
func KickoutFromTicket(ticketType uint8, owner *user.User, targetUserID string, cb func(err error))
KickoutFromTicket forcefully removes a matched member from the matchmaking ticket.
[IMPORATANT] Only the owner of the ticket may execute this operation.
Error Cases
╒═══════════════════════════╤═════════════════════════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞═══════════════════════════╪═════════════════════════════════════════════════════════════════════════════╡ │ MatchMaker room not found │ The owner user is not in a matchmaking ticket room. │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤ │ Must be the owner │ Only the owner of the ticket may kickout matched members. │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤ │ Target user not found │ The target user to kick out is not a matched member. │ ╘═══════════════════════════╧═════════════════════════════════════════════════════════════════════════════╛
func LeaveFromTicketMatchmaking(ticketType uint8, userData *user.User) bool
LeaveFromTicketMatchmaking makes the target user leave the matchmaking that the user has matched and joined.
func LeaveFromTicketMatchmakingWithCallback(ticketType uint8, userData *user.User, cb func(err error))
LeaveFromTicketMatchmakingWithCallback makes the target user leave the matchmaking that the user has matched and joined.
func MarkTicketAsComplete(ticketType uint8, userData *user.User) error
MarkTicketAsComplete finishes the ticket as complete immediately.
[IMPORTANT] Only the owner user of the ticket may execute this function.
Error Cases
╒═══════════════════════╤═════════════════════════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞═══════════════════════╪═════════════════════════════════════════════════════════════════════════════╡ │ Ticket not found │ Either the ticket is not available or the given user does not own a ticket. │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────┤ │ User is not owner │ User given is not the owner of the ticket. │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────┤ │ Ticket room not found │ Internal room of the ticket is missing. │ │ │ Most likely due of an internal bug causing the ticket data to be corrupt. │ ╘═══════════════════════╧═════════════════════════════════════════════════════════════════════════════╛
Parameters
ticketType - Ticket type. userData - Owner user of the ticket to mark as complete.
func MarkTicketAsCompleteWhenExpire(ticketType uint8, userData *user.User) bool
MarkTicketAsCompleteWhenExpire marks the ticket as complete, but it will wait until the ticket expires.
[IMPORTANT] Only the owner of the ticket may execute this function.
This is useful when you need to have alternative conditions for matchmaking completion without having all expected members match.
func Remove(matchingID string, uniqueIDList []string, limit int)
Remove removes a list of searchable matching candidate items by their unique IDs
[NOTE] This function is very expensive as it will send a message to all related mesh nodes [NOTE] There maybe some delay with removal operation on multiple servers as the instruction to remove must traverse all servers in the cluster.
Parameters
matchingID - Target matching profile ID to remove items from uniqueIDList - A list of unique IDs of the searchable items to remove limit - Mesh network relay limit
func Search(profileIDList []string, tag string, props map[string]int, limit int, callback func(err error, results []interface{}))
Search searches for matched data based on the given props' values
[IMPORTANT] Search performs search operations on remote servers and the number of servers to perform the search is calculated based on the number of the server and distributionRate configuration. This means that there is a chance that Search function may miss the server(s) with the desired matchmaking data resulting in not finding the intended matchmaking data.
Error Cases
╒═════════════════════╤══════════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞═════════════════════╪══════════════════════════════════════════════════════════════╡ │ Invalid profile IDs │ Either missing or invalid matchmaking profile IDs give. │ ├─────────────────────┼──────────────────────────────────────────────────────────────┤ │ Invalid properties │ Either missing or invalid properties given. │ ├─────────────────────┼──────────────────────────────────────────────────────────────┤ │ Reliable timeout │ Communication to another server process timed out or failed. │ ╘═════════════════════╧══════════════════════════════════════════════════════════════╛
Parameters
profileIDList - A list of matchmaking profile IDs to search by. The order of the list is the order of search attempts. tag - A tag is used to isolate and group search meaning the search will not include tags that do not match. props - A property map to act as match making conditions. limit - A hard limit to the number of results. callback - A callback with the search results or an error.
func SearchWithRange(profileIDList []string, tag string, searchProps map[string][]int, limit int, callback func(err error, results []interface{}))
SearchWithRange searches for matched data based on the given props's values in range.
Each props will have an array of elements with property values that should range from minimum value to maximum value. The function will use those values per property to performance the search.
[IMPORTANT] SearchWithRange performs search operations on remote servers and the number of servers to perform the search is calculated based on the number of the server and distributionRate configuration. This means that there is a chance that SearchWithRange function may miss the server(s) with the desired matchmaking data resulting in not finding the intended matchmaking data. [IMPORTANT] The number of allowed range properties is limited to two.
Example:
searchProps["level"] = []int{ 1, 2, 3, 4, 5 } // range property searchProps["rank"] = []int{ 1, 2, 3 } // range property searchProps["matchType"] = []int{ 1 } // regular property searchProps["league"] = []int{ 10 } // regular property
Error Cases
╒═════════════════════╤══════════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞═════════════════════╪══════════════════════════════════════════════════════════════╡ │ Invalid profile IDs │ Either missing or invalid matchmaking profile IDs give. │ ├─────────────────────┼──────────────────────────────────────────────────────────────┤ │ Invalid properties │ Either missing or invalid properties given. │ ├─────────────────────┼──────────────────────────────────────────────────────────────┤ │ Reliable timeout │ Communication to another server process timed out or failed. │ ╘═════════════════════╧══════════════════════════════════════════════════════════════╛
Parameters
profileIDList - A list of matchmaking profile IDs to search by. The order of the list is the order of search attempts. tag - A tag is used to isolate and group search meaning the search will not include tags that do not match. searchProps - A map with search condition values. You are allowed to have maximum two properties with range (more than 1 element in the int array). If you have more than two elements with range, it will give you an error. limit - A hard limit to the number of results. callback - A callback with the search results or an error.
Diagram below shows how it works:
┏━━━┓ ┃ 8 ┃ 8 with ±3 would fall into 5 ~ 11 and that means it matches with items in the bucket of 0 to 10 and 11 to 20 ┗━┳━┛ ┏━┻━━━━┓ │ ▼ │ ▼ │ │ │ 0 ~ 10 │ 11 ~ 20 │ 21 ~ 30 │ └─────────┴─────────┴─────────┘
To make ranged search more precise, consider using SetOnTicketAllowMatchIf callback for MatchMaker Ticket.
func SetCustomJoinCondition(callback func(string, *user.User) bool)
SetCustomJoinCondition assigns a on join evaluation callback to be called to evaluate if the user should join or not
func SetOnDeleteTicketRoom(ticketType uint8, userData *user.User, callback func(id string)) bool
SetOnDeleteTicketRoom assigns a callback which is triggered when a matching room is deleted.
Uses mutex lock internally.
[IMPORTANT] This function is available ONLY for the owner of the ticket.
func SetOnIssueTicket(ticketType uint8, cb func(userData *user.User) *TicketParams) bool
SetOnIssueTicket assigns a callback to be invoked when the built-in command issue ticket is called.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked and expected to create and return TicketParams for a new ticket.
The callback is invoked for the owner user only.
Calling StartTicket triggers this callback and TicketParams that it returns will be used to create a new ticket.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] This callback must be assigned to the appropriate ticket type in order for StartTicket(ticketType uint8, userData *user.User) to work properly. [IMPORTANT] userData maybe nil if the user disconnects from the server.
func SetOnLeaveTicketRoom(ticketType uint8, userData *user.User, callback func(id string, userData *user.User)) bool
SetOnLeaveTicketRoom assigns a callback which is triggered when a member leaves a matching room.
ticket.OnMatchedMemberLeave is valid only while ticket exists whereas this will be triggered also after the ticket completion.
Uses mutex lock internally.
[IMPORTANT] This function is available ONLY for the owner of the ticket.
func SetOnMatchedTicketCanceled(ticketType uint8, cb func(ownerID string, userData *user.User)) bool
SetOnMatchedTicketCanceled assigns a callback to be invoked when a ticket that the user has joined is cancled.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked for the non-owner users of the ticket only. For the ticket owner, OnTicketCancled will be invoked. [IMPORTANT] When the owner of the ticket either disconnects or re-connects to another server, the ticket will be canceled automatically. Cancel event is raised event after the completion of the ticket when the owner of the ticket disconnects or re-connects..
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a ticket is canceled.
func SetOnTicketAllowMatchIf(ticketType uint8, cb func(ticketProps *TicketProperties, owner, candidate *user.User) bool) bool
SetOnTicketAllowMatchIf assigns a callback to be invoked before a match is made to add a custom logic to control if the match found should proceed forward to become an actual match or not..
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. callback - Callback to be called func(ticketProps *TicketProperties, owner *user.User, candidate *user.User) bool
If the callback returns true, a match will be made.
The callback is invoked for the owner user only.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] Candidate is the user that has been matched and attempting to join the matched member room. [IMPORTANT] owner and/or candidate maybe nil if owner and/or candidate disconnects from the server.
func SetOnTicketCanceled(ticketType uint8, cb func(owner *user.User)) bool
SetOnTicketCanceled assigns a callback to be invoked when an issued ticket has been canceled.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked only for the owner user of the ticket. For the non-owner users, OnMatchedTicketCancled will be invoked. [IMPORTANT] Owner maybe nil if owner is disconnected from the server.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a ticket is canceled.
func SetOnTicketComplete(ticketType uint8, cb func(ticketProps *TicketProperties, owner *user.User) []byte) bool
SetOnTicketComplete assigns a callback to be invoked when an issued ticket successfully completes.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked only for the owner user of the ticket. [IMPORTANT] Owner maybe nil if owner disconnects from the server.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a matchmaking is complete.
The callback is invoked for the owner user of the ticket only.
The callback function must return a message byte array to be sent to all matched user clients.
func SetOnTicketMatch(ticketType uint8, cb func(ticket *Ticket, matchedUser, ownerUser *user.User, roomID string, memberIDs []string) bool) bool
SetOnTicketMatch assigns a callback to be invoked when a new match is made.
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to control if the match completes the matchmaking or not. Room ID passed to the callback is NOT Diarkis Room's ID, but it is the ID of the internal matchmaking room. func(ticket *Ticket, matchedUserData *user.User, owner *user.User, roomID string, memberIDs []string) bool
This callback is meant to execute a custom logic for matchmaking completion on every match found.
Having the callback return true will automatically completes the matchmaking.
The callback is invoked for the owner user only.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORATNT] callback is invoked for the owner of the ticket only. [IMPORTANT] matchedUser is a copy of the actual user data of *user.User because the matched user maybe on a different server. [IMPORTANT] ownerUser and/or matchedUser maybe nil if ownerUser and/or matchedUser disconnects from the server.
func SetOnTicketMemberJoined(ticketType uint8, cb func(ticket *Ticket, joinedUser, ownerUser *user.User, memberIDs []string)) bool
SetOnTicketMemberJoined assigns a callback to be invoked when a matched member joins.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked for the owner user only. [IMPORTANT] joinedUser is a copy of the actual user data of *user.User because the matched user maybe on a different server. [IMPORTANT] ownerUser and/or joinedUser maybe nil if ownerUser and/or joinedUser disconnects from the server.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a matched member joins the match.
func SetOnTicketMemberJoinedAnnounce(ticketType uint8, cb func(ticket *Ticket, joinedUser, ownerUser *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte)) bool
SetOnTicketMemberJoinedAnnounce assigns a callback to be invoked when a matched member joins and returns ver, cmd, and message to be used as an announcement.
An announcement is sent to all matched users.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The event is invoked for the owner of the ticket only.
Parameters
ticketType - Apply the callback to the given ticket type. cb - Callback to be invoked when a new user successfuly match and join. ticket - The matchmaking ticket. joinedUser - The user that joined the matchmaking. [IMPORTANT] This is a copy data of the joined user and it is not the actual joined user data. ownerUser - The owner user of the matchmaking ticket. memberIDs - an array of matched member user IDs.
Example:
added := matching.SetOnTicketMemberJoinedAnnounce(ticketType, func(ticket *matching.Ticket, joinedUser, ownerUser *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte) { // we will be sending a notification message to all matched users with the following: ver = uint8(2) // the notification message will be sent with command ver 2 cmd = uint16(1010) // the notification message will be sent with command ID 1010 message = []byte(strings.Join(messageIDs, ",")) // the notification message will send a message with comma separated list of matched member user IDs. return ver, cmd, message }) if !added { // failed to assign the callback... }
func SetOnTicketMemberLeave(ticketType uint8, cb func(ticket *Ticket, leftUserData, ownerUser *user.User, roomID string, memberIDs []string)) bool
SetOnTicketMemberLeave assigns a callback to be invoked when a matched member leaves.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked for the owner user only. [IMPORTANT] leftUser is a copy of the actual user data of *user.User because the matched user maybe on a different server. [IMPORTANT] ownerUser and/or leftUserData maybe nil if ownerUser and/or leftUserData disconnects from the server.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a matched member leaves the match.
func SetOnTicketMemberLeaveAnnounce(ticketType uint8, cb func(ticket *Ticket, joinedUser, ownerUser *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte)) bool
SetOnTicketMemberLeaveAnnounce assigns a callback to be invoked when a matched member leaves and returns ver, cmd, and message to be used as an announcement.
An announcement is sent to all matched users.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The event is invoked for the owner of the ticket only.
Parameters
ticketType - Apply the callback to the given ticket type. cb - Callback to be invoked when a matched user leaves. ticket - The matchmaking ticket. leftUser - The user that left the matchmaking. [IMPORTANT] This is a copy of the left user data and it is not the acutal left user data. ownerUser - The owner user of the matchmaking ticket. memberIDs - an array of matched member user IDs.
Example:
added := matching.SetOnTicketMemberLeaveAnnounce(ticketType, func(ticket *matching.Ticket, leftUser, ownerUser *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte) { // we will be sending a notification message to all matched users with the following: ver = uint8(2) // the notification message will be sent with command ver 2 cmd = uint16(1010) // the notification message will be sent with command ID 1010 message = []byte(strings.Join(messageIDs, ",")) // the notification message will send a message with comma separated list of matched member user IDs. return ver, cmd, message }) if !added { // failed to assign the callback... }
func SetOnTicketTimeout(ticketType uint8, cb func(owner *user.User)) bool
SetOnTicketTimeout assigns a callback to be invoked when an issued ticket has timed out.
[CRITITALLY IMPORTANT] Using pointer variables that are defined outside of the callback closure in the callback closure will cause those pointers to be not garbage collected leading to memory leak. [IMPORTANT] The callback is invoked for the owner user of the ticket only. [IMPORTANT] Owner maybe nil if owner disconnects from the server.
Parameters
ticketType - Ticket type is used to group tickets. It will assign the callback to the given ticket type. cb - Callback to be invoked when a ticket times out.
func SetTicketProperties(ticketType uint8, userData *user.User, data map[string]interface{}) error
SetTicketProperties stores a collection of keys and their values to ticket as properties.
Error Cases
+----------------+----------------------------------------------------------------+ | Error | Reason | +----------------+----------------------------------------------------------------+ | Room not found | MatchMaker ticket is corrupt. | | Must be owner | Only the ticket owner user is allowed to execute the function. | +----------------+----------------------------------------------------------------+
Uses mutex lock internally.
[IMPORTANT] This function is avilable ONLY for the owner of the ticket. [IMPORTANT] If the same key exists, it overwrites the existing value of the same key.
Properties are only premitive values and does not support reference type data such as array and map.
func SetTicketProperty(ticketType uint8, userData *user.User, key string, value interface{}) error
SetTicketProperty stores a key and a value as a property to the ticket.
Error Cases
+----------------+----------------------------------------------------------------+ | Error | Reason | +----------------+----------------------------------------------------------------+ | Room not found | MatchMaker ticket is corrupt. | | Must be owner | Only the ticket owner user is allowed to execute the function. | +----------------+----------------------------------------------------------------+
Uses mutex lock internally.
[IMPORTANT] This function is avilable ONLY for the owner of the ticket.
If the same key exists, it overwrites the existing value of the same key.
Properties are only premitive values and does not support reference type data such as array and map.
func SetTicketPropertyIfNotExists(ticketType uint8, userData *user.User, key string, value interface{}) bool
SetPropertyIfNotExists stores a key and a value as a property to the ticket if the same key does not exist.
Uses mutex lock internally.
[IMPORTANT] This function is avilable ONLY for the owner of the ticket.
Properties are only premitive values and does not support reference type data such as array and map.
func Setup(confpath string)
Setup sets up MatchMaker on the server. You must call this at the start of the server process.
confpath - Absolute path of the configuration file to be loaded.
func StartTicket(ticketType uint8, userData *user.User) error
StartTicket creates and starts a new ticket-based matchmaking with the given ticket type.
[IMPORTANT] If the owner user (user that created the ticket) disconnects or re-connects, the ticket will be canceled automatically. This also means that if you use Diarkis modules (Diarkis Field and Diarkis Room) that may require the user to re-connect such as Room and Field, it may cause the ticket to be canceled unexpected when the user re-connects. [IMPORTANT] Complex search properties with large number of properties with long range (lengthy array of values) may have negative impact on server performance.
Error Cases
╒════════════════════════════════════════════════════╤══════════════════════════════════════════════════════════════════════════════╕ │ Error │ Reason │ ╞════════════════════════════════════════════════════╪══════════════════════════════════════════════════════════════════════════════╡ │ MatchMaker is not setup correctly │ SetOnIssueTicket callback for the ticketType must be assigned. │ ├────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ MatchMaker ticket cannot be issued more than once │ The user is not allowed to issue more than one ticket of the same ticke type.│ ├────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Failed to create a ticket │ Given nil for *TicketParams. │ ├────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Failed to issue a new ticket │ The user is still in a previous matchmaking room of the same ticket type. │ ╘════════════════════════════════════════════════════╧══════════════════════════════════════════════════════════════════════════════╛
Parameters
ticketType - Ticket type is used to group tickets. You may issue multiple tickets of different ticket types. userData - The user that issues and starts the ticket and becomes the owner of the ticket.
Ticket manages MatchMaker's Add and Search internally, so that you do not have to manage and balance their calls.
Ticket has two phases: "Search" and "Waiting"
Ticket starts out in "Search" phase and moves to "Waiting" phase.
The diagram below shows how a ticket operations internally:
┌──────────────┐ │ Start Ticket │ └──────┬───────┘ │ ▼ ┌──────────────┐ │ Search │ └──────┬───────┘ │ ┌──────────┴──────────┐ │ │ Ticket actively searches for ▼ ▼ other tickets that are ┌───────────────┐ ┌────────┐ Ticket creates a waiting room for in "Wait" phase to match │ Found Matches │ │ Wait │ the ticket and waits for └──────┬────────┘ └──┬──┬──┘ other tickets to "Search" it and match ╭────────────────────────────────────╮ │ │ │ │ Ticket found other tickets │ │ ┌─────────────────┘ │ │ to join and matched ticket ├─▷│ │◁──────────┐ │ │ met the required number of users │ │ │ │ │ ╰────────────────────────────────────╯ ▼ ▼ │ ▼ ╔═══════════════════════╗ │ ┌─────────┐ If required number of users are not met ║ Matchmaking Completed ║ │ │ Timeout │ and ticket ducation expires, ╚═══════════════════════╝ │ └─────────┘ the ticket times out. In order to continue, │ The user must issue and start a new ticket ╭──────────────────────────────────────────────────┴─╮ │ Other tickets searched and found │ │ and the required number of users have been matched │ ╰────────────────────────────────────────────────────╯
The table below explains the notifications that the client receives from the server.
┌───────────────────┬──────────────────┬─────────────────┬───────────────────────────────────────────────────────────────────────────┐ │ Notification Type │ Push Command Ver │ Push Command ID │ Description │ ╞═══════════════════╪══════════════════╪═════════════════╪═══════════════════════════════════════════════════════════════════════════╡ │ Succecss │ 1 │ 220 │ Matchmaking ticket has been successfuly completed │ │ │ │ │ and all matched user clients receive this server push. │ ├───────────────────┼──────────────────┼─────────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Timeout │ 1 │ 219 │ Matchmaking ticket has failed and it has been discarded. │ │ │ │ │ All user clients that matched receives this server push. │ ├───────────────────┼──────────────────┼─────────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Cancel │ 1 │ 222 │ Matchmaking ticket has been canceled │ │ │ │ │ and all user clients that matched reiceves this server push. │ ├───────────────────┼──────────────────┼─────────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Broadcast │ 1 │ 224 │ Matchmaking ticket sends a broadcast message to all matched user clients. │ └───────────────────┴──────────────────┴─────────────────┴───────────────────────────────────────────────────────────────────────────┘
Calling StartTicket raises The callback assigned by SetOnIssueTicket and a new ticket will be created using the given ticket parameters.
Example with SetOnIssueTicket callback
// the callback will be invoked by matching.StartTicket matching.SetOnIssueTicket(sampleTicketType, func(userData *user.User) *matching.TicketParams { return &matching.TicketParams{ ProfileIDs: []string{"RankMatch"}, MaxMembers: 2, SearchInterval: 300, // 300 milliseconds interval of search SearchTries: 4, // allow 4 consecutive empty search results up to 4 times before moving on to wait TicketDuration: 20, // ticket lasts for 20 seconds HowMany: 20, // up to 20 search results Tag: "", // if we want to group tickets using tag add the string value here AddProperties: &map[string]int{ "Rank": 3 }, // wait for other users to find me and my rank is 3 SearchProperties: &map[string][]int{ "Rank": &[]int{ 1, 2, 3, 4, 5 } }, // search for other users within the range of 1 to 5 and property is "Rank" } }) err := matching.StartTicket(sampleTicketType, userData) if err != nil { // error... }
▶︎ SearchPropeties
ServerProperties dictate conditions for searches that is performed internally.
[IMPORTANT] The number of allowed range properties is limited to two. When you have multiple elements in a search property, it is considered as a range property. [IMPORTANT] SearchProperties operates AND operations. It means that with multiple search properties, the search must satisfy all search properties in order to match.
Diagram below shows how each search property operates:
┏━━━┓ ┃ 8 ┃ 8 with ±3 would fall into 5 ~ 11 and that means it matches with items in the bucket of 0 to 10 and 11 to 20 ┗━┳━┛ ┏━┻━━━━┓ │ ▼ │ ▼ │ │ │ 0 ~ 10 │ 11 ~ 20 │ 21 ~ 30 │ └─────────┴─────────┴─────────┘
Example:
searchProps["level"] = []int{ 1, 2, 3, 4, 5 } // range property searchProps["rank"] = []int{ 1, 2, 3 } // range property searchProps["matchType"] = []int{ 1 } // regular property searchProps["league"] = []int{ 10 } // regular property
Order of range search property's search:
The range search properties will look for matches in the order of the array. It means that if []int{ 1, 2, 3, 4, 5 } is given, it will start from 1 and continue upto 5 until it finds it matches.
▶︎ Callbacks
Every callback is assigned to given ticket type and invoked based on assigned ticket type.
func StartTicketBackfill(ticketType uint8, owner *user.User) error
StartTicketBackfill starts "backfill" on a ticket that has already been completed.
Backfill allows other users to match and join "after" the completion of the ticket.
When ticket is completed, the ticket itself will be deleted, but the matched users remain in the ticket room.
The owner user that wishes to start backfill must be a member of this ticket room.
[IMPORTANT] If the ticket is full, no users may match and join even with backfill started. [IMPORATNT] In order to stop backfill, you must invoke StopTicketBackfill.
Error Cases
+----------------------------------------------------+--------------------------------------------------------------------------------+ | Error | Reason | +----------------------------------------------------+--------------------------------------------------------------------------------+ | Completed ticket room must be available | The ticket and its internal room have been discarded. | | Ticket already exists | Either the ticket has not been completed or backfill has already been started. | | MatchMaker is not setup correctly | SetOnIssueTicket callback for the ticketType must be assigned. | | MatchMaker ticket cannot be issued more than once | The user is not allowed to issue more than one ticket of the same ticke type. | | Failed to create a ticket | Given nil for *TicketParams. | | Failed to issue a new ticket | The user is still in a previous matchmaking room of the same ticket type. | +----------------------------------------------------+--------------------------------------------------------------------------------+
Parameters
ticketType - Type of the completed ticket to start backfill. owner - Ticket's owner user.
func StopTicketBackfill(ticketType uint8, owner *user.User) error
StopTicketBackfill stops backfill ticket.
Error Cases +--------------------------------+-------------------------------------------------------------------------+ | Error | Reason | +--------------------------------+-------------------------------------------------------------------------+ | Backfill ticket not found | Backfill ticket to stop does not eixst. | | Backfill ticket room not found | Backfill ticket room has been discarded. (All users have disconnected.) | +--------------------------------+-------------------------------------------------------------------------+
Parameters
ticketType - Backfill ticket type to stop backfill. owner - Backfill ticket owner user.
func TTLTest(src []int64) []int64
TTLTest this is used ONLY in tests
func Test(method string, data map[string]interface{}) ([]byte, error)
Test this is used ONLY in tests
func TestDebugDataDump() map[string][]*searchItem
TestDebugDataDump is used ONLY in internal tests.
func TicketBroadcast(ticketType uint8, userData *user.User, ver uint8, cmd uint16, msg []byte) error
TicketBroadcast sends a reliable message to all matched users with the given ver, cmd, and message byte array.
[NOTE] This function can be executed by any matched member user.
Parameters
ticketType - MatchMaker Ticket's type. userData - Matched member user of the ticket. ver - Broadcast message command version. cmd - Broadcast message command ID. msg - Broadcast message data in byte array format.
func UpdateTicketProperties( ticketType uint8, userData *user.User, data map[string]interface{}, cb func(exists bool, storedValue interface{}, newValue interface{}) (updateValue interface{})) error
UpdateTicketProperties changes the existing property values of ticket.
The callback is invoked while the internal lock is still held, locking inside the callback may cause mutex deadlock.
Error Cases
+----------------+----------------------------------------------------------------+ | Error | Reason | +----------------+----------------------------------------------------------------+ | Room not found | MatchMaker ticket is corrupt. | | Must be owner | Only the ticket owner user is allowed to execute the function. | +----------------+----------------------------------------------------------------+
Highlights
[IMPORTANT] This function is avilable ONLY for the owner of the ticket. [IMPORTANT] This function is NOT asynchronous. [IMPORTANT] Properties are only premitive values and does not support reference type data such as array and map.
Parameters
ticketType - Ticket type is used to find the ticket. userData - Owner user data of the ticket. data - A map of key and value pair to be stored or updated as properties. cb - Callback to be invoked on every key and value pair to handle the update. func(exists bool, storedValue interface{}, updateValue interface{}) (updatedValue interface{}) - exists - Indicates if the same key already exists or not - storedValue - Existing value that is stored as a property. If the key does not exist it is a nil. - updateValue - The value to be used to update/replace or set.
func UpdateTicketProperty( ticketType uint8, userData *user.User, key string, value interface{}, cb func(exists bool, storedValue interface{}, newValue interface{}) (updateValue interface{})) error
UpdateTicketProperty changes the existing property value of ticket.
The callback is invoked while the internal lock is still held, locking inside the callback may cause mutex deadlock.
Error Cases
+----------------+----------------------------------------------------------------+ | Error | Reason | +----------------+----------------------------------------------------------------+ | Room not found | MatchMaker ticket is corrupt. | | Must be owner | Only the ticket owner user is allowed to execute the function. | +----------------+----------------------------------------------------------------+
Highlights
[IMPORTANT] This function is avilable ONLY for the owner of the ticket. [IMPORTANT] This function is NOT asynchronous. [IMPORTANT] Properties are only premitive values and does not support reference type data such as array and map.
Parameters
ticketType - Ticket type is used to find the ticket. userData - Owner user data of the ticket. key - A key of the property to be updated. value - A value of the property to be updated with. cb - Callback to be invoked on every key and value pair to handle the update. func(exists bool, storedValue interface{}, updateValue interface{}) (updatedValue interface{}) - exists - Indicates if the same key already exists or not - storedValue - Existing value that is stored as a property. If the key does not exist it is a nil. - updateValue - The value to be used to update/replace or set.
AddData represents internally used matchmaking data
type AddData struct { InternalID string `json:"internalID"` MatchingID string `json:"matchingID"` Tag string `json:"tag"` Props map[string]int `json:"props"` Value map[string]interface{} `json:"value"` TTL int64 `json:"ttl"` }
Client represents matchmaking ticket matched member user client.
type Client struct { ID string SID string // Available ONLY for UDP PublicAddress string // Available ONLY for UDP PrivateAddressBytes []byte // User property data copied when the user joins a matchmaking ticket UserData map[string]interface{} }
func GetTicketMemberClients(ticketType uint8, userData *user.User) ([]*Client, bool)
GetTicketMemberClients returns the list of matched member user clients.
Cases for the second return value to be false
Highlights
[IMPORTANT] This function is aviable ONLY for the owner of the ticket. [IMPORTANT] If non-user uses this function it returns an empty array.
FindOwnerData represents internally used data
type FindOwnerData struct { SID string `json:"sid"` }
JoinRoomData represents internally used data
type JoinRoomData struct { TicketType uint8 `json:"ticketType"` ID string `json:"id"` SID string `json:"sid"` MeshAddr string `json:"meshAddr"` UserData map[string]interface{} `json:"userData"` }
LeaveRoomData represents internally used data
type LeaveRoomData struct { TicketType uint8 `json:"ticketType"` ID string `json:"id"` UID string `json:"uid"` SID string `json:"sid"` }
RemoveData represents internally used matchmaking removal data
type RemoveData struct { MatchingID string `json:"matchingID"` UniqueIDs []string `json:"uniqueIDs"` }
Room represents matchmaker ticket room that is used internally
type Room struct { sync.RWMutex // contains filtered or unexported fields }
func (r *Room) CancelReservation(userData *user.User) bool
CancelReservation removes the reservation of the given user from the ticket room.
func (r *Room) GetID() string
GetID returns the room ID.
func (r *Room) GetMemberIDs() []string
GetMemberIDs returns an array of matched member IDs.
func (r *Room) GetMemberMeshAddrByUID(uid string) string
GetMemberMeshAddrByUID returns a mesh address of a member.
Returns an empty string if the member is not found or invalid.
func (r *Room) GetMemberMeshAddrList() []string
GetMemberMeshAddrList returns an array of internal server address of each matched user.
func (r *Room) GetMemberSIDByUID(uid string) string
GetMemberSIDByUID returns the member's SID.
It returns and empty string if the member is not found or invalid.
func (r *Room) GetMemberSIDs() []string
GetMemberSIDs returns an array of matched member SIDs.
func (r *Room) GetMemberUsers() []*user.User
GetMemberUsers returns an array of matched member user copies.
[IMPORTANT] The return array contains copies of member users.
func (r *Room) GetOwnerUser() (*user.User, bool)
GetOwnerUser returns the ticket owner user.
[IMPORTANT] Returned owner user is NOT a copy.
func (r *Room) GetProperties(keys []string) map[string]interface{}
GetProperties returns key and value pairs as a map.
Properties are only premitive values and does not support reference type data such as array and map.
If a value of a given key does not exist, the returned map will have a nil as a value of the key.
The returned property value is an interface{}, in order to type assert safely, please use Diarkis' util package functions.
Example:
values, ok := r.GetProperties([]string{ "someKey" }) if !ok { // handle error here } for key, v := range values { // If the value data type is an uint8, of course ;) value, ok := util.ToUint8(v) }
func (r *Room) GetProperty(key string) (interface{}, bool)
GetProperty returns the value of the given key and if the key does not exist, the second return value will be a false.
Properties are only premitive values and does not support reference type data such as array and map.
The returned property value is an interface{}, in order to type assert safely, please use Diarkis' util package functions.
Example:
v, ok := r.GetProperty("someKey") if !ok { // handle error here } // If the value data type is an uint8, of course ;) v, ok := util.ToUint8(v)
func (r *Room) MakeReservation(userData *user.User) bool
MakeReservation allows the user to reserve a spot in the ticket room.
func (r *Room) SetOnDeleted(cb func(id string)) bool
SetOnDeleted assigns a callback on ticket room deletion.
[NOTE] You can assign multiple callbacks to a room.
func (r *Room) SetOnJoin(cb func(id string, userData *user.User) bool) bool
SetOnJoin assigns a callback on ticket room to be invoked when a new member is matched and attempting to join the match.
The callback returns a bool and if you return false, the matched user will be rejected and will not match and join.
[NOTE] You can assign multiple callbacks to a room.
func (r *Room) SetOnJoined(cb func(id string, userData *user.User)) bool
SetOnJoined assigns a callback on ticket room to be invoked when a new member is matched.
[NOTE] You can assign multiple callbacks to a room.
func (r *Room) SetOnLeft(cb func(id string, userData *user.User)) bool
SetOnLeft assigns a callback on ticket room to be invoked when a member of matched user leaves the match.
[NOTE] You can assign multiple callbacks to a room.
func (r *Room) SetOnTick(interval uint16, cb func(id string)) bool
SetOnTick assigns a callback to be invoked at every given interval.
[IMPORTANT] A single callback may be assigned per tick interval. You may not assign multiple calblacks a tick with the same interval.
Parameters
interval - Tick interval in seconds. cb - Callback to be invoked at every tick.
func (r *Room) SetOnTickStop(interval uint16, cb func(id string)) bool
SetOnTickStop assigns a calblack to be invoked when a tick of the room stops.
[IMPORTANT] Only one callback can be assigned to a room.
func (r *Room) SetProperties(data map[string]interface{})
SetProperties stores a collection of keys and their values to ticket room.
If the same key exists, it overwrites the existing value of the same key.
Properties are only premitive values and does not support reference type data such as array and map.
func (r *Room) SetProperty(key string, value interface{})
SetProperty stores a key and value data to ticket room.
If the same key exists, it overwrites the existing value of the same key.
Properties are only premitive values and does not support reference type data such as array and map.
func (r *Room) SetPropertyIfNotExists(key string, value interface{}) bool
SetPropertyIfNotExists stores a key and value data to ticket room if the same key does not exist.
Properties are only premitive values and does not support reference type data such as array and map.
func (r *Room) StopAllTicks() bool
StopAllTicks stops all tick loops.
func (r *Room) UpdateProperties(data map[string]interface{}, cb func(bool, interface{}, interface{}) interface{})
UpdateProperties changes the existing property values of ticket room.
The callback is invoked while the internal lock is still held, locking inside the callback may cause mutex deadlock.
Properties are only premitive values and does not support reference type data such as array and map.
data - A map of key and value pair to be stored as properties. cb - Callback to be invoked on every key and value pair to handle the update. func(exists bool, storedValue interface{}, updateValue interface{}) (updatedValue interface{}) - exists - Indicates if the same key already exists or not - storedValue - Existing value that is stored as a property. If the key does not exist it is a nil. - updateValue - The value to be used to update/replace or set.
func (r *Room) UpdateProperty(key string, value interface{}, cb func(bool, interface{}, interface{}) interface{})
UpdateProperty changes the existing property value of ticket room.
The callback is invoked while the internal lock is still held, locking inside the callback may cause mutex deadlock.
Properties are only premitive values and does not support reference type data such as array and map.
key - A key of the property to be updated. value - A value of the property to be updated with. cb - Callback to be invoked on every key and value pair to handle the update. func(exists bool, storedValue interface{}, updateValue interface{}) (updatedValue interface{}) - exists - Indicates if the same key already exists or not - storedValue - Existing value that is stored as a property. If the key does not exist it is a nil. - updateValue - The value to be used to update/replace or set.
RoomBroadcastData represents internally used broadcast message data
type RoomBroadcastData struct { ID string `json:"id"` Ver uint8 `json:"ver"` Cmd uint16 `json:"cmd"` Msg []byte `json:"msg"` MemberSIDs []string `json:"memberSIDs"` }
RoomJoinReturnData represents internally used data
type RoomJoinReturnData struct { LockKey string `json:"lockKey"` }
SearchData represents internally used matchmaking data
type SearchData struct { MatchingID string `json:"matchingID"` Tag string `json:"tag"` Props map[string][]int `json:"props"` Limit int `json:"limit"` }
SearchReturnData represents internally used data
type SearchReturnData struct { Results []*SearchReturnItemData `json:"results"` }
SearchReturnItemData represents internally used data
type SearchReturnItemData struct { ID string `json:"id"` TTL int64 `json:"ttl"` Value interface{} `json:"value"` }
Ticket represents a matchmaking ticket that manages a life cycle of issued ticket
OnMatch - Raised when a remote user matches. By returning true, you may compelte the ticket and raise OnComplete (OnComplete event is captured by matching.SetOnComplete callback) OnMatchedMemberJoined - Raised when a matched member completes join. OnMatchedMemberJoinedAnnounce - Raised when a matched member completes join and returns ver, cmd, and message to be sent to all matched members. OnMatchedMemberLeaveAnnounce - Raised when a matched member leaves and returns ver, cmd, and message to be sent to all matched members. OnMatchedMemberLeave - Raised when a matched member user leave the match. OnTimeout - Raised when the ticket times out.
type Ticket struct { OnMatch func(ticket *Ticket, userData *user.User, owner *user.User, roomID string, memberIDs []string) bool OnMatchedMemberJoined func(ticket *Ticket, userData *user.User, owner *user.User, memberIDs []string) OnMatchedMemberLeave func(ticket *Ticket, userData *user.User, owner *user.User, roomID string, memberIDs []string) OnTimeout func(userData *user.User) OnMatchedMemberJoinedAnnounce func(ticket *Ticket, userData *user.User, owner *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte) OnMatchedMemberLeaveAnnounce func(ticket *Ticket, userData *user.User, owner *user.User, memberIDs []string) (ver uint8, cmd uint16, message []byte) // contains filtered or unexported fields }
func FindTicket(ticketType uint8, userData *user.User) *Ticket
FindTicket returns the valid matchmaking ticket that the user has.
[IMPORTANT] This function works with the owner of the ticket only. [IMPORTANT] IF the user given does not own a ticket, it returns nil. ticketType - MatchMaker ticket type. userData - The owner user of the ticket.
func (t *Ticket) GetRoomID() string
GetRoomID returns the room ID of the ticket.
func (t *Ticket) GetTicketType() uint8
GetTicketType returns the ticket type of the *Ticket instance.
func (t *Ticket) IsTicketFinished() bool
IsTicketFinished returns true if the ticket has finished its entire operations.
func (t *Ticket) Start() bool
Start starts the life cycle of a ticket.
func (t *Ticket) Stop() bool
Stop interrupts the ticket and stops all matchmaking opertions.
TicketHolder represents add and search properties of the ticket holder user.
AddProperties - Add properties of the ticket: Add properties are used to be found by other tickets. SearchProperties - Ssarch properties of the ticket: Search properties are used to search for other tickets. ApplicationData - May hold application data that maybe added from the application. ApplicationData must NOT be a struct or must NOT contain struct.
type TicketHolder struct { AddProperties map[string]int SearchProperties map[string][]int ApplicationData interface{} }
TicketParams parameter struct for issueTicket
[IMPORTANT] AddProperties and SearchProperties are limited to have up to 2 properties.
Properties
ProfileIDs - A list of profiles to add to and search against Tag - A string tag to group matchmaking data by the same tag. Data with different tag do NOT match even with the matching properties. Leave it with an empty string if no need. AddProperties - Matchmaking properties (conditions) for add (being a host waiting) SearchProperties - Matchmaking properties to used for search Each property may contain a range of property values i.e. []int{ 1, 2, 3, 4, 5 } etc. The number of properties allowed is 2, if you exceed the number of properties, two properties will be randomly chosen. ApplicationData - May hold application data that maybe added from the application. ApplicationData must NOT be a struct or must NOT contain struct. MaxMembers - Maximum number of matchmaking users per matchmaking. When matched users reach this number, the matchmaking will complete as success TicketDuration - Duration of the ticket to be valid in seconds. Minimum value for TicketDuration is 10 seconds. SearchInterval - The interval for search in milliseconds TimeoutExtensionOnMatchJoin - Timeout extension in seconds to be added every time a new match joins. Leave it with 0 if no need. SearchTries - Number of empty search results to tolarate before giving up and moving on to hosting (add) EmptySearches - If the number of empty search results reach EmptySearches, the ticket will forcefully change to add phase. If 0 is given, this feature will be disabled. Default is 0. HowMany - Matchmaking profile IDs to use for search and add Leave this empty if you do not need to repeat the operation set.
A ticket has two phases. When you start a ticket, it starts as a search phase where it actively searches other tickets that are in waiting phase. Once a certain time passes and the search yields no matches, ticket then switches to waiting phase where it waits for other searching tickets to find it.
Diagram below visually explains how these two pahses of a ticket work and how some of the parameters affect these two phases.
▶︎ SearchInterval 200ms ▶︎ SearchTries 10 ▶︎ TicketDuration 4s ▷ Search Phase: The ticket will search every 200ms 10 times ▷ Wait Phase: If the ticket does not find match, it will wait for the remainder of time until the ticket duration expires 200ms x 10 searches ┌────── Search Phase ──────┐ ┌─────── Waiting Phase ───────┐ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┰────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ ┃ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┸────────────────────────────────┘ Total 2 seconds of searching Total 2 seconds of waiting │ │ └─────────── Ticket duration is 4 seconds in total ────────────┘ This means that a ticket in search phase will only match with tickets in wait phase and vice versa.
It usually helps to have randomized values for SearchInterval, SearchTries, and TicketDuration.
This is because every ticket strictly follows search → wait flow. Having every ticket with different search and wait durations will help tickets find other tickets.
type TicketParams struct { ProfileIDs []string Tag string AddProperties map[string]int SearchProperties map[string][]int ApplicationData interface{} MaxMembers uint8 TicketDuration uint8 SearchInterval uint16 TimeoutExtensionOnMatchJoin uint8 SearchTries uint8 EmptySearches uint8 HowMany uint8 }
TicketProperties represents both the owner of the matched ticket and the candidate to be matched.
It is primarily meant to be used for SetOnTicketAllowMatchIf callback.
Owner - Represents ticket owner's add and search properties (user that perform add/waiting). Owner add and search properties are pointers to the original properties and chaning the values may influence the matchmaking. Candidate - Represents match candidate's add and search properties (user that performes searches). Candidate add and search properties are pointers to the original properties and chaning the values may influence the matchmaking.
type TicketProperties struct { Owner *TicketHolder Candidate *TicketHolder }
UpdateUserData represents internally used user data update
type UpdateUserData struct { RoomID string `json:"id"` UserID string `json:"ID"` SID string `json:"SID"` PublicAddr string `json:"PublicAddr"` PrivateAddrBytes []byte `json:"PrivateAddrBytes"` MeshAddr string `json:"meshAddr"` }