...

Package room

import "github.com/Diarkis/diarkis/room"
Overview
Index

Overview ▾

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(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterCreateRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterGetRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterJoinRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterLeaveRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterMessageRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func AfterUpdateRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func Announce(roomID string, memberIDs []string, ver uint8, cmd uint16, message []byte, reliable bool)
func BeforeBroadcastRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeCreateRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeGetRoomPropCmd(callback func(ver uint8, cmd uint16, payloa []byte, userData *user.User, next func(error)))
func BeforeJoinRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeLeaveRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeMessageRoomCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func BeforeUpdateRoomPropCmd(callback func(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)))
func Broadcast(roomID string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)
func CancelReservation(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error
func CancelReservationRemote(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool, cb func(error))
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, syncInterval, syncAllDelay, ttl int64, combineLimit uint8) 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 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, callback JoinRoomCallback)
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, cmd uint16, message []byte, reliable bool)
func MigrateRoom(ver uint8, cmd uint16, userData *user.User, callback func(err error, newRoomID string, oldRoomID string))
func NewRoom(userData *user.User, maxMembers int, allowEmpty bool, join bool, ttl int64, interval int64) (string, error)
func Relay(roomID string, sender *user.User, ver uint8, cmd uint16, message []byte, reliable bool) bool
func RelayTo(roomID string, sender *user.User, members []string, ver uint8, cmd uint16, message []byte, reliable bool) 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, callback func(roomID string, userData *user.User) (uint8, uint16, []byte)) 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(previousRoomID string, currentRoomID string))
func SetOnRoomChange(cb func(string, int, []string, map[string]interface{})) bool
func SetOnRoomChangeByID(roomID string, cb func(roomID string, changeEvent int, memberIDs []string, properties map[string]interface{})) 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 SetupAsWSServer()
func SetupBackup(backupNum int)
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, linkToUser, reliable bool) error
func UpsertStateByRoomID(roomID string, userData *user.User, key string, reliable bool, cb func(exists bool, current []byte) []byte) error
type DataDump
type JoinReturnData
type JoinRoomCallback
type Room
    func GetRoomByID(roomID string) *Room

Constants

MemberAdded is an enum flag for SetOnRoomChange callback to indicate that there is a new member added to the room

const MemberAdded = 1

MemberRemoved is an enum flag for SetOnRoomChange callback to indicate that there is a member that has been removed from the room

const MemberRemoved = 2

PropertyChanged is an enum flag for SetOnRoomChange callback to indicate that one or more room properties have been changed

const PropertyChanged = 3

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 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 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 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 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:

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:

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 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.   │
├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Not allowed to join without reservation │ The room is room including reservation and the user does not have reservation. │
└─────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘

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).

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 ]  │
               │                                            │
               │                                            │
               │                                            │
               │                                [ room.SetOnJoinByID ]
               │                                            │
               │                                   ┌────────┴───┐
               │                                   │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━[ Room Join Failed ]  │
               │                                                │
               │                                                │
               │                                     [ Reservation Check ]
               │                                                │
               │                                       ┌────────┴───┐
               │                                       │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ]  │
               │                                                    │
               │                                       [ room.SetOnJoinByID ]
               │                                                    │
               │                                           ┌────────┴───┐
               │                                           │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ]  │
               │                                                        │
               │                                             [ room.SetOnRoomChange ]
               │                                                        │
               │                                          [ room.SetOnJoinCompleteByID ]
               │                                                        │
               │                                                 [ Join Success ]
               │                                                        │
     [ 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 ]◀︎─────┘       │
            │                 │                     │
[ Join Failure Response ]◀︎━━━━┥                     │
            │                 │                     │
            │                 │          [ room.SetOnJoinByID ]
            │                 │                     │
            │                 │                 ┌───┴───┐
            │                 │                 │       │
            │         [ Join Failure ]◀︎─────────┘       │
            │                 │                         │
[ Join Failure Response ]◀︎━━━━┥                         │
            │                 │                         │
            │                 │               [ Reservation Check ]
            │                 │                         │
            │                 │                     ┌───┴───┐
            │                 │                     │       │
            │         [ Join Failure ]◀︎─────────────┘       │
            │                 │                             │
[ Join Failure Response ]◀︎━━━━┥                             │
            │                 │                             │
            │                 │                  [ room.SetOnJoinByID ]
            │                 │                             │
            │                 │                         ┌───┴───┐
            │                 │                         │       │
            │         [ Join Failure ]◀︎─────────────────┘       │
            │                 │                                 │
[ Join Failure Response ]◀︎━━━━┥                                 │
            │                 │                                 │
            │                 │                    [ room.SetOnRoomChange ]
            │                 │                                 │
            │          [ Join Success ]◀︎────────────────────────┤ Callback of room.Join on Server A is invoked.
            │                 │                                 │
[ 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.                    │
│ 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.
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-connections will take place
└────────────────────────┘                   └────────────────────────┘     AFTER the execution of SetOnMigrated
        ▲                                      │                 ▲
        │                                      │                 │
        │ <1> Migrate                          │                 │ <6> Re-connect
        │                                      │                 │     (All members of the room will reconnect asynchronously)
        │ ┌────────────────────────────────────┘                 │
        │ │ <6> Re-connect instruction                           │
        │ │     (All members of the room will receive            │
        │ │      instruction asynchronously)                     │
        │ ▼                                                      │
    ╭────────╮                                                   │
    │ Client │───────────────────────────────────────────────────┘
    ╰────────╯(Client re-connects to where the migrated room is)

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)    │
      │                           │(cmd: custom)    │
      │                           │                 │
      ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ]    │
      │                           │                 │
      │                           │                 │
[ Leave Confirmation ]◀︎━━━━━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━▶︎[ Join Request To 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)    │
      │                           │(cmd: custom)    │
      │                           │                 │
      ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ]    │
      │                           │                 │
      │                           │                 │
[ Leave Confirmation ]◀︎━━━━━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━▶︎[ Join Request To 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 bot 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.                                                        │
├───────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
│ 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(previousRoomID string, currentRoomID 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 SetupAsWSServer

func SetupAsWSServer()

SetupAsWSServer 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 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...

}

type DataDump

DataDump implies a payload format for the dump room data command

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"`
}

type JoinReturnData

JoinReturnData represents internally used data

type JoinReturnData struct {
    MemberUIDs  []string `json:"memberUIDs"`
    OwnerID     string   `json:"ownerID"`
    CreatedTime int64    `json:"createdTime"`
}

type JoinRoomCallback

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 JoinRoomCallback func(err error, memberIDs []string, ownerID string, createdTime int64)

type Room

Room Room data structure

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
}

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.