package room
import "github.com/Diarkis/diarkis/room"
Package room ▷
Room module
[IMPORTANT] Diarkis Room can NOT be used with Diarkis Field and MatchMaker Ticket.
Room Join
Joining a room may require the client to switch the server depending on where the join is located. If the client is connected to a server that the room is not located, the server instructs the client to re-connect. This is handled internally by Diarkis.
There are a few things you must keep in mind when using Join function.
The callback of Join function may not be invoked on the server where the room is. What this means is that if the client is required to re-connect to the server where the room is, Diarkis internally handles this from one server to another. The callback is then invoked on the server that the client was originally connected.
The following example will not work as expected if the client is required to re-connect, therefore you must avoid writing such code:
▶︎ Retrieving a room property in Join callback
room.Join(roomID, userData, ver, cmd, message, callback func(err error, memberIDs []string, ownerID string, createdTime int64) { // This will NOT retrieve intended room property because the room does not exist on this server doesNotWork := room.GetProperty(roomID, "RoomName") // This WILL retrieve intended room property because room.GetRemoteProperty accesses the room on the different server // Notice the function is asynchronous room.GetRemoteProperty(roomID, "RoomName", func(err error, value interface{}) { // value is the property of "RoomName" }) })
Room Broadcast
Room Broadcast sends a message to all member clients of the room including the sender itself.
Room Broadcast requires the sender user to he a member of the room.
Room Broadcast also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Broadcast messages for the given interval. The interval is given to the room when the room is created.
Room Message
Room Message sends a message to selected members clients of the room.
Room Message requires the sender user to he a member of the room.
Room Message also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Message messages for the given interval. The interval is given to the room when the room is created.
Room Announce
Room Announce sends a message to selected member of clients of the room regardless of the sender user being a member of the room. This function is not available for the built-in client command calls.
Room Announce also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Announce messages for the given interval. The interval is given to the room when the room is created.
Room Relay
Room Relay sends a message to all members of the room except for the sender user.
Unlike Room Broadcast, Message, and Announce, Room Relay does not combine multiple messages.
Room State Synchronization
Room State Synchronization allows the user to add, remove, and update custom states.
A Room State has a name and a value that will be automatically synchronized to the member clients when the state value changes. The member clients will raise an event per synchronization of a state.
▶︎ Setting up Room State Synchronization
Command version to be used to send synchronization data when a state value changes. updateVer := uint8(2) // Command version to be used to send synchronization data when a state is removed. removeVer := uint8(2) // Command ID to be used to send synchronization data when a state value changes. updateCmd := uint16(1000) // Command ID to be used to send synchronization data when a state is removed. removeCmd := uint16(1100) // Checks and send synchronization data to all member clients at every 100 milliseconds. syncInterval := int64(100) // Delays the initial synchronization of all states when a new client becomes a member of the room. // The value is in milliseconds. syncAllDelay := int64(0) // TTL of each state. If a state is not updated for longer than TTL, it will be removed automatically. ttl := int64(500) // Maximum number of synchronization data packets to be combined. combineLimit := 10 success := room.EnableStateSync(roomID, updateVer, removeVer, updateCmd, removeCmd, syncInterval, syncAllDelay, ttl, combineLimit)
▶︎ Update Room State With The Current Value
When updating a state, you may need to use the current value of the state to perform the update operation while making sure the value of the state will not be changed until the update operation is finished.
[IMPORTANT] The callback is invoked while a mutex lock is still held and it is released when the callback returns.
The example below increments the current state value. Since the callback is protected by a mutex lock, there is no race condition while updating the value.
err := room.UpsertStateByRoomID(roomID, userData, key, reliable, cb func(exists bool, current []byte { if !exists { // The state does not exist, so simply create a new one. // The returned value will be the state value. // For example, the value of this state is a byte array encoded uint32 bytes := make([]byte, 4) binary.BigEndian.PutUint32(bytes, newStateValue) return bytes } // For example, the value of the state is byte array encoded uint32 currentCount := binary.BigEndian.Uint32(current) currentCount += newStateValue bytes := make([]byte, 4) binary.BigEndian.PutUint32(bytes, currentCount) return bytes }) []byte)
Index
- Constants
- func AfterBroadcastRoomCmd(...)
- func AfterCreateOrJoinByCustomIDCmd(...)
- func AfterCreateRoomCmd(...)
- func AfterGetRoomPropCmd(...)
- func AfterJoinRoomCmd(...)
- func AfterLeaveRoomCmd(...)
- func AfterMessageExtendedRoomCmd(...)
- func AfterMessageRoomCmd(...)
- func AfterUpdateRoomPropCmd(...)
- func Announce(roomID string, memberIDs []string, ver uint8, cmd uint16, message []byte, ...)
- func BeforeBroadcastRoomCmd(...)
- func BeforeCreateOrJoinByCustomIDCmd(...)
- func BeforeCreateRoomCmd(...)
- func BeforeGetRoomPropCmd(...)
- func BeforeJoinRoomCmd(...)
- func BeforeLeaveRoomCmd(...)
- func BeforeMessageExtendedRoomCmd(...)
- func BeforeMessageRoomCmd(...)
- func BeforeUpdateRoomPropCmd(...)
- func Broadcast(roomID string, senderUser *user.User, ver uint8, cmd uint16, message []byte, ...)
- func CancelReservation(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error
- func CancelReservationRemote(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool, ...)
- func ChangeTTL(roomID string, ttl int64) bool
- func DebugDataDump() []map[string]interface{}
- func DeleteRoom(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte)
- func EnableStateSync(roomID string, updateVer, removeVer uint8, updateCmd, removeCmd uint16, ...) bool
- func Exists(roomID string) bool
- func ExposeCommands()
- func ExposePufferCommands()
- func GetAllRoomIDsOnNode() []string
- func GetChatHistory(roomID string) [][]string
- func GetCreatedTime(roomID string) int64
- func GetMemberByID(roomID string, id string) *user.User
- func GetMemberIDs(roomID string) []string
- func GetMemberIDsAndOwner(roomID string) ([]string, string, string)
- func GetMemberSIDs(roomID string) []string
- func GetMemberSIDsAndOwner(roomID string) ([]string, string, string)
- func GetMemberUsers(roomID string) []*user.User
- func GetMemberUsersAndOwnerUser(roomID string) ([]*user.User, *user.User)
- func GetNumberOfRoomMembers(roomID string, callback func(err error, currentMembers int, maxMembers int))
- func GetProperties(roomID string) map[string]interface{}
- func GetProperty(roomID string, name string) interface{}
- func GetRemoteProperties(roomID string, cb func(err error, properties map[string]interface{}))
- func GetRemoteProperty(roomID string, name string, cb func(err error, property interface{}))
- func GetReservedUserIDs(roomID string) []string
- func GetRoomID(userData *user.User) string
- func GetRoomNodeAddressList(roomID string) ([]string, error)
- func GetRoomOwnerID(roomID string) string
- func IncrProperty(roomID string, propName string, delta int64) (int64, bool)
- func IsCancelReserveError(err error) bool
- func IsFailureError(err error) bool
- func IsJoinError(err error) bool
- func IsLeaveError(err error) bool
- func IsNewRoomError(err error) bool
- func IsReserveError(err error) bool
- func IsReserved(roomID string, uid string) bool
- func IsRoomFull(roomID string) bool
- func IsStateUpdateError(err error) bool
- func IsStateUpsertError(err error) bool
- func IsUserInRoom(roomID string, userData *user.User) bool
- func Join(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte, ...)
- func Leave(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte) error
- func Message(roomID string, memberIDs []string, senderUser *user.User, ver uint8, ...)
- func MigrateRoom(ver uint8, cmd uint16, userData *user.User, ...)
- func NewRoom(userData *user.User, maxMembers int, allowEmpty bool, join bool, ttl int64, ...) (string, error)
- func Relay(roomID string, sender *user.User, ver uint8, cmd uint16, message []byte, ...) bool
- func RelayTo(roomID string, sender *user.User, members []string, ver uint8, cmd uint16, ...) bool
- func RemoveStateByRoomID(roomID string, userData *user.User, key string, reliable bool) bool
- func Reserve(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error
- func SetChatHistoryLimit(roomID string, limit int) bool
- func SetJoinCondition(cond func(roomID string, userData *user.User) error)
- func SetOnAnnounce(roomID string, cb func(string, uint8, uint16, []byte)) bool
- func SetOnChatMessage(roomID string, callback func(*user.User, string) bool) bool
- func SetOnClock(roomID string, name string, interval int64, callback func(roomID string)) bool
- func SetOnClockStop(roomID string, name string, callback func(string)) bool
- func SetOnCustomUserDiscardByID(roomID string, ...) bool
- func SetOnDiscardCustomMessage(custom func(string, string, string) []byte) bool
- func SetOnJoinByID(roomID string, callback func(roomID string, userData *user.User) bool) bool
- func SetOnJoinCompleteByID(roomID string, callback func(roomID string, userData *user.User)) bool
- func SetOnLeaveByID(roomID string, callback func(roomID string, userData *user.User)) bool
- func SetOnMigrated(callback func(currentRoomID string, previousRoomID string))
- func SetOnRoomChange(cb func(string, int, []string, map[string]interface{})) bool
- func SetOnRoomChangeByID(roomID string, ...) bool
- func SetOnRoomDiscard(cb func(roomID string)) bool
- func SetOnRoomDiscardByID(roomID string, callback func(roomID string)) bool
- func SetOnRoomOwnerChange(cb func(roomID string, ownerID string))
- func SetOnRoomPropertyUpdate(cb func(roomID string, props map[string]interface{}))
- func SetOnTick(roomID string, callback func(string)) bool
- func SetOnTickStop(roomID string, callback func(string)) bool
- func SetProperty(roomID string, name string, value interface{}) bool
- func SetRollbackOnJoinFailureByID(roomID string, callback func(roomID string, userData *user.User)) bool
- func Setup()
- func SetupAsTCPServer()
- func SetupAsUDPServer()
- func SetupBackup(backupNum int)
- func SetupWithDive(confpath string)
- func StopClock(roomID string, name string) bool
- func StopTick(roomID string)
- func SyncAllStatesByRoomID(roomID string, userData *user.User, reliable bool) bool
- func SyncChatMessage(roomID string, userData *user.User, ver uint8, cmd uint16, message string) bool
- func SyncCreateTime(roomID string, ver uint8, cmd uint16, memberIDs []string)
- func UpdateProperties(roomID string, operation func(properties map[string]interface{}) bool) map[string]interface{}
- func UpdateStateByRoomID(roomID string, userData *user.User, key string, value []byte, ...) error
- func UpsertStateByRoomID(roomID string, userData *user.User, key string, reliable bool, ...) error
- type DataDump
- type GetRoomInfoData
- type JoinRoomCallback
- type Room
Constants
const MemberAdded = 1
MemberAdded is an enum flag for SetOnRoomChange callback to indicate that there is a new member added to the room
const MemberRemoved = 2
MemberRemoved is an enum flag for SetOnRoomChange callback to indicate that there is a member that has been removed from the room
const PropertyChanged = 3
PropertyChanged is an enum flag for SetOnRoomChange callback to indicate that one or more room properties have been changed
Functions
func AfterBroadcastRoomCmd
func AfterBroadcastRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterBroadcastRoomCmd registers a callback function to be executed after broadcast room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterCreateOrJoinByCustomIDCmd
func AfterCreateOrJoinByCustomIDCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterCreateOrJoinByCustomIDCmd registers a callback function to be executed after create or join by custom id:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterCreateRoomCmd
func AfterCreateRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterCreateRoomCmd registers a callback function to be executed after create room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterGetRoomPropCmd
func AfterGetRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterGetRoomPropCmd registers a callback function to be executed after get room properties:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterJoinRoomCmd
func AfterJoinRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterJoinRoomCmd registers a callback function to be executed after join room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterLeaveRoomCmd
func AfterLeaveRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterLeaveRoomCmd registers a callback function to be executed after leave room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterMessageExtendedRoomCmd
func AfterMessageExtendedRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterMessageExtendedRoomCmd registers a callback function to be executed after RoomMessageExtended:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterMessageRoomCmd
func AfterMessageRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterMessageRoomCmd registers a callback function to be executed after message room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func AfterUpdateRoomPropCmd
func AfterUpdateRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
AfterUpdateRoomPropCmd registers a callback function to be executed after update room properties:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func Announce
func Announce(roomID string, memberIDs []string, ver uint8, cmd uint16, message []byte, reliable bool)
Announce Sends a message to selected members to the room without having a "sender" - This function must NOT be called by user
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] All announce payloads have leading 4-byte-long header. The client must skip the first 4 bytes. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID. memberIDs - An array of member user IDs to send message to. senderUser - User to send broadcast. ver - Command version to be used as broadcast message. cmd - Command ID to be used as broadcast message. message - Message byte array. reliable - If true, UDP will be RUDP.
func BeforeBroadcastRoomCmd
func BeforeBroadcastRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeBroadcastRoomCmd registers a callback function to be executed before broadcast room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeCreateOrJoinByCustomIDCmd
func BeforeCreateOrJoinByCustomIDCmd(callback func(ver uint8, cmd uint16, payloa []byte, userData *user.User, next func(error)))
BeforeCreateOrJoinByCustomIDCmd registers a callback function to be executed before create or join by custom id:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeCreateRoomCmd
func BeforeCreateRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeCreateRoomCmd registers a callback function to be executed before create room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeGetRoomPropCmd
func BeforeGetRoomPropCmd(callback func(ver uint8, cmd uint16, payloa []byte, userData *user.User, next func(error)))
BeforeGetRoomPropCmd registers a callback function to be executed before get room properties:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeJoinRoomCmd
func BeforeJoinRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeJoinRoomCmd registers a callback function to be executed before join room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeLeaveRoomCmd
func BeforeLeaveRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeLeaveRoomCmd registers a callback function to be executed before leave room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeMessageExtendedRoomCmd
func BeforeMessageExtendedRoomCmd(callback func(ver uint8, cmd uint16, payloa []byte, userData *user.User, next func(error)))
BeforeMessageExtendedRoomCmd registers a callback function to be executed before RoomMessageExtended command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeMessageRoomCmd
func BeforeMessageRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeMessageRoomCmd registers a callback function to be executed before message room command:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func BeforeUpdateRoomPropCmd
func BeforeUpdateRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
BeforeUpdateRoomPropCmd registers a callback function to be executed before update room properties:
Must be called before ExposeCommands
Parameters
ver - Command ver sent from the client. cmd - Command ID sent from the client. payload - Command payload sent from the client. userData - User data representing the client that sent the command. next - The function to signal the command to move on to the next operation of the same ver and command ID. This function must be called at the end of all operations in the callback. If you pass an error, it will not proceed to the next operations of the same command ver and ID.
func Broadcast
func Broadcast(roomID string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)
Broadcast Sends a broadcast message to the other members in the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] Multiple broadcast payloads maybe combined and the client must parse the combined payloads BytesToBytesList of Diarkis client SDK. [IMPORTANT] Built-in events such as OnMemberBroadcast handles the separation of combined payloads internally, so the application does not need to handle it by using BytesToBytesList. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID. senderUser - User to send broadcast. ver - Command version to be used as broadcast message. cmd - Command ID to be used as broadcast message. message - Message byte array. reliable - If true, UDP will be RUDP.
func CancelReservation
func CancelReservation(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error
CancelReservation removes reservation per members
[IMPORTANT] This function does not work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Error Cases
┌───────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═══════════════════════════════╪════════════════════════════════════════════════════════════════════════════════╡ │ Room and/or its owner missing │ It is not possible to cancel reservations if room and/or its owner is missing. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Must be owner │ If mustBeOwner is true, only the room owner is allowed to cancel reservations. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Room not found │ Reservations cannot be canceled if the room is missing. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ No reservation │ Cannot cancel reservations if there is no reservation. │ └───────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsCancelReserveError(err error) // Failed to cancel a reservation of a room
Parameters
room ID - Target room ID to cancel a reservation. userData - Owner user to cancel the reservation. memberIDs - An array of user IDs to cancel the reservation for. mustBeOwner - If true userData must be the room owner
func CancelReservationRemote
func CancelReservationRemote(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool, cb func(error))
CancelReservationRemote removes reservation per members
[IMPORTANT] This function works even if the room is not on the same server. [IMPORTANT] The callback may be invoked on the server where the room is not held. Do not attempt to use functions that works only if the room is on the same server. [NOTE] This function is asynchronous.
Error Cases
┌───────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═══════════════════════════════╪════════════════════════════════════════════════════════════════════════════════╡ │ Room and/or its owner missing │ It is not possible to cancel reservations if room and/or its owner is missing. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Must be owner │ If mustBeOwner is true, only the room owner is allowed to cancel reservations. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Room not found │ Reservations cannot be canceled if the room is missing. │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ No reservation │ Cannot cancel reservations if there is no reservation. │ └───────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
Besides the following errors, there are Mesh module errors as well.
room.IsCancelReserveError(err error) // Failed to cancel a reservation of a room
Parameters
roomID - Target room ID to cancel a reservation. userData - Owner user to cancel the reservation. memberIDs - An array of user IDs to cancel the reservation for. mustBeOwner - If true userData must be the room owner. cb - Callback function to be invoked when the cancel operation is completed.
func ChangeTTL
func ChangeTTL(roomID string, ttl int64) bool
ChangeTTL changes TTL of the targeted room
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to change its TTL. ttl - New TTL of the room.
func DebugDataDump
func DebugDataDump() []map[string]interface{}
DebugDataDump returns an array of all rooms on the server.
[IMPORTANT] This is for debug purpose only.
func DeleteRoom
func DeleteRoom(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte)
DeleteRoom deletes the target room regardless of the room being not empty and sends notification message to its members.
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] All the members of the room will be automatically kicked out of the room. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to delete. userData - User that performs the deletion of the room. ver - Command version to send the notification as. cmd - Command ID to send the notification as. message - Message byte array to be sent to the members.
func EnableStateSync
func EnableStateSync( roomID string, updateVer, removeVer uint8, updateCmd, removeCmd uint16, syncInterval, syncAllDelay, ttl int64, combineLimit uint8) bool
EnableStateSync enables and starts state-based synchronization with its members.
All members of the room may update states via UpdateStateByRoomID and they will be synchronized at the interval (in milliseconds) given.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] You may enable reliable and unreliable state sync simultaneously. [IMPORTANT] If you migrate the room, you MUST use EnableStateSync again with the new roomID. [NOTE] Uses mutex lock internally.
Parameters
roomID - The target room ID of the room to enable sate synchronization. updateVer - Server push command version for property update used when the server sends updates to the member clients. removeVer - Server push command version for property removal used when the server sends removals to the member clients. updateCmd - Server push command ID for property update used when the server sends updates to the member clients. removeCmd - Server push command ID for property removal used when the user sends removals to the member clients. syncInterval - State propagation to all members is handled at a certain interval in milliseconds. syncInterval controls the interval in milliseconds for it. Minimum syncInterval value is 17 milliseconds. syncAllDelay - Delays the invocation of synchronization of all properties in milliseconds. Minimum syncAllDelay is 0 milliseconds. ttl - TTL of each state. If a state does not get updated for more than TTL, the property will be removed internally to save memory. TTL is in milliseconds and the minimum allowed value is 500. By passing TTL lower than the minimum value of 500, you will disable TTL function for properties. combineLimit - Maximum number of outbound synchronization packets to be combined per member. Default is 30.
func Exists
func Exists(roomID string) bool
Exists return true if the given room ID's room still exists
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to check if the room exists or not.
func ExposeCommands
func ExposeCommands()
ExposeCommands Exposes TCP or UDP/RUDP commands to execute room functions from the client
This function exposes the following commands to the client:
- Create Room
- Join Room
- Leave Room
- Broadcast To Room
- Send Message To Room Members
- Get and Update Room Properties
- Reserve Room
- Cancel Room Reservation
- Get Number of Room Members
- Room Migration
- Property Sync
- Propagate Latency
func ExposePufferCommands
func ExposePufferCommands()
ExposePufferCommands Exposes TCP or UDP/RUDP puffer commands to execute room functions from the client
This function exposes the following commands to the client:
- Create Room
- Join Room
- Leave Room
- Broadcast To Room
- Send Message To Room Members
- Get and Update Room Properties
- Reserve Room
- Cancel Room Reservation
- Get Number of Room Members
- Room Migration
- Property Sync
- Propagate Latency
func GetAllRoomIDsOnNode
func GetAllRoomIDsOnNode() []string
GetAllRoomIDsOnNode returns all valid room IDs on the current node
[NOTE] Uses mutex lock internally.
func GetChatHistory
func GetChatHistory(roomID string) [][]string
GetChatHistory returns chat history data as an array
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
func GetCreatedTime
func GetCreatedTime(roomID string) int64
GetCreatedTime returns the created time (in seconds) of the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
func GetMemberByID
func GetMemberByID(roomID string, id string) *user.User
GetMemberByID returns member user by room ID and user ID
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to get the member *user.User from. id - Target user ID to get *user.User of.
func GetMemberIDs
func GetMemberIDs(roomID string) []string
GetMemberIDs returns the list of member IDs (not SIDs)
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally for both room and user.
Parameters
roomID - Target room ID to get the list of member user IDs.
func GetMemberIDsAndOwner
func GetMemberIDsAndOwner(roomID string) ([]string, string, string)
GetMemberIDsAndOwner returns an array of all member IDs and owner ID and ownerSID
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally for both room and user.
Parameters
roomID - Target room ID to get the list of member user IDs and its owner user ID from. Returns member user IDs as an array, owner user ID, and owner user SID.
func GetMemberSIDs
func GetMemberSIDs(roomID string) []string
GetMemberSIDs returns the list of member SIDs
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to get a list of member SIDs.
func GetMemberSIDsAndOwner
func GetMemberSIDsAndOwner(roomID string) ([]string, string, string)
GetMemberSIDsAndOwner returns an array of all member IDs and owner ID and owner SID
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally for both room and user.
Parameters
roomID - Target room ID to get the list of member SIDs, owner user ID, and owner SID.
Returns an array of member user SIDs, owner user ID, and owner SID.
func GetMemberUsers
func GetMemberUsers(roomID string) []*user.User
GetMemberUsers returns the list of member user struct instances
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally. [NOTE] Returned *user.User may be nil if the user has disconnected.
Parameters
roomID - Target room ID to get the list of member userData.
func GetMemberUsersAndOwnerUser
func GetMemberUsersAndOwnerUser(roomID string) ([]*user.User, *user.User)
GetMemberUsersAndOwnerUser returns an array of all member IDs and owner ID
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally. [NOTE] Returned *user.User may be nil if the user has disconnected.
Parameters
roomID - Target room ID to get member *user.User and owner *user.User.
Returns member *user.User as an array and owner *user.User.
func GetNumberOfRoomMembers
func GetNumberOfRoomMembers(roomID string, callback func(err error, currentMembers int, maxMembers int))
GetNumberOfRoomMembers retrieves number of room members.
This can be executed by anyone and they do not have to be part of the room.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] This function works for all users including the users that are not members of the target room.
Parameters
roomID - Target room ID to get the number of members from. callback - Callback to be invoked when the number of current members and max members retrieved. func(err error, currentMembers int, maxMembers int)
func GetProperties
func GetProperties(roomID string) map[string]interface{}
GetProperties returns properties of a room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] The fetched property is of map[string]interface{} type. Make sure to use util.GetAsInt, util.GetAsBytes etc. [NOTE] Uses mutex lock internally.
Example
properties := room.GetProperties(roomID) counter, ok := util.GetAsInt(properties, "counter") if !ok { // incorrect data type or the value does not exist } message, ok := util.GetAsBytes(properties, "message") if !ok { // incorrect data type or the value does not exist } flag, ok := util.GetAsBool(properties, "flag") if !ok { // incorrect data type or the value does not exist }
Parameters
roomID - Target room ID of the properties.
func GetProperty
func GetProperty(roomID string, name string) interface{}
GetProperty returns a property of the given room and property name. Returns nil if not found.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] The fetched property is of interface{} type. Make sure to use util.ToInt, util.ToBytes etc. [NOTE] Uses mutex lock internally.
Example
property := room.GetProperty(roomID, "counter") // assuming "counter" is an int counter, ok := util.ToInt(property) if !ok { // incorrect data type or the value does not exist }
Parameters
roomID - Target room ID of the properties. name - Property name to retrieve.
func GetRemoteProperties
func GetRemoteProperties(roomID string, cb func(err error, properties map[string]interface{}))
GetRemoteProperties returns properties of a room
[IMPORTANT] This function works even if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] The fetched property is of map[string]interface{} type. Make sure to use util.GetAsInt, util.GetAsBytes etc. [IMPORTANT] The callback may be invoked on the server where the room is not held. Do not use functions that require the room to be on the same server. [NOTE] This function is asynchronous.
Example
room.GetRemoteProperties(roomID func(err error, properties map[string]interface{}) { if err != nil { // handle error here... } // assuming "counter" is an int counter, ok := util.GetAsInt(properties, "counter") if !ok { // incorrect data type of the value does not exist } message, ok := util.GetAsBytes(properties, "message") if !ok { // incorrect data type of the value does not exist } flag, ok := util.GetAsBool(properties, "bool") if !ok { // incorrect data type of the value does not exist } })
Parameters
roomID - Target room ID of the properties. cb - A callback to be invoked when the properties have been fetched.
func GetRemoteProperty
func GetRemoteProperty(roomID string, name string, cb func(err error, property interface{}))
GetRemoteProperty returns a property of the given room and property name. Returns nil if not found.
[IMPORTANT] This function works even if the room is not on the same server. [IMPORTANT] The fetched property is of interface{} type. Make sure to use util.ToInt, util.ToBytes etc. In order to read the data with the correct data type. [IMPORTANT] The callback may be invoked on the server where the room is not held. Do not use functions that require the room to be on the same server. [NOTE] This function asynchronous.
Operation example:
room.GetRemoteProperty(roomID, "counter", func(err error, property interface{}) { if err != nil { // handle error here... } // assuming "counter" is an int counter, ok := util.ToInt(property) if !ok { // incorrect data type or "counter" does not exist... } }) roomID - Target room ID of the properties. name - Property name to retrieve. cb - A callback to be invoked when the property has been fetched.
func GetReservedUserIDs
func GetReservedUserIDs(roomID string) []string
GetReservedUserIDs returns a list of user IDs that have reservations in the room.
[NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to get reservations.
func GetRoomID
func GetRoomID(userData *user.User) string
GetRoomID returns roomID that the user has joined
[IMPORTANT] This function can be used only on the server that the room exists. [NOTE] Uses mutex lock internally.
Parameters
userData - Target user to get the room ID that the user is currently member of.
func GetRoomNodeAddressList
func GetRoomNodeAddressList(roomID string) ([]string, error)
GetRoomNodeAddressList returns a list of internal node addresses that the room is stored
roomID - Target room ID to extract the server internal node addresses from.
Returns a list of server internal node addresses of the room and error if it fails.
func GetRoomOwnerID
func GetRoomOwnerID(roomID string) string
GetRoomOwnerID returns the user ID of the owner of the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to get the owner from.
func IncrProperty
func IncrProperty(roomID string, propName string, delta int64) (int64, bool)
IncrProperty increments int64 property by given delta and returns the incremented value.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function DOES update room's internal TTL.
If the property does not exist, it creates the property.
[NOTE] Uses mutex lock internally.
Cases for return value false
┌──────────────────┬──────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞══════════════════╪══════════════════════════════════════════════════════╡ │ Room not found │ Either invalid room ID given or room does not exist. │ │ Property Corrupt │ Target property data type is not int64. │ └──────────────────┴──────────────────────────────────────────────────────┘
Parameters
roomID - Target room ID. propName - Target property name. delta - Delta value to increment by.
Usage Example
updatedHP, updated := room.IncrProperty(roomID, "HP", damage)
func IsCancelReserveError
func IsCancelReserveError(err error) bool
IsCancelReserveError returns true if the given error is or contains a RoomCancelReserveError.
func IsFailureError
func IsFailureError(err error) bool
IsFailureError returns true if the given error is or contains a generic RoomFailureError.
func IsJoinError
func IsJoinError(err error) bool
IsJoinError returns true if the given error is or contains a RoomJoinError.
func IsLeaveError
func IsLeaveError(err error) bool
IsLeaveError returns true if the given error is or contains a RoomLeaveError.
func IsNewRoomError
func IsNewRoomError(err error) bool
IsNewRoomError returns true if the given error is or contains a RoomNewError.
func IsReserveError
func IsReserveError(err error) bool
IsReserveError returns true if the given error is or contains a RoomReserveError.
func IsReserved
func IsReserved(roomID string, uid string) bool
IsReserved returns true if the given uid (User ID) has a reservation with the given room.
[NOTE] Uses mutex lock internally.
func IsRoomFull
func IsRoomFull(roomID string) bool
IsRoomFull returns true if the room is full.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to check.
func IsStateUpdateError
func IsStateUpdateError(err error) bool
IsStateUpdateError returns true if the given error is or contains a RoomStateUpdateError.
func IsStateUpsertError
func IsStateUpsertError(err error) bool
IsStateUpsertError returns true if the given error is or contains a RoomStateUpsertError.
func IsUserInRoom
func IsUserInRoom(roomID string, userData *user.User) bool
IsUserInRoom returns true if the user is in the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID to check. userData - Target user to see if the user is in the room.
func Join
func Join(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback JoinRoomCallback)
Join joins a room and notify the other members of the room on joining the room.
[NOTE] Uses mutex lock internally. [NOTE] If message is empty, Broadcast will not be sent. [NOTE] This function is asynchronous. What this means is that it involves server-to-server communication internally. [IMPORTANT] The room to join may not be on the same server process and if that is the case, the client will move to where the room is. That means the client will re-connect to a different Diarkis server in the Diarkis cluster. This is handled by Diarkis client SDK. The join will be completed when the user successfully changes the server. [IMPORTANT] The callback is called on the original server that the user client is connected to and the room to join may not be on the same server. Please do not read and/or write room properties in the callback as the room may not be accessible and creates a bug in your application code. Do not use functions that require the room to be on the same server to work. [IMPORTANT] This function works even if the room is on a different server.
Error Cases
┌─────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═════════════════════════════════════════╪════════════════════════════════════════════════════════════════════════════════╡ │ User is already in another room │ The user is not allowed to join more than one room at a time. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Node of room not found │ Server of the room is not available in the Diarkis cluster. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Failed to transfer user │ Transferring the user to the server of the room failed. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Room not found │ Room to join not found. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Room join rejected │ SetOnJoinByID and/or SetJoinCondition callback(s) rejected the user to join. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ Cannot join room │ The room is at capacity, or all remaining slots have pending reservations. │ ├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤ │ User is already in the room │ The user is already in the room. │ └─────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
Besides the following errors, there are Mesh module errors as well.
room.IsJoinError(err error) // Failed to join a room
Parameters
roomID - Target room ID to join. userData - User to join the room. ver - Command version to be used for successful join message sent to other room members. cmd - Command ID to be used for successful join message sent to other room members. message - Message byte array to be sent as successful message to other room members. If message is either nil or empty, the message will not be sent. callback - Callback to be invoked when join operation completes (both success and failure). [IMPORTANT] When the user needs to re-connect, the callback is invoked BEFORE the re-connect. In order to capture the actual completion of joining the room, use room.SetOnJoinCompleteByID.
Packets sent from the server for join
Join operation on the server may send multiple packets to the client.
Here are the details on each packet sent from the server and their order.
▶︎ Re-connect instruction push
This packet is sent from the server when the server requires the client to re-connect to another server.
▶︎ On join response
This packet is always sent from the server when join operation is completed.
ver = 1 cmd = 101
Command ver and ID for on join packet is as shown above:
Order of packets from the server and join callback
▶︎ With re-connect instruction:
Join request → Re-connect instruction push → On join response → On member join push
┌──────────────────────────┐ ┌──────────────────┐ │ UDP/TCP server A │ │ UDP/TCP server B │──────────────┐ └──────────────────────────┘ └──────────────────┘ │ ▲ │ │ │ <1> Join request │ │ │ │ │ │ <2> Re-connect instruction push │ │ │ │ │ <3> On join response │ ╭────────╮◀︎───┘ │ │ <4> On member join push │ Client │◀︎───────────────────────────────────────┘ │ ╰────────╯◀︎───────────────────────────────────────────────────────────────────┤ ╭────────╮╮╮ │ Other room members│ Client │││◀︎───────────────────────────────────────────────────────────┘ ╰────────╯╯╯
▶︎ Without re-connect instruction:
Join request → On join response → On member join push
┌────────────────────────────────────┐ ┌─▶︎ │ UDP/TCP server A │────┐ │ └────────────────────────────────────┘ │ │ │ │ │ <1> Join request │ │ │ │ <2> On join response │ │ ▼ │ <3> On member join push │ ╭────────╮ │ └──────────────────│ Client │◀︎────────────────┤ ╰────────╯ │ ╭────────╮╮╮ │ Other room members│ Client │││◀︎──────────────┘ ╰────────╯╯╯
The order of packet and callback change when re-connect or not.
Callback and Server Location
When the user joins a room that exists on a different server, the client is required to re-connect to the server where the room is. Diarkis handles this internally, but it is useful to understand the mechanism behind it.
The diagram below shows the sequence of operations and callbacks as well as where they are executed.
The number in <> indicates the order of execution of callbacks and operations.
┌──────────────────┐ ┌────────────────────────┐ <7> On member join push waits for on join response │ UDP/TCP server A │ │ UDP/TCP server B │─────────────────────────────────────┐ │ │ <2> Join operation │ │ │ │ │─────────────────────▶︎│ │ <6> On join response waits for │ │ │ │ │ SetOnJoinCompleteByID execution │ │ │◀︎─────────────────────│ [ Room A exists here ] │─────────────────────────────┐ │ └──────────────────┘ <3> Join operation └────────────────────────┘ │ │ ▲ callback is ▲ <5> Callback of SetOnJoinCompleteByID is │ │ │ executed on server A │ executed on server B │ │ │ │ │ │ │ <1> Join request │ <4> Re-connect │ │ │ │ Client re-connects to where the room is │ │ ╭────────╮ │ │ │ │ Client │────────────────────────────────────┘ │ │ ╰────────╯◀︎──────────────────────────────────────────────────────────────────────────────────┘ │ ▲ │ │ │ └────────────────────────────────────────────────────────────────────────────────────────────────┤ ╭────────╮╮╮ │ Other room members│ Client │││◀︎─────────────────────────────────────────────────────────────────────────┘ ╰────────╯╯╯
Join Sequences
Join operation and its sequences are different when the room to join is on the same server or on a different server.
▶︎ Same Server Join
The sequence below is join operation sequence where the room is on the same server as the user. [ Room is here ] ╭────────╮ ┌──────────┐ │ Client │ │ Server A │ ╰────────╯ └──────────┘ │ │ ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Join Request ] │ │ │ [ room.SetJoinCondition ] │ │ │ ┌────────┴───┐ │ │ │ [ Join Failure Response ]◀︎━━━━━[ Room Join Failed ] │ --- ( JoinRoomCallback ) │ │ │ │ │ │ │ [ room.SetOnJoinByID ] │ │ │ ┌────────┴───┐ │ │ │ [ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━[ Room Join Failed ] │ --- ( JoinRoomCallback ) │ │ │ │ │ [ Reservation Check ] │ │ │ ┌────────┴───┐ │ │ │ [ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ] │ --- ( JoinRoomCallback ) │ │ │ [ room.SetOnJoinByID ] │ │ │ ┌────────┴───┐ │ │ │ [ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ] │ --- ( JoinRoomCallback ) │ │ │ [ room.SetOnRoomChange ] │ │ │ [ room.SetOnJoinCompleteByID ] │ │ │ [ Join Success ] --- ( JoinRoomCallback ) │ │ [ On Join Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ │ │ [ On Member Join ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ On Member Join will be sent to all members. │ │ ▽ ▽
▶︎ Remote Server Join
The sequence below is the operation sequence where the room is on a different server from the user. [ Room is here ] ╭────────╮ ┌──────────┐ ┌──────────┐ │ Client │ │ Server A │ │ Server B │ ╰────────╯ └──────────┘ └──────────┘ │ │ │ ┝━━━━━━━━▶︎[ Join Request ] │ │ │ │ │ ├────────▶︎[ Join Request ] │ │ │ │ │ [ room.SetJoinCondition ] │ │ │ │ │ ┌───┴───┐ │ │ │ │ │ [ Join Failure ]◀︎─────┘ │ --- ( JoinRoomCallback ) on Server A │ │ │ [ Join Failure Response ]◀︎━━━━┥ │ │ │ │ │ │ [ room.SetOnJoinByID ] │ │ │ │ │ ┌───┴───┐ │ │ │ │ │ [ Join Failure ]◀︎─────────┘ │ --- ( JoinRoomCallback ) on Server A │ │ │ [ Join Failure Response ]◀︎━━━━┥ │ │ │ │ │ │ [ Reservation Check ] │ │ │ │ │ ┌───┴───┐ │ │ │ │ │ [ Join Failure ]◀︎─────────────┘ │ --- ( JoinRoomCallback ) on Server A │ │ │ [ Join Failure Response ]◀︎━━━━┥ │ │ │ │ │ │ [ room.SetOnJoinByID ] │ │ │ │ │ ┌───┴───┐ │ │ │ │ │ [ Join Failure ]◀︎─────────────────┘ │ --- ( JoinRoomCallback ) on Server A │ │ │ [ Join Failure Response ]◀︎━━━━┥ │ │ │ │ │ │ [ room.SetOnRoomChange ] │ │ │ │ [ Join Success ]◀︎────────────────────────┤ --- ( JoinRoomCallback ) on Server A │ │ │ [ Re-connect Instruction ]◀︎━━━┥ Disconnect from Server A. │ │ │ │ ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ] │ │ │ [ On Connect ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ │ │ │ │ │ [ room.SetOnJoinCompleteByID ] │ │ │ │ │ [ Join Success ] │ │ │ [ On Join Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ │ │ │ [ On Member Join ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ On Member Join will be sent to all members. │ │ │ ▽ ▽ ▽
func Leave
func Leave(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte) error
Leave Leaves from a room and notify the other members on leaving. If message is empty Broadcast will not be sent.
[NOTE] Uses mutex lock internally. [IMPORTANT] This function does not work if the room is not on the same server. [IMPORTANT] When a member user of a room disconnects unexpectedly, the room will automatically detect the leave of the user and sends on leave message to the reset of the member users. The message contains room ID and the user ID that disconnected. In order to have custom message for this behavior, use SetOnDiscardCustomMessage.
Error Cases
┌──────────────────────────┬─────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞══════════════════════════╪═════════════════════════════════════════════════════╡ │ Room not found │ Room to leave from is not found. │ ├──────────────────────────┼─────────────────────────────────────────────────────┤ │ The user is not a member │ The user is not a member of the room to leave from. │ └──────────────────────────┴─────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsLeaveError(err error) // Failed to leave from a room
Parameters
roomID string - Target room ID to leave from. userData *user.User - User that will be leaving the room. ver uint8 - Command version to be used for message sent when leave is successful. cmd uint16 - Command ID to be used for message sent when leave is successful. message []byte - Message byte array to be sent as successful message to other room members. If message is either nil or empty, the message will not be sent.
func Message
func Message(roomID string, memberIDs []string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)
Message Sends a message to selected members of the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] All message payloads have leading 4-byte-long header. The client must skip the first 4 bytes. [IMPORTANT] Built-in events such as OnMemberMessage handles the separation of combined payloads internally, so the application does not need to handle it by using BytesToBytesList. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID. memberIDs - An array of member user IDs to send message to. senderUser - User to send broadcast. ver - Command version to be used as broadcast message. cmd - Command ID to be used as broadcast message. message - Message byte array. reliable - If true, UDP will be RUDP.
func MigrateRoom
func MigrateRoom(ver uint8, cmd uint16, userData *user.User, callback func(err error, newRoomID string, oldRoomID string))
MigrateRoom migrates a room to another node and moves its members to the new room.
This is intended to be used when the current node is about to shutdown (in offline state), but you need to keep the current room.
[IMPORTANT] This function does not work if the room is not on the same server. [IMPORTANT] Migration will change the room ID. [IMPORTANT] The callback may be invoked on the server where the room is not held. Do not use functions that requires the room to be on the same server. [NOTE] Uses mutex lock internally. [NOTE] This function is asynchronous.
Error Cases
┌─────────────────────────────────────────┬────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═════════════════════════════════════════╪════════════════════════════════════════════════════════════════════╡ │ Node (server) to migrate room not found │ The server to migrate the room to is not found. │ │ User must be provided │ Given user must be a valid user. │ │ User must not be a blank user │ Given user must not be a blank user. │ │ Must be owner │ Only the room owner is allowed to perform room migration. │ │ User transfer failed │ The owner user failed to transfer to another server for migration. │ └─────────────────────────────────────────┴────────────────────────────────────────────────────────────────────┘
Parameters
ver - Command ver to send the new migrated room ID to all members as migration instruction. cmd - Command ID to send the new migrated room ID to all members as migration instruction. userData - Owner user to perform the migration. The user passed to this function must be a valid user that is also the owner of the room. callback - Invoked when migration operation is completed.
When a room is migrated to another server, the users of the room will be re-connected to the server where the room is migrated. This is handled by Diarkis internally, but it is useful to understand the mechanism of it.
The diagram below shows the sequence of operations and callbacks as well as where they are executed.
The number in < > indicates the order of execution of callbacks and operations.
┌────────────────────────┐ ┌────────────────────────┐ │ UDP/TCP server A │ <2> Migrate │ UDP TCP server B │ │ │──────────────────▶︎│ │ │ [ Room A exists here ] │ │ [ Room A migrated ] │ <3> SetOnMigrated is executed on server B │ │ │ │ Re-join will take place └────────────────────────┘ └────────────────────────┘ AFTER the execution of SetOnMigrated ▲ │ ▲ │ └───────────┐ │ │ <1> Migrate │ │ <5> Re-join: │ │ │ Each member must leave the previous room (room before the migration) and │ │ │ join the new migrated room by the room ID pushed from the server. │ │ │ (All members of the room will reconnect asynchronously) │ ┌───────────────┘ │ │ │ <4> New migrated room ID notification │ │ │ (All members of the room will receive │ │ │ the new migrated room ID asynchronously) │ │ ▼ │ ╭────────╮ │ │ Client │───────────────────────────────────────────────────┘ ╰────────╯(Client re-connects to where the migrated room is via executing Join)
Owner user:
The owner of the room will NOT receive on join event response (cmd:101) from the server. Instead, the owner will receive on migration complete event push (cmd:20) from the server when the owner user completes the server re-connection.
╭────────╮ ┌──────────┐ ┌──────────┐ │ Client │ │ Server A │ │ Server B │ ╰────────╯ └──────────┘ └──────────┘ │ │ │ ┝━━━━━━━━━━━━━━━━━▶︎[ Migration Request ] │ │ │ │ │ ├───────────▶︎[ Migration ] Room is copied here with the new room ID. │ │ │ │ │ [ SetOnMigrated Callback Invoked ] │ │ │ │ [ Migration Confirmation ]◀︎───────┤ │ │ │ [ Migration Instruction ]◀︎━━━━━━━━┥(ver: custom) │ Migration Instruction contains the new room ID. │ │(cmd: custom) │ │ │ │ ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ] │ The user leaves the previous room. │ │ │ │ │ │ [ Leave Confirmation ]◀︎━━━━━━━━━━━┥ │ │ │ │ ┝━━━━━━━▶︎[ Join Request To Migrated Room ] │ The user joins the new migrated room. │ │ │ │ ├────────────▶︎[ Join ] │ │ │ │ [ Join Confirmation ]◀︎─────────┤ │ │ │ [ Re-connect Instruction ]◀︎━━━━━━━┥ │ │ │ │ ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ] │ │ │ │ │ │ [ Migration Confirmation ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━┥ For owner user: cmd=20 on migration complete │ │ │ ▽ ▽ ▽
Non-owner user:
Non-owner user WILL receive on join event response (cmd:101) from the server when completing the server re-connection.
╭────────╮ ┌──────────┐ ┌──────────┐ │ Client │ │ Server A │ │ Server B │ ╰────────╯ └──────────┘ └──────────┘ │ │ │ ┝━━━━━━━━━━━━━━━━━▶︎[ Migration Request ] │ │ │ │ │ ├───────────▶︎[ Migration ] Room is copied here with the new room ID. │ │ │ │ │ [ SetOnMigrated Callback Invoked ] │ │ │ │ [ Migration Confirmation ]◀︎───────┤ │ │ │ [ Migration Instruction ]◀︎━━━━━━━━┥(ver: custom) │ Migration Instruction contains the new room ID. │ │(cmd: custom) │ │ │ │ ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ] │ The user leaves the previous room. │ │ │ │ │ │ [ Leave Confirmation ]◀︎━━━━━━━━━━━┥ │ │ │ │ ┝━━━━━━━▶︎[ Join Request To Migrated Room ] │ The user joins the new migrated room. │ │ │ │ ├────────────▶︎[ Join ] │ │ │ │ [ Join Confirmation ]◀︎─────────┤ │ │ │ [ Re-connect Instruction ]◀︎━━━━━━━┥ │ │ │ │ ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ] │ │ │ │ │ │ [ Join Confirmation ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ Treat join confirmation as migration confirmation. │ │ │ ▽ ▽ ▽
func NewRoom
func NewRoom(userData *user.User, maxMembers int, allowEmpty bool, join bool, ttl int64, interval int64) (string, error)
NewRoom Creates a new room
[NOTE] Uses mutex lock internally. [NOTE] This function creates a new room on the same server as it is invoked.
Error Cases:
┌─────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═════════════════════════════════════╪══════════════════════════════════════════════════════════════════════════════╡ │ allowEmpty and join are false │ If allowEmpty and join are both false, the room will be deleted immediately. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Server is offline │ The server is in offline state (getting ready to shutdown) │ │ │ and creating new rooms is not allowed. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Invalid TTL │ TTL must be greater than 0 second. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Incorrect parameters for blank user │ Using a blank user must have allowEmpty=true and join=false parameters. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ User in another room │ You may not join more than one room at a time. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Max member is invalid │ The range of max member is from 2 to 1000. │ └─────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsNewRoomError(err error) // Room module failed to create a new room
Parameters
userData - User data struct. If you do not have user available, you may use a dummy user created by user.CreateBlankUser. Using a dummy user allows you to create an empty room without having the access to a user. With a dummy user, you must have allowEmpty=true, join=false. maxMembers - Maximum number of members allowed to join the room allowEmpty - If true, the room will not be deleted until TTL expires even if all members leave join - If true, the creator user will join the room automatically ttl - TTL of the room when it is empty in seconds. The value must be greater than 0. Minimum is 10 seconds interval - Broadcast interval in milliseconds. Interval below 100ms will be forced to 0. If it's 0, no packet merge
func Relay
func Relay(roomID string, sender *user.User, ver uint8, cmd uint16, message []byte, reliable bool) bool
Relay sends a message to all members of the room except for the sender.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] Unlike Broadcast, Message, and Announce, Relay does not combine multiple messages. Therefore, the message sent does not have to be separated by BytesToBytesList on the client side. [IMPORTANT] Unlike Broadcast, Message, and Announce, Relay does not send the message to the sender user. [NOTE] Uses mutex lock internally.
Parameters
roomID - Room ID of the room to send relay message to. sender - Sender user. The sender user must be a member of the room. ver - Command version of the message sent to the members of the room. cmd - Command ID of the message sent to the members of the room. message - Message to be sent to the members of the room. reliable - If true, the message will be sent as an RUDP if the network protocol is UDP. If the network protocol used is TCP, this flag is ignored.
func RelayTo
func RelayTo(roomID string, sender *user.User, members []string, ver uint8, cmd uint16, message []byte, reliable bool) bool
RelayTo sends a message to selected members of the room except for the sender.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] Unlike Broadcast, Message, and Announce, RelayTo does not combine multiple messages. Therefore, the message sent does not have to be separated by BytesToBytesList on the client side. [IMPORTANT] Unlike Broadcast, Message, and Announce, Relay does not send the message to the sender user. [NOTE] Uses mutex lock internally.
Parameters
roomID - Room ID of the room to send relay message to. sender - Sender user. The sender user must be a member of the room. members - An array of target member user IDs to send relay message to. ver - Command version of the message sent to the members of the room. cmd - Command ID of the message sent to the members of the room. message - Message to be sent to the members of the room. reliable - If true, the message will be sent as an RUDP if the network protocol is UDP. If the network protocol used is TCP, this flag is ignored.
func RemoveStateByRoomID
func RemoveStateByRoomID(roomID string, userData *user.User, key string, reliable bool) bool
RemoveStateByRoomID removes a state property and synchronize its removal to all members of the room.
ver and cmd will be used as command ver and command ID when synchronizing with the room members.
User must be a member of the room to use this function.
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Parameters
roomID - The target room ID of the room to remove a state from. userData - Room member user to perform state removal. key - State key to be removed. reliable - If true, synchronization for UDP communication will be RUDP.
func Reserve
func Reserve(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error
Reserve the user may reserve a slot in a room so that it will be guaranteed to join the room later.
[IMPORTANT] This function does not work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Error Cases
┌──────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞══════════════════════════════╪══════════════════════════════════════════════════════════════════════════════╡ │ memberIDs array is empty │ No member IDs to make reservations with. │ ├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Room or room owner not found │ Cannot make a reservation if the room and/or its owner is missing. │ ├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Must be owner │ If mustBeOwner is true, only the room owner is allowed to make reservations. │ ├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Room not found │ Cannot make a reservation if the room is missing. │ ├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Exceeds max members │ Make reservations that exceeds max members of the room is not allowed. │ ├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤ │ Reservation is full │ There is no more room for reservations. │ └──────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsReserveError(err error) // Failed to make a reservation of a room
Parameters
roomID - Target room ID to make a reservation. userData - Owner user of the room to make a reservation. memberIDs - An array of user IDs to make a reservation for. mustBeOwner - If true, userData must be the owner of the room.
func SetChatHistoryLimit
func SetChatHistoryLimit(roomID string, limit int) bool
SetChatHistoryLimit sets the chat history maximum length
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
func SetJoinCondition
func SetJoinCondition(cond func(roomID string, userData *user.User) error)
SetJoinCondition registers a condition function to control room join. Returning an error will cause room join to fail
Join condition is NOT protected by mutex lock.
SetJoinCondition(condition func(roomID string, userData *user.User)) cond func(roomID string, userData *user.User) error - Custom function to be invoked before room join to evaluate join conditions.
func SetOnAnnounce
func SetOnAnnounce(roomID string, cb func(string, uint8, uint16, []byte)) bool
SetOnAnnounce assigns a listener callback on Announce of room
[CRITICALLY 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 function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally. [NOTE] ver and cmd passed to the callback are the ver and cmd used to send Broadcast or Message.
It captures Broadcast and Message as well
roomID string - Target room ID. cb - func(roomID, ver uint8, cmd uint16, message []byte) - Callback to be invoked on every Broadcast and Message. Usage Example: Useful when capturing and sending the message data to external database or service.
func SetOnChatMessage
func SetOnChatMessage(roomID string, callback func(*user.User, string) bool) bool
SetOnChatMessage assigns a callback to be invoked before synchronizing a chat message.
[CRITICALLY 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 function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Return false will reject the incoming chat message and rejected chat message will NOT be sent to other members.
func SetOnClock
func SetOnClock(roomID string, name string, interval int64, callback func(roomID string)) bool
SetOnClock assigns a custom callback to be invoked at a given interval until it is stopped by ClockStop callback
[CRITICALLY 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. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID of the room to have a clock callback loop name - Unique name of the clock callback. Duplicates will be ignored interval - Clock interval in seconds callback - Callback function to be invoked
func SetOnClockStop
func SetOnClockStop(roomID string, name string, callback func(string)) bool
SetOnClockStop assigns a callback to be invoked when a clock callback is stopped by StopClock
[CRITICALLY 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. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID of the room to stop the clock callback name - Unique name of the clock to stop callback - Callback function to be invoked when clock is stopped by StopClock
func SetOnCustomUserDiscardByID
func SetOnCustomUserDiscardByID(roomID string, callback func(roomID string, userData *user.User) (uint8, uint16, []byte)) bool
SetOnCustomUserDiscardByID registers a callback to be executed when a room member disconnects unexpected.
[CRITICALLY 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. [CRITICALLY IMPORTANT] If the callback blocks, it will NOT allow the room to execute Leave when the user is disconnected. [NOTE] Uses mutex lock internally.
The purpose of this callback is to use custom command ver, cmd, and message data to be sent to other members.
func SetOnDiscardCustomMessage
func SetOnDiscardCustomMessage(custom func(string, string, string) []byte) bool
SetOnDiscardCustomMessage sets a custom function to create a custom message on user discard to be sent to members The callback receives roomID string, user ID string, user SID string
[CRITICALLY 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. custom func(roomID string, userID string, userSID string) []byte - Custom function to create a custom message byte array to be sent to other members. When the member client disconnects and leave.
func SetOnJoinByID
func SetOnJoinByID(roomID string, callback func(roomID string, userData *user.User) bool) bool
SetOnJoinByID registers a callback to be executed just before the join operation to evaluate, if the user should join or not.
[CRITICALLY 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. [CRITICALLY IMPORTANT] If the callback blocks, the room will NOT execute Join that follows. [NOTE] Uses mutex lock internally.
Returning value false will cause the join operation to fail.
When joining a room that is on a different server, the client is required to re-connect to the server where the room is. This is handle by Diarkis internally.
Diagram below shows where the callback of SetOnJoinByID is executed.
┌──────────────────┐ ┌────────────────────────┐ │ UDP/TCP server A │ <2> Join │ UDP/TCP server B │ │ │───────────▶︎│ [ Room A exists here ] │ └──────────────────┘ └────────────────────────┘ ▲ <3> Callback of SetOnJoinByID is executed on server B │ │ <1> Join │ ╭────────╮ │ Client │ ╰────────╯
func SetOnJoinCompleteByID
func SetOnJoinCompleteByID(roomID string, callback func(roomID string, userData *user.User)) bool
SetOnJoinCompleteByID registers a callback on join operation complete.
[CRITICALLY 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. [NOTE] Uses mutex lock internally.
Joining a room that requires server re-connect
When joining a room that is on a different server, the client is required to re-connect to the server where the room is. This is handle by Diarkis internally.
Where SetOnJoinCompleteByID callback is executed
The diagram below explains where the callback of SetOnJoinCompleteByID is executed when the client re-connects:
The number in < > indicates the order of execution of callbacks and operations.
┌──────────────────┐ ┌────────────────────────┐ │ UDP/TCP server A │ <2> Join │ UDP/TCP server B │ │ │───────────▶︎│ [ Room A exists here ] │ └──────────────────┘ └────────────────────────┘ ▲ ▲ <4> Callback of SetOnJoinCompleteByID is on server B │ │ │ <1> Join │ <3> Re-connect │ │ ╭────────╮ │ │ Client │────────────────────────────────┘ ╰────────╯ Client re-connects to where the room is SetOnJoinCompleteByID waits until the client completes re-connection to the new server and finishes the join operation.
func SetOnLeaveByID
func SetOnLeaveByID(roomID string, callback func(roomID string, userData *user.User)) bool
SetOnLeaveByID registers a callback on leave
[CRITICALLY 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. [CRITICALLY IMPORTANT] The callbacks are invoked in room.Leave function. If a callback blocks, room.Leave will block also. [NOTE] Uses mutex lock internally.
func SetOnMigrated
func SetOnMigrated(callback func(currentRoomID string, previousRoomID string))
SetOnMigrated registers a callback on migrated. The callbacks will be invoked on the server node where the room is migrated to
[CRITICALLY 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. callback - A callback to be invoked when migration is successful.
func SetOnRoomChange
func SetOnRoomChange(cb func(string, int, []string, map[string]interface{})) bool
SetOnRoomChange registers a callback function on room change such as create, join, leave, property updates
[CRITICALLY 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 function does NOT work if the room is not on the same server.
Parameters
cb - Callback cb func(roomID string, changeEvent int, memberUserIDs []string, roomProperties map[string]interface{}) changeEvent is an enum value that tells us what change took place: room.MemberAdded, room.MemberRemoved, room.PropertyChanged
func SetOnRoomChangeByID
func SetOnRoomChangeByID(roomID string, cb func(roomID string, changeEvent int, memberIDs []string, properties map[string]interface{})) bool
SetOnRoomChangeByID registers a callback function on room change such as create, join, leave, property updates
[CRITICALLY 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 function does NOT work if the room is not on the same server. changeEvent is an enum value that tells us what change took place: room.MemberAdded, room.MemberRemoved, room.PropertyChanged cb func(roomID string, changeEvent int, memberUserIDs []string, roomProperties map[string]interface{})
func SetOnRoomDiscard
func SetOnRoomDiscard(cb func(roomID string)) bool
SetOnRoomDiscard registers a callback function on room deletions
[CRITICALLY 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. cb func(roomID string) - Function to be invoked on room's deletion.
func SetOnRoomDiscardByID
func SetOnRoomDiscardByID(roomID string, callback func(roomID string)) bool
SetOnRoomDiscardByID registers a callback on room deletion by room ID
[CRITICALLY 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 function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
func SetOnRoomOwnerChange
func SetOnRoomOwnerChange(cb func(roomID string, ownerID string))
SetOnRoomOwnerChange sets a callback for room owner change
[CRITICALLY 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 function does NOT work if the room is not on the same server. [IMPORTANT] The owner ID may be an empty string. [NOTE] Uses mutex lock internally.
Parameters
cb func(roomID string, ownerID string) - Callback to be invoked when the room owner changes.
func SetOnRoomPropertyUpdate
func SetOnRoomPropertyUpdate(cb func(roomID string, props map[string]interface{}))
SetOnRoomPropertyUpdate sets a callback for room property updates.
[CRITICALLY 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 function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Parameters
cb func(roomID string, properties map[string]interface{}) - Callback to be invoked when room property changes.
func SetOnTick
func SetOnTick(roomID string, callback func(string)) bool
SetOnTick registers a callback on every 5 seconds tick on a room
[CRITICALLY 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] If you access room properties in the callback, it updates the TTL of the room internally. It means that as long as the callback keeps accessing the properties, it will keep the room from being deleted beyond its TTL. [NOTE] Uses mutex lock internally.
Parameters
roomID string - Target room ID to set a tick callback. callback func(roomID string) - Callback to be invoked at every tick.
Usage Example: Use this to call matching.Add so that you may keep the room available for matchmaking as long as you with.
func SetOnTickStop
func SetOnTickStop(roomID string, callback func(string)) bool
SetOnTickStop assigns a callback to be invoked when room tick stops
[CRITICALLY 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. [NOTE] Uses mutex lock internally.
Parameters
roomID string - Target room ID callback func(string) - Callback to be invoked on tick stop. The callback passes roomID
func SetProperty
func SetProperty(roomID string, name string, value interface{}) bool
SetProperty assigns a value to the target room associated with the given name. If the property already exists, it will overwrite it.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] Room properties do NOT support structs. [IMPORTANT] Numeric properties will be float64. Use util.ToInt, ToUint etc. To convert to proper data type. [IMPORTANT] Array properties will be []interface{}. Must apply type assertion per element. [IMPORTANT] Byte array properties will be converted to base64 encoded string. Use util.ToBytes() to convert it back. [NOTE] If there is a value associated with the name, the value will be replace. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID name - Property name to set the value as value - Property value to be associated with the name
func SetRollbackOnJoinFailureByID
func SetRollbackOnJoinFailureByID(roomID string, callback func(roomID string, userData *user.User)) bool
SetRollbackOnJoinFailureByID registers a callback to perform rollback operations on join failure
[NOTE] Uses mutex lock internally.
func Setup
func Setup()
Setup Sets up room package but without any server association
func SetupAsTCPServer
func SetupAsTCPServer()
SetupAsTCPServer Sets up room package
func SetupAsUDPServer
func SetupAsUDPServer()
SetupAsUDPServer Sets up room package
func SetupBackup
func SetupBackup(backupNum int)
SetupBackup Enables room data backup to different nodes - maximum backup nodes you can set is 2
backupNum int - Number of backup servers.
func SetupWithDive
func SetupWithDive(confpath string)
SetupWithDive must be called in the server main function to setup room module before diarkis.Start
func StopClock
func StopClock(roomID string, name string) bool
StopClock stops a clock callback loop
[NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID of the room to stop the clock callback name - Unique name of the clock to stop
func StopTick
func StopTick(roomID string)
StopTick stops room's tick event loop
[NOTE] Uses mutex lock internally.
func SyncAllStatesByRoomID
func SyncAllStatesByRoomID(roomID string, userData *user.User, reliable bool) bool
SyncAllStatesByRoomID synchronizes all existing states to the target user client.
Invoking this function will forcefully send all existing states to the targeted user client.
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Parameters
roomID - The target room ID of the room. userData - Room member user to receive all state synchronizations. reliable - If true, synchronization for UDP communication will be RUDP.
func SyncChatMessage
func SyncChatMessage(roomID string, userData *user.User, ver uint8, cmd uint16, message string) bool
SyncChatMessage records the chat message data and synchronize the chat message with room members
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
func SyncCreateTime
func SyncCreateTime(roomID string, ver uint8, cmd uint16, memberIDs []string)
SyncCreateTime sends room's created time (in seconds) to the selected (or all) members of the room
[IMPORTANT] This function does NOT work if the room is not on the same server. [NOTE] Uses mutex lock internally.
Parameters
roomID - Target room ID. ver - Command version to be used for the message. cmd - Command ID to be used for the message. memberIDs - An array of member user IDs to sync the room creation time.
func UpdateProperties
func UpdateProperties(roomID string, operation func(properties map[string]interface{}) bool) map[string]interface{}
UpdateProperties updates or creates properties of a room and returns the updated or created properties.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function DOES update room's internal TTL. [IMPORTANT] Room properties do NOT support structs. [IMPORTANT] Numeric properties will be float64. Use util.ToInt, ToUint etc. To convert to proper data type. [IMPORTANT] Array properties will be []interface{}. Must apply type assertion per element. [IMPORTANT] Byte array properties will be converted to base64 encoded string. Use util.ToBytes() to convert it back. [IMPORTANT] Operation function is protected by mutex lock, using another mutex lock within the function may cause a deadlock. [NOTE] Uses mutex lock internally.
Operation example:
var updateErr error _ := room.UpdateProperties(roomID, func(properties map[string]interface{}) { capsule := datacapsule.NewCapsule() err := capsule.Import(properties["roomPropertyCapsule"].(map[string]interface{})) if err != nil { // this is how to propagate an error updateErr = err return } counter := capsule.GetAsInt("counter") counter++ capsule.SetAsInt("counter", counter) properties["roomPropertyCapsule"] = capsule.Export() }) if updateErr != nil { // handle update error here }
Use datacapsule.Capsule as property:
capsule := datacapsule.NewCapsule() capsule.SetAsInt8("memberNum", memberNum) properties["memberNum"] = capsule.Export() // setting capsule as a property
Parameters
roomID - Room ID to update its properties. operation - Callback function to perform update operations and returns updated properties as a map. Must return true, when property (properties) is updated and false when there is no update.
func UpdateStateByRoomID
func UpdateStateByRoomID(roomID string, userData *user.User, key string, value []byte, linkToUser, reliable bool) error
UpdateStateByRoomID updates/creates a state property and synchronize its value to all members of the room.
ver and cmd will be used as command ver and command ID when synchronizing with the room members.
User must be a member of the room to use this function.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] Size of the state value and key combined should not exceed 40 bytes in length. [IMPORTANT] If a state is updated multiple times before synchronized, only the last updated value will be synchronized. [NOTE] Uses mutex lock internally.
Error Cases:
┌─────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═════════════════════════════════════╪══════════════════════════════════════════════════════════════════╡ │ Room not found │ The room tarted to update its state not found or does not exist. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤ │ Room state synchronizer not started │ EnableStateSync must be called to enable state synchronization. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤ │ User must be a member of the room │ The user that updates room state must be a member of the room. │ ├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤ │ Invalid value │ The value must not be nil or an empty byte array. │ └─────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsStateUpdateError(err error) // Failed to update a room state
Parameters
roomID - Target room ID of the room to update its state. userData - The user that is updating a state of the target room. If linkToUser flag is set to true, the state will be associated to the user and will be removed when the user leaves the room. key - Key represents the name of the state to be updated. value - Value is used to replace the previous state value. linkToUser - If the flag is set to true, the state will be linked to the user given. When the linked user leaves the room all linked states will be removed. reliable - If true, synchronization for UDP communication will be RUDP.
func UpsertStateByRoomID
func UpsertStateByRoomID(roomID string, userData *user.User, key string, reliable bool, cb func(exists bool, current []byte) []byte) error
UpsertStateByRoomID updates/creates a state property and synchronize its value to all members of the room.
ver and cmd will be used as command ver and command ID when synchronizing with the room members.
User must be a member of the room to use this function.
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] Size of the state value and key combined should not exceed 40 bytes in length. [IMPORTANT] If a state is updated multiple times before synchronized, only the last updated value will be synchronized. [IMPORTANT] The callback is invoked while the mutex lock is held and release when the callback finishes its execution. [NOTE] Uses mutex lock internally.
Error Cases:
┌───────────────────────────────────────┬────────────────────────────────────────────────────────────────────────┐ │ Error │ Reason │ ╞═══════════════════════════════════════╪════════════════════════════════════════════════════════════════════════╡ │ Room not found │ The room tarted to update its state not found or does not exist. │ ├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤ │ Room state synchronizer not started │ EnableStateSync must be called to enable state synchronization. │ ├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤ │ User must be a member of the room │ The user that updates room state must be a member of the room. │ ├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤ │ State value is not updated nor stored │ Upsert callback's return value must not be nil or an empty byte array. │ └───────────────────────────────────────┴────────────────────────────────────────────────────────────────────────┘
Error Evaluations
The possible error evaluations:
room.IsStateUpsertError(err error) // Failed to upsert a room state
Parameters
roomID - Target room ID of the room to update its state. userData - The user that is updating a state of the target room. If linkToUser flag is set to true, the state will be associated to the user and will be removed when the user leaves the room. key - Key represents the name of the state to be updated. cb - Callback function to perform upsert operation. The returned value will be used to upsert the value for the key. If the returned value's length is 0, it will not upsert at all. func(exists bool, current []byte) []byte exists - If true, the state of the given key exists. current - The current value of the state. The returned byte array of the callback will be the value of the state. reliable - If true, synchronization for UDP communication will be RUDP.
Usage Example
UpsertStateByRoomID is useful when you need to reference the value of a state that already exists and update its value based on the current value without the risk of race conditions. The concept is very similar to select for update SQL query.
// this will be the damage inflicted on the state called HP damage := uint32(-40) err := room.UpsertStateByRoomID(roomID, userData, "HP", true, func(exists bool, currentValue []byte) (updatedValue []byte) { // HP state does not exist yet, initialize it if !exists { // initial HP is 100 hp := uint32(100) // state value must be a byte array bytes := make([]byte, 4) binary.BigEndian.PutUint32(bytes, hp) // returning bytes will set bytes as HP state's value return bytes } // calculate HP state's new value currentHP := binary.BigEndian.Uint32(currentValue) currentHP += damage // encode the updated HP back to byte array bytes := make([]byte, 4) binary.BigEndian.PutUint32(bytes, currentHP) // returning bytes will set bytes as HP state's value return bytes }) if err != nil {
UpsertStateByRoomID failed, handle the error here...
}
Types
type DataDump
type DataDump struct { ID string `json:"RoomID"` MaxMembers int `json:"MaxMembers"` AllowEmpty bool `json:"AllowEmpty"` MemberIDs map[string]string `json:"MemberIDs"` Properties map[string]interface{} `json:"Properties"` }
DataDump implies a payload format for the dump room data command
type GetRoomInfoData
type GetRoomInfoData struct { RoomID string `json:"roomID"` CurrentMembers uint16 `json:"currentMembers"` MaxMembers uint16 `json:"maxMembers"` MemberIDs []string `json:"memberIDs"` OwnerID string `json:"ownerID"` AllowEmpty bool `json:"allowEmpty"` TTL int64 `json:"TTL"` LastPropUpdated int64 `json:"lastPropUpdated"` UpdaterSID string `json:"updaterSID"` Interval int64 `json:"interval"` Created int64 `json:"created"` Reserves []string `json:"reserves"` }
GetRoomInfoData represents internally used data
func GetRoomInfo
func GetRoomInfo(roomID string) (*GetRoomInfoData, error)
GetRoomInfo retrieves the information of the room.
This can be executed by anyone and they do not have to be part of the room.
[IMPORTANT] This function does NOT update room's internal TTL. [IMPORTANT] This function works for all users including the users that are not members of the target room.
Parameters
roomID - Target room ID to get the number of members from.
type JoinRoomCallback
type JoinRoomCallback func(err error, memberIDs []string, ownerID string, createdTime int64)
JoinRoomCallback is callback function for room.Join.
[IMPORTANT] This callback function is invoked on the server where the user is "originally" connected. room.Join may move the user to a different server if the room that the user is joining is not on the same server. When the user is moved to another server, this callback function is invoked on the server where the user was originally connected.
type Room
type Room struct { ID string MaxMembers int AllowEmpty bool // an array of member SIDs Members []string // ID as key and SID as value MemberIDs map[string]string // contains filtered or unexported fields }
Room Room data structure
func GetRoomByID
func GetRoomByID(roomID string) *Room
GetRoomByID returns a room
[IMPORTANT] This function does NOT work if the room is not on the same server. [IMPORTANT] This function does NOT update room's internal TTL. [NOTE] Uses mutex lock internally. [NOTE] This will not update TTL of the room.
Parameters
roomID - Target room ID to get the room object.