package room

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

Package room ▷

Room module

Important

Diarkis Room can NOT be used with Diarkis Field and MatchMaker Ticket.

Room Join

Joining a room may require the client to switch the server depending on where the join is located. If the client is connected to a server that the room is not located, the server instructs the client to re-connect. This is handled internally by Diarkis.

There are a few things you must keep in mind when using Join function.

The callback of Join function may not be invoked on the server where the room is. What this means is that if the client is required to re-connect to the server where the room is, Diarkis internally handles this from one server to another. The callback is then invoked on the server that the client was originally connected.

The following example will not work as expected if the client is required to re-connect, therefore you must avoid writing such code:

▶︎ Retrieving a room property in Join callback

room.Join(roomID, userData, ver, cmd, message, callback func(err error, memberIDs []string, ownerID string, createdTime int64) {

  // This will NOT retrieve intended room property because the room does not exist on this server
  doesNotWork := room.GetProperty(roomID, "RoomName")

  // This WILL retrieve intended room property because room.GetRemoteProperty accesses the room on the different server
  // Notice the function is asynchronous
  room.GetRemoteProperty(roomID, "RoomName", func(err error, value interface{}) {
    // value is the property of "RoomName"
  })

})

Room Broadcast

Room Broadcast sends a message to all member clients of the room including the sender itself.

Room Broadcast requires the sender user to he a member of the room.

Room Broadcast also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Broadcast messages for the given interval. The interval is given to the room when the room is created.

Room Message

Room Message sends a message to selected members clients of the room.

Room Message requires the sender user to he a member of the room.

Room Message also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Message messages for the given interval. The interval is given to the room when the room is created.

Room Announce

Room Announce sends a message to selected member of clients of the room regardless of the sender user being a member of the room. This function is not available for the built-in client command calls.

Room Announce also combines multiple messages in order to reduce the number of packets sent from the server. This is done by buffering Announce messages for the given interval. The interval is given to the room when the room is created.

Room Relay

Room Relay sends a message to all members of the room except for the sender user.

Unlike Room Broadcast, Message, and Announce, Room Relay does not combine multiple messages.

Room State Synchronization

Room State Synchronization allows the user to add, remove, and update custom states.

A Room State has a name and a value that will be automatically synchronized to the member clients when the state value changes. The member clients will raise an event per synchronization of a state.

▶︎ Setting up Room State Synchronization

// Command version to be used to send synchronization data when a state value changes.
updateVer := uint8(2)

// Command version to be used to send synchronization data when a state is removed.
removeVer := uint8(2)

// Command ID to be used to send synchronization data when a state value changes.
updateCmd := uint16(1000)

// Command ID to be used to send synchronization data when a state is removed.
removeCmd := uint16(1100)

// Checks and send synchronization data to all member clients at every 100 milliseconds.
syncInterval := int64(100)

// Delays the initial synchronization of all states when a new client becomes a member of the room.
// The value is in milliseconds.
syncAllDelay := int64(0)

// TTL of each state. If a state is not updated for longer than TTL, it will be removed automatically.
ttl := int64(500)

// Maximum number of synchronization data packets to be combined.
combineLimit := 10
success := room.EnableStateSync(roomID, updateVer, removeVer, updateCmd, removeCmd, syncInterval, syncAllDelay, ttl, combineLimit)

▶︎ Update Room State With The Current Value

When updating a state, you may need to use the current value of the state to perform the update operation while making sure the value of the state will not be changed until the update operation is finished.

Important

The callback is invoked while a mutex lock is still held and it is released when the callback returns.

The example below increments the current state value. Since the callback is protected by a mutex lock, there is no race condition while updating the value.

err := room.UpsertStateByRoomID(roomID, userData, key, reliable, cb func(exists bool, current []byte {

  if !exists {
    // The state does not exist, so simply create a new one.
    // The returned value will be the state value.
    // For example, the value of this state is a byte array encoded uint32
    bytes := make([]byte, 4)
    binary.BigEndian.PutUint32(bytes, newStateValue)
    return bytes
  }

  // For example, the value of the state is byte array encoded uint32
  currentCount := binary.BigEndian.Uint32(current)
  currentCount += newStateValue
  bytes := make([]byte, 4)
  binary.BigEndian.PutUint32(bytes, currentCount)
  return bytes

}) []byte)

Index

Constants

const MemberAdded = 1

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

const MemberRemoved = 2

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

const PropertyChanged = 3

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

Variables

var ErrGetUserBySID = errors.New("could not find user by SID")

ErrGetUserBySID could not find user by SID

var ErrTransferOwnershipDisabled = errors.New("ownership transfer is not enabled for this Room")

ErrTransferOwnershipDisabled ownership transfer is not enabled for this Room

var ErrTransferOwnershipEmptyRoom = errors.New("ownership transfer is not possible when owner is the only Room member")

ErrTransferOwnershipEmptyRoom ownership transfer is not possible when owner is the only Room member

var ErrTransferOwnershipNotAllowed = errors.New("you must be the owner to perform ownership transfer")

ErrTransferOwnershipNotAllowed ownership transfer cannot be performed by non-owner member.

var ErrTransferOwnershipSelf = errors.New("owner cannot transfer Room ownership to self")

ErrTransferOwnershipSelf owner cannot transfer Room ownership to self

var ErrUserNotFound = errors.New("could not find user in Room")

ErrUserNotFound could not find the specified user in Room

Functions

func AfterBroadcastRoomCmd

func AfterBroadcastRoomCmd(callback BeforeAfterCommandCallback)

AfterBroadcastRoomCmd registers a callback function to be executed after broadcast room command:

Important

Must be called before ExposeCommands

func AfterCreateOrJoinByCustomIDCmd

func AfterCreateOrJoinByCustomIDCmd(callback BeforeAfterCommandCallback)

AfterCreateOrJoinByCustomIDCmd registers a callback function to be executed after create or join by custom id:

Important

Must be called before ExposeCommands

func AfterCreateRoomCmd

func AfterCreateRoomCmd(callback BeforeAfterCommandCallback)

AfterCreateRoomCmd registers a callback function to be executed after create room command:

Important

Must be called before ExposeCommands

func AfterCreateRoomWithAllowOwnershipTransferCmd

func AfterCreateRoomWithAllowOwnershipTransferCmd(callback BeforeAfterCommandCallback)

AfterCreateRoomWithAllowOwnershipTransferCmd registers a callback function to be executed before create room with allow transfer ownership:

Important

Must be called before ExposeCommands

func AfterGetRoomPropCmd

func AfterGetRoomPropCmd(callback BeforeAfterCommandCallback)

AfterGetRoomPropCmd registers a callback function to be executed after get room properties:

Important

Must be called before ExposeCommands

func AfterJoinRoomCmd

func AfterJoinRoomCmd(callback BeforeAfterCommandCallback)

AfterJoinRoomCmd registers a callback function to be executed after join room command:

Important

Must be called before ExposeCommands

func AfterLeaveRoomCmd

func AfterLeaveRoomCmd(callback BeforeAfterCommandCallback)

AfterLeaveRoomCmd registers a callback function to be executed after leave room command:

Important

Must be called before ExposeCommands

func AfterMessageExtendedRoomCmd

func AfterMessageExtendedRoomCmd(callback BeforeAfterCommandCallback)

AfterMessageExtendedRoomCmd registers a callback function to be executed after RoomMessageExtended:

Important

Must be called before ExposeCommands

func AfterMessageRoomCmd

func AfterMessageRoomCmd(callback BeforeAfterCommandCallback)

AfterMessageRoomCmd registers a callback function to be executed after message room command:

Important

Must be called before ExposeCommands

func AfterUpdateRoomPropCmd

func AfterUpdateRoomPropCmd(callback BeforeAfterCommandCallback)

AfterUpdateRoomPropCmd registers a callback function to be executed after update room properties:

Important

Must be called before ExposeCommands

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

BeforeBroadcastRoomCmd registers a callback function to be executed before broadcast room command:

Important

Must be called before ExposeCommands

func BeforeCreateOrJoinByCustomIDCmd

func BeforeCreateOrJoinByCustomIDCmd(callback BeforeAfterCommandCallback)

BeforeCreateOrJoinByCustomIDCmd registers a callback function to be executed before create or join by custom id:

Important

Must be called before ExposeCommands

func BeforeCreateRoomCmd

func BeforeCreateRoomCmd(callback BeforeAfterCommandCallback)

BeforeCreateRoomCmd registers a callback function to be executed before create room command.

Important

Must be called before ExposeCommands

func BeforeCreateRoomWithAllowOwnershipTransferCmd

func BeforeCreateRoomWithAllowOwnershipTransferCmd(callback BeforeAfterCommandCallback)

BeforeCreateRoomWithAllowOwnershipTransferCmd registers a callback function to be executed before create room with allow transfer ownership:

Important

Must be called before ExposeCommands

func BeforeGetRoomPropCmd

func BeforeGetRoomPropCmd(callback BeforeAfterCommandCallback)

BeforeGetRoomPropCmd registers a callback function to be executed before get room properties:

Important

Must be called before ExposeCommands

func BeforeJoinRoomCmd

func BeforeJoinRoomCmd(callback BeforeAfterCommandCallback)

BeforeJoinRoomCmd registers a callback function to be executed before join room command:

Important

Must be called before ExposeCommands

func BeforeLeaveRoomCmd

func BeforeLeaveRoomCmd(callback BeforeAfterCommandCallback)

BeforeLeaveRoomCmd registers a callback function to be executed before leave room command:

Important

Must be called before ExposeCommands

func BeforeMessageExtendedRoomCmd

func BeforeMessageExtendedRoomCmd(callback BeforeAfterCommandCallback)

BeforeMessageExtendedRoomCmd registers a callback function to be executed before RoomMessageExtended command:

Important

Must be called before ExposeCommands

func BeforeMessageRoomCmd

func BeforeMessageRoomCmd(callback BeforeAfterCommandCallback)

BeforeMessageRoomCmd registers a callback function to be executed before message room command:

Important

Must be called before ExposeCommands

func BeforeUpdateRoomPropCmd

func BeforeUpdateRoomPropCmd(callback BeforeAfterCommandCallback)

BeforeUpdateRoomPropCmd registers a callback function to be executed before update room properties:

Important

Must be called before ExposeCommands

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

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

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

Parameters

roomID - Target room ID of the properties.
name   - Property name to retrieve.
cb     - A callback to be invoked when the property has been fetched.

func GetReservedUserIDs

func GetReservedUserIDs(roomID string) []string

GetReservedUserIDs returns a list of user IDs that have reservations in the room.

Note

Uses mutex lock internally.

Parameters

roomID - Target room ID to get reservations.

func GetRoomID

func GetRoomID(userData *user.User) string

GetRoomID returns roomID that the user has joined

Important

This function can be used only on the server that the room exists.

Note

Uses mutex lock internally.

Parameters

userData - Target user to get the room ID that the user is currently member of.

func GetRoomNodeAddressList

func GetRoomNodeAddressList(roomID string) ([]string, error)

GetRoomNodeAddressList returns a list of internal node addresses that the room is stored

roomID - Target room ID to extract the server internal node addresses from.

Returns a list of server internal node addresses of the room and error if it fails.

func GetRoomOwnerID

func GetRoomOwnerID(roomID string) string

GetRoomOwnerID returns the user ID of the owner of the room

Important

This function does NOT work if the room is not on the same server.

Important

This function does NOT update room's internal TTL.

Note

Uses mutex lock internally.

Parameters

roomID - Target room ID to get the owner from.

func IncrProperty

func IncrProperty(roomID string, propName string, delta int64) (int64, bool)

IncrProperty increments int64 property by given delta and returns the incremented value.

Important

This function does NOT work if the room is not on the same server.

Important

This function DOES update room's internal TTL.

If the property does not exist, it creates the property.

Note

Uses mutex lock internally.

Cases for return value false

┌──────────────────┬──────────────────────────────────────────────────────┐
│ Error            │ Reason                                               │
╞══════════════════╪══════════════════════════════════════════════════════╡
│ Room not found   │ Either invalid room ID given or room does not exist. │
│ Property Corrupt │ Target property data type is not int64.              │
└──────────────────┴──────────────────────────────────────────────────────┘

Parameters

roomID   - Target room ID.
propName - Target property name.
delta    - Delta value to increment by.

Usage Example

updatedHP, updated := room.IncrProperty(roomID, "HP", damage)

func IsCancelReserveError

func IsCancelReserveError(err error) bool

IsCancelReserveError returns true if the given error is or contains a RoomCancelReserveError.

func IsFailureError

func IsFailureError(err error) bool

IsFailureError returns true if the given error is or contains a generic RoomFailureError.

func IsJoinError

func IsJoinError(err error) bool

IsJoinError returns true if the given error is or contains a RoomJoinError.

func IsLeaveError

func IsLeaveError(err error) bool

IsLeaveError returns true if the given error is or contains a RoomLeaveError.

func IsNewRoomError

func IsNewRoomError(err error) bool

IsNewRoomError returns true if the given error is or contains a RoomNewError.

func IsReserveError

func IsReserveError(err error) bool

IsReserveError returns true if the given error is or contains a RoomReserveError.

func IsReserved

func IsReserved(roomID string, uid string) bool

IsReserved returns true if the given uid (User ID) has a reservation with the given room.

Note

Uses mutex lock internally.

func IsRoomFull

func IsRoomFull(roomID string) bool

IsRoomFull returns true if the room is full.

Important

This function does NOT work if the room is not on the same server.

Important

This function does NOT update room's internal TTL.

Note

Uses mutex lock internally.

Parameters

roomID - Target room ID to check.

func IsStateUpdateError

func IsStateUpdateError(err error) bool

IsStateUpdateError returns true if the given error is or contains a RoomStateUpdateError.

func IsStateUpsertError

func IsStateUpsertError(err error) bool

IsStateUpsertError returns true if the given error is or contains a RoomStateUpsertError.

func IsUserInRoom

func IsUserInRoom(roomID string, userData *user.User) bool

IsUserInRoom returns true if the user is in the room

Important

This function does NOT work if the room is not on the same server.

Important

This function does NOT update room's internal TTL.

Note

Uses mutex lock internally.

Parameters

roomID   - Target room ID to check.
userData - Target user to see if the user is in the room.

func Join

func Join(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte, callback JoinRoomCallback)

Join joins a room and notify the other members of the room on joining the room.

Note

Uses mutex lock internally.

Note

If message is empty, Broadcast will not be sent.

Note

This function is asynchronous. What this means is that it involves server-to-server communication internally.

Important

The room to join may not be on the same server process and if that is the case, the client will move to where the room is.
That means the client will re-connect to a different Diarkis server in the Diarkis cluster.
This is handled by Diarkis client SDK. The join will be completed when the user successfully changes the server.

Important

The callback is called on the original server that the user client is connected to
and the room to join may not be on the same server.
Please do not read and/or write room properties in the callback as the room may not be accessible
and creates a bug in your application code.
Do not use functions that require the room to be on the same server to work.

Important

This function works even if the room is on a different server.

Error Cases:

┌─────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│ Error                           │ Reason                                                                         │
╞═════════════════════════════════╪════════════════════════════════════════════════════════════════════════════════╡
│ User is already in another room │ The user is not allowed to join more than one room at a time.                  │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Node of room not found          │ Server of the room is not available in the Diarkis cluster.                    │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Failed to transfer user         │ Transferring the user to the server of the room failed.                        │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Room not found                  │ Room to join not found.                                                        │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Room join rejected              │ SetOnJoinByID and/or SetJoinCondition callback(s) rejected the user to join.   │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ Cannot join room                │ The room is at capacity, or all remaining slots have pending reservations.     │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ User is already in the room     │ The user is already in the room.                                               │
└─────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

Besides the following errors, there are Mesh module errors as well.

room.IsJoinError(err error) // Failed to join a room

Parameters

roomID   - Target room ID to join.
userData - User to join the room.
ver      - Command version to be used for successful join message sent to other room members.
cmd      - Command ID to be used for successful join message sent to other room members.
message  - Message byte array to be sent as successful message to other room members.
           If message is either nil or empty, the message will not be sent.
callback - Callback to be invoked when join operation completes (both success and failure).
           [IMPORTANT] When the user needs to re-connect, the callback is invoked BEFORE the re-connect.
                       In order to capture the actual completion of joining the room, use room.SetOnJoinCompleteByID.

Packets sent from the server for join

Join operation on the server may send multiple packets to the client.

Here are the details on each packet sent from the server and their order.

▶︎ Re-connect instruction push

This packet is sent from the server when the server requires the client to re-connect to another server.

▶︎ On join response

This packet is always sent from the server when join operation is completed.

ver = 1
cmd = 101

Command ver and ID for on join packet is as shown above:

Order of packets from the server and join callback

▶︎ With re-connect instruction:

Join request → Re-connect instruction push → On join response → On member join push

    ┌──────────────────────────┐                        ┌──────────────────┐
    │     UDP/TCP server A     │                        │ UDP/TCP server B │──────────────┐
    └──────────────────────────┘                        └──────────────────┘              │
                 ▲        │                                   │                           │
<1> Join request │        │                                   │                           │
                 │        │ <2> Re-connect instruction push   │                           │
                 │        │                                   │ <3> On join response      │
            ╭────────╮◀︎───┘                                   │                           │ <4> On member join push
            │ Client │◀︎───────────────────────────────────────┘                           │
            ╰────────╯◀︎───────────────────────────────────────────────────────────────────┤
                  ╭────────╮╮╮                                                            │
Other room members│ Client │││◀︎───────────────────────────────────────────────────────────┘
                  ╰────────╯╯╯

▶︎ Without re-connect instruction:

Join request → On join response → On member join push

    ┌────────────────────────────────────┐
┌─▶︎ │           UDP/TCP server A         │────┐
│   └────────────────────────────────────┘    │
│                      │                      │
│ <1> Join request     │                      │
│                      │ <2> On join response │
│                      ▼                      │ <3> On member join push
│                  ╭────────╮                 │
└──────────────────│ Client │◀︎────────────────┤
                   ╰────────╯                 │
                   ╭────────╮╮╮               │
 Other room members│ Client │││◀︎──────────────┘
                   ╰────────╯╯╯

The order of packet and callback change when re-connect or not.

Callback and Server Location

When the user joins a room that exists on a different server, the client is required to re-connect to the server where the room is. Diarkis handles this internally, but it is useful to understand the mechanism behind it.

The diagram below shows the sequence of operations and callbacks as well as where they are executed.

The number in <> indicates the order of execution of callbacks and operations.

┌──────────────────┐                      ┌────────────────────────┐ <7> On member join push waits for on join response
│ UDP/TCP server A │                      │    UDP/TCP server B    │─────────────────────────────────────┐
│                  │  <2> Join operation  │                        │                                     │
│                  │─────────────────────▶︎│                        │ <6> On join response waits for      │
│                  │                      │                        │     SetOnJoinCompleteByID execution │
│                  │◀︎─────────────────────│ [ Room A exists here ] │─────────────────────────────┐       │
└──────────────────┘ <3> Join operation   └────────────────────────┘                             │       │
        ▲                callback is              ▲ <5> Callback of SetOnJoinCompleteByID is     │       │
        │                executed on server A     │     executed on server B                     │       │
        │                                         │                                              │       │
        │ <1> Join request                        │ <4> Re-connect                               │       │
        │                                         │     Client re-connects to where the room is  │       │
    ╭────────╮                                    │                                              │       │
    │ Client │────────────────────────────────────┘                                              │       │
    ╰────────╯◀︎──────────────────────────────────────────────────────────────────────────────────┘       │
        ▲                                                                                                │
        │                                                                                                │
        └────────────────────────────────────────────────────────────────────────────────────────────────┤
                   ╭────────╮╮╮                                                                          │
 Other room members│ Client │││◀︎─────────────────────────────────────────────────────────────────────────┘
                   ╰────────╯╯╯

Join Sequences

Join operation and its sequences are different when the room to join is on the same server or on a different server.

▶︎ Same Server Join

The sequence below is join operation sequence where the room is on the same server as the user.

                                                [ Room is here ]
          ╭────────╮                              ┌──────────┐
          │ Client │                              │ Server A │
          ╰────────╯                              └──────────┘
               │                                        │
               ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Join Request ]
               │                                        │
               │                            [ room.SetJoinCondition ]
               │                                        │
               │                               ┌────────┴───┐
               │                               │            │
       [ Join Failure Response ]◀︎━━━━━[ Room Join Failed ]  │ --- ( JoinRoomCallback )
               │                                            │
               │                                            │
               │                                            │
               │                                [ room.SetOnJoinByID ]
               │                                            │
               │                                   ┌────────┴───┐
               │                                   │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━[ Room Join Failed ]  │ --- ( JoinRoomCallback )
               │                                                │
               │                                                │
               │                                     [ Reservation Check ]
               │                                                │
               │                                       ┌────────┴───┐
               │                                       │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ]  │ --- ( JoinRoomCallback )
               │                                                    │
               │                                       [ room.SetOnJoinByID ]
               │                                                    │
               │                                           ┌────────┴───┐
               │                                           │            │
[ Join Failure Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━[ Room Join Failed ]  │ --- ( JoinRoomCallback )
               │                                                        │
               │                                             [ room.SetOnRoomChange ]
               │                                                        │
               │                                          [ room.SetOnJoinCompleteByID ]
               │                                                        │
               │                                                 [ Join Success ] --- ( JoinRoomCallback )
               │                                                        │
     [ On Join Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
               │                                                        │
      [ On Member Join ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ On Member Join will be sent to all members.
               │                                                        │
               ▽                                                        ▽

▶︎ Remote Server Join

The sequence below is the operation sequence where the room is on a different server from the user.

                                         [ Room is here ]
       ╭────────╮       ┌──────────┐       ┌──────────┐
       │ Client │       │ Server A │       │ Server B │
       ╰────────╯       └──────────┘       └──────────┘
            │                 │                 │
            ┝━━━━━━━━▶︎[ Join Request ]          │
            │                 │                 │
            │                 ├────────▶︎[ Join Request ]
            │                 │                 │
            │                 │     [ room.SetJoinCondition ]
            │                 │                 │
            │                 │             ┌───┴───┐
            │                 │             │       │
            │         [ Join Failure ]◀︎─────┘       │ --- ( JoinRoomCallback ) on Server A
            │                 │                     │
[ Join Failure Response ]◀︎━━━━┥                     │
            │                 │                     │
            │                 │          [ room.SetOnJoinByID ]
            │                 │                     │
            │                 │                 ┌───┴───┐
            │                 │                 │       │
            │         [ Join Failure ]◀︎─────────┘       │ --- ( JoinRoomCallback ) on Server A
            │                 │                         │
[ Join Failure Response ]◀︎━━━━┥                         │
            │                 │                         │
            │                 │               [ Reservation Check ]
            │                 │                         │
            │                 │                     ┌───┴───┐
            │                 │                     │       │
            │         [ Join Failure ]◀︎─────────────┘       │ --- ( JoinRoomCallback ) on Server A
            │                 │                             │
[ Join Failure Response ]◀︎━━━━┥                             │
            │                 │                             │
            │                 │                  [ room.SetOnJoinByID ]
            │                 │                             │
            │                 │                         ┌───┴───┐
            │                 │                         │       │
            │         [ Join Failure ]◀︎─────────────────┘       │ --- ( JoinRoomCallback ) on Server A
            │                 │                                 │
[ Join Failure Response ]◀︎━━━━┥                                 │
            │                 │                                 │
            │                 │                    [ room.SetOnRoomChange ]
            │                 │                                 │
            │          [ Join Success ]◀︎────────────────────────┤ --- ( JoinRoomCallback ) on Server A
            │                 │                                 │
[ Re-connect Instruction ]◀︎━━━┥ Disconnect from Server A.       │
            │                 │                                 │
            ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ]
            │                 │                                 │
    [ On Connect ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
            │                 │                                 │
            │                 │                    [ room.SetOnJoinCompleteByID ]
            │                 │                                 │
            │                 │                          [ Join Success ]
            │                 │                                 │
  [ On Join Response ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
            │                 │                                 │
   [ On Member Join ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ On Member Join will be sent to all members.
            │                 │                                 │
            ▽                 ▽                                 ▽

func Leave

func Leave(roomID string, userData *user.User, ver uint8, cmd uint16, message []byte) error

Leave Leaves from a room and notify the other members on leaving. If message is empty Broadcast will not be sent.

Note

Uses mutex lock internally.

Important

This function does not work if the room is not on the same server.

Important

When a member user of a room disconnects unexpectedly, the room will automatically detect the leave of
the user and sends on leave message to the reset of the member users.
The message contains room ID and the user ID that disconnected.
In order to have custom message for this behavior, use SetOnDiscardCustomMessage.

Error Cases:

┌──────────────────────────┬─────────────────────────────────────────────────────┐
│ Error                    │ Reason                                              │
╞══════════════════════════╪═════════════════════════════════════════════════════╡
│ Room not found           │ Room to leave from is not found.                    │
├──────────────────────────┼─────────────────────────────────────────────────────┤
│ The user is not a member │ The user is not a member of the room to leave from. │
└──────────────────────────┴─────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

room.IsLeaveError(err error) // Failed to leave from a room

Parameters

roomID   - Target room ID to leave from.
userData - User that will be leaving the room.
ver      - Command version to be used for message sent when leave is successful.
cmd      - Command ID to be used for message sent when leave is successful.
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.

func Message

func Message(roomID string, memberIDs []string, senderUser *user.User, ver uint8, cmd uint16, message []byte, reliable bool)

Message Sends a message to selected members of the room

Important

This function does NOT work if the room is not on the same server.

Important

All message payloads have leading 4-byte-long header. The client must skip the first 4 bytes.

Important

Built-in events such as OnMemberMessage handles the separation of combined payloads internally,
so the application does not need to handle it by using BytesToBytesList.

Note

Uses mutex lock internally.

Parameters

roomID     - Target room ID.
memberIDs  - An array of member user IDs to send message to.
senderUser - User to send broadcast.
ver        - Command version to be used as broadcast message.
cmd        - Command ID to be used as broadcast message.
message    - Message byte array.
reliable   - If true, UDP will be RUDP.

func MigrateRoom

func MigrateRoom(ver uint8, cmd uint16, userData *user.User, callback func(err error, newRoomID string, oldRoomID string))

MigrateRoom migrates a room to another node and moves its members to the new room.

This is intended to be used when the current node is about to shutdown (in offline state), but you need to keep the current room.

Important

This function does not work if the room is not on the same server.

Important

Migration will change the room ID.

Important

The callback may be invoked on the server where the room is not held.
Do not use functions that requires the room to be on the same server.

Note

Uses mutex lock internally.

Note

This function is asynchronous.

Error Cases:

┌─────────────────────────────────────────┬────────────────────────────────────────────────────────────────────┐
│ Error                                   │ Reason                                                             │
╞═════════════════════════════════════════╪════════════════════════════════════════════════════════════════════╡
│ Node (server) to migrate room not found │ The server to migrate the room to is not found.                    │
├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ User must be provided                   │ Given user must be a valid user.                                   │
├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ User must not be a blank user           │ Given user must not be a blank user.                               │
├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ Must be owner                           │ Only the room owner is allowed to perform room migration.          │
├─────────────────────────────────────────┼────────────────────────────────────────────────────────────────────┤
│ User transfer failed                    │ The owner user failed to transfer to another server for migration. │
└─────────────────────────────────────────┴────────────────────────────────────────────────────────────────────┘

Parameters

ver      - Command ver to send the new migrated room ID to all members as migration instruction.
cmd      - Command ID to send the new migrated room ID to all members as migration instruction.
userData - Owner user to perform the migration.
           The user passed to this function must be a valid user that is also the owner of the room.
callback - Invoked when migration operation is completed.

When a room is migrated to another server, the users of the room will be re-connected to the server where the room is migrated. This is handled by Diarkis internally, but it is useful to understand the mechanism of it.

The diagram below shows the sequence of operations and callbacks as well as where they are executed.

The number in < > indicates the order of execution of callbacks and operations.

┌────────────────────────┐                   ┌────────────────────────┐
│ UDP/TCP server A       │  <2> Migrate      │    UDP TCP server B    │
│                        │──────────────────▶︎│                        │
│ [ Room A exists here ] │                   │  [ Room A migrated ]   │ <3> SetOnMigrated is executed on server B
│                        │                   │                        │     Re-join will take place
└────────────────────────┘                   └────────────────────────┘     AFTER the execution of SetOnMigrated
        ▲     │                                                  ▲
        │     └───────────┐                                      │
        │ <1> Migrate     │                                      │ <5> Re-join:
        │                 │                                      │     Each member must leave the previous room (room before the migration) and
        │                 │                                      │     join the new migrated room by the room ID pushed from the server.
        │                 │                                      │     (All members of the room will reconnect asynchronously)
        │ ┌───────────────┘                                      │
        │ │ <4> New migrated room ID notification                │
        │ │     (All members of the room will receive            │
        │ │      the new migrated room ID asynchronously)        │
        │ ▼                                                      │
    ╭────────╮                                                   │
    │ Client │───────────────────────────────────────────────────┘
    ╰────────╯(Client re-connects to where the migrated room is via executing Join)

Owner user:

The owner of the room will NOT receive on join event response (cmd:101) from the server. Instead, the owner will receive on migration complete event push (cmd:20) from the server when the owner user completes the server re-connection.

  ╭────────╮                 ┌──────────┐      ┌──────────┐
  │ Client │                 │ Server A │      │ Server B │
  ╰────────╯                 └──────────┘      └──────────┘
      │                           │                 │
      ┝━━━━━━━━━━━━━━━━━▶︎[ Migration Request ]      │
      │                           │                 │
      │                           ├───────────▶︎[ Migration ] Room is copied here with the new room ID.
      │                           │                 │
      │                           │ [ SetOnMigrated Callback Invoked ]
      │                           │                 │
      │           [ Migration Confirmation ]◀︎───────┤
      │                           │                 │
[ Migration Instruction ]◀︎━━━━━━━━┥(ver: custom)    │ Migration Instruction contains the new room ID.
      │                           │(cmd: custom)    │
      │                           │                 │
      ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ]    │ The user leaves the previous room.
      │                           │                 │
      │                           │                 │
[ Leave Confirmation ]◀︎━━━━━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━▶︎[ Join Request To Migrated Room ]    │ The user joins the new migrated room.
      │                           │                 │
      │                           ├────────────▶︎[ Join ]
      │                           │                 │
      │              [ Join Confirmation ]◀︎─────────┤
      │                           │                 │
[ Re-connect Instruction ]◀︎━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ]
      │                           │                 │
      │                           │                 │
[ Migration Confirmation ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━┥ For owner user: cmd=20 on migration complete
      │                           │                 │
      ▽                           ▽                 ▽

Non-owner user:

Non-owner user WILL receive on join event response (cmd:101) from the server when completing the server re-connection.

  ╭────────╮                 ┌──────────┐      ┌──────────┐
  │ Client │                 │ Server A │      │ Server B │
  ╰────────╯                 └──────────┘      └──────────┘
      │                           │                 │
      ┝━━━━━━━━━━━━━━━━━▶︎[ Migration Request ]      │
      │                           │                 │
      │                           ├───────────▶︎[ Migration ] Room is copied here with the new room ID.
      │                           │                 │
      │                           │ [ SetOnMigrated Callback Invoked ]
      │                           │                 │
      │           [ Migration Confirmation ]◀︎───────┤
      │                           │                 │
[ Migration Instruction ]◀︎━━━━━━━━┥(ver: custom)    │ Migration Instruction contains the new room ID.
      │                           │(cmd: custom)    │
      │                           │                 │
      ┝━━━━━━━━━━━━▶︎[ Leave From Previous Room ]    │ The user leaves the previous room.
      │                           │                 │
      │                           │                 │
[ Leave Confirmation ]◀︎━━━━━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━▶︎[ Join Request To Migrated Room ]    │ The user joins the new migrated room.
      │                           │                 │
      │                           ├────────────▶︎[ Join ]
      │                           │                 │
      │              [ Join Confirmation ]◀︎─────────┤
      │                           │                 │
[ Re-connect Instruction ]◀︎━━━━━━━┥                 │
      │                           │                 │
      ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶︎[ Re-connect ]
      │                           │                 │
      │                           │                 │
[ Join Confirmation ]◀︎━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥ Treat join confirmation as migration confirmation.
      │                           │                 │
      ▽                           ▽                 ▽

func NewRoom

func NewRoom(userData *user.User, maxMembers int, allowEmpty bool, join bool, ttl int64, interval int64) (string, error)

NewRoom Creates a new room

Note

Uses mutex lock internally.

Note

This function creates a new room on the same server as it is invoked.

Error Cases:

┌─────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐
│ Error                               │ Reason                                                                       │
╞═════════════════════════════════════╪══════════════════════════════════════════════════════════════════════════════╡
│ allowEmpty and join are false       │ If allowEmpty and join are both false, the room will be deleted immediately. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Server is offline                   │ The server is in offline state (getting ready to shutdown)                   │
│                                     │ and creating new rooms is not allowed.                                       │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Invalid TTL                         │ TTL must be greater than 0 second.                                           │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Incorrect parameters for blank user │ Using a blank user must have allowEmpty=true and join=false parameters.      │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ User in another room                │ You may not join more than one room at a time.                               │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Max member is invalid               │ The range of max member is from 2 to 1000.                                   │
└─────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

room.IsNewRoomError(err error) // Room module failed to create a new room

Parameters

userData   - User data struct.
             If you do not have user available, you may use a dummy user created by user.CreateBlankUser.
             Using a dummy user allows you to create an empty room without having the access to a user.
             With a dummy user, you must have allowEmpty=true, join=false.
maxMembers - Maximum number of members allowed to join the room
allowEmpty - If true, the room will not be deleted until TTL expires even if all members leave
join       - If true, the creator user will join the room automatically
ttl        - TTL of the room when it is empty in seconds. The value must be greater than 0. Minimum is 10 seconds
interval   - Broadcast interval in milliseconds. Interval below 100ms will be forced to 0. If it's 0, no packet merge

func Relay

func Relay(roomID string, sender *user.User, ver uint8, cmd uint16, message []byte, reliable bool) bool

Relay sends a message to all members of the room except for the sender.

Important

This function does NOT work if the room is not on the same server.

Important

Unlike Broadcast, Message, and Announce, Relay does not combine multiple messages.
Therefore, the message sent does not have to be separated by BytesToBytesList on the client side.

Important

Unlike Broadcast, Message, and Announce, Relay does not send the message to the sender user.

Note

Uses mutex lock internally.

Parameters

roomID   - Room ID of the room to send relay message to.
sender   - Sender user. The sender user must be a member of the room.
ver      - Command version of the message sent to the members of the room.
cmd      - Command ID of the message sent to the members of the room.
message  - Message to be sent to the members of the room.
reliable - If true, the message will be sent as an RUDP if the network protocol is UDP.
           If the network protocol used is TCP, this flag is ignored.

func RelayTo

func RelayTo(roomID string, sender *user.User, members []string, ver uint8, cmd uint16, message []byte, reliable bool) bool

RelayTo sends a message to selected members of the room except for the sender.

Important

This function does NOT work if the room is not on the same server.

Important

Unlike Broadcast, Message, and Announce, RelayTo does not combine multiple messages.
Therefore, the message sent does not have to be separated by BytesToBytesList on the client side.

Important

Unlike Broadcast, Message, and Announce, Relay does not send the message to the sender user.

Note

Uses mutex lock internally.

Parameters

roomID   - Room ID of the room to send relay message to.
sender   - Sender user. The sender user must be a member of the room.
members  - An array of target member user IDs to send relay message to.
ver      - Command version of the message sent to the members of the room.
cmd      - Command ID of the message sent to the members of the room.
message  - Message to be sent to the members of the room.
reliable - If true, the message will be sent as an RUDP if the network protocol is UDP.
           If the network protocol used is TCP, this flag is ignored.

func RemoveStateByRoomID

func RemoveStateByRoomID(roomID string, userData *user.User, key string, reliable bool) bool

RemoveStateByRoomID removes a state property and synchronize its removal to all members of the room.

ver and cmd will be used as command ver and command ID when synchronizing with the room members.

User must be a member of the room to use this function.

Important

This function does NOT work if the room is not on the same server.

Note

Uses mutex lock internally.

Parameters

roomID   - The target room ID of the room to remove a state from.
userData - Room member user to perform state removal.
key      - State key to be removed.
reliable - If true, synchronization for UDP communication will be RUDP.

func Reserve

func Reserve(roomID string, userData *user.User, memberIDs []string, mustBeOwner bool) error

Reserve the user may reserve a slot in a room so that it will be guaranteed to join the room later.

Important

This function does not work if the room is not on the same server.

Note

Uses mutex lock internally.

Error Cases:

┌──────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐
│ Error                        │ Reason                                                                       │
╞══════════════════════════════╪══════════════════════════════════════════════════════════════════════════════╡
│ memberIDs array is empty     │ No member IDs to make reservations with.                                     │
├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Room or room owner not found │ Cannot make a reservation if the room and/or its owner is missing.           │
├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Must be owner                │ If mustBeOwner is true, only the room owner is allowed to make reservations. │
├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Room not found               │ Cannot make a reservation if the room is missing.                            │
├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Exceeds max members          │ Make reservations that exceeds max members of the room is not allowed.       │
├──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ Reservation is full          │ There is no more room for reservations.                                      │
└──────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

room.IsReserveError(err error) // Failed to make a reservation of a room

Parameters

roomID      - Target room ID to make a reservation.
userData    - Owner user of the room to make a reservation.
memberIDs   - An array of user IDs to make a reservation for.
mustBeOwner - If true, userData must be the owner of the room.

func SetChatHistoryLimit

func SetChatHistoryLimit(roomID string, limit int) bool

SetChatHistoryLimit sets the chat history maximum length

Important

This function does NOT work if the room is not on the same server.

Note

Uses mutex lock internally.

func SetJoinCondition

func SetJoinCondition(cond func(roomID string, userData *user.User) error)

SetJoinCondition registers a condition function to control room join. Returning an error will cause room join to fail

Join condition is NOT protected by mutex lock.

SetJoinCondition(condition func(roomID string, userData *user.User))

cond func(roomID string, userData *user.User) error - Custom function to be invoked before room join to evaluate join conditions.

func SetOnAnnounce

func SetOnAnnounce(roomID string, cb func(string, uint8, uint16, []byte)) bool

SetOnAnnounce assigns a listener callback on Announce of room

Caution

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.

Caution

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

Caution

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

Caution

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.

Caution

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.

Caution

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

Caution

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.

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.

Caution

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.

Caution

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.

Caution

Using pointer variables that are defined outside of the callback closure
in the callback closure will cause those pointers to be not garbage collected during
the lifespan of the room.

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

Caution

Using pointer variables that are defined outside of the callback closure
in the callback closure will cause those pointers to be not garbage collected during
the lifespan of the room.

Caution

The callbacks are invoked in room.Leave function. If a callback blocks, room.Leave will block also.

Note

Uses mutex lock internally.

func SetOnMigrated

func SetOnMigrated(callback func(currentRoomID string, previousRoomID string))

SetOnMigrated registers a callback on migrated. The callbacks will be invoked on the server node where the room is migrated to

Caution

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.

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

Caution

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

Caution

Using pointer variables that are defined outside of the callback closure
in the callback closure will cause those pointers to be not garbage collected during
the lifespan of the room.

Important

This function does NOT work if the room is not on the same server.

func SetOnRoomDiscard

func SetOnRoomDiscard(cb func(roomID string)) bool

SetOnRoomDiscard registers a callback function on room deletions

Caution

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.

func SetOnRoomDiscardByID

func SetOnRoomDiscardByID(roomID string, callback func(roomID string)) bool

SetOnRoomDiscardByID registers a callback on room deletion by room ID

Caution

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

Caution

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

Caution

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

Caution

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   - Target room ID to set a tick callback.
callback - 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

Caution

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
callback - 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 SetupWithDive

func SetupWithDive(confpath string)

SetupWithDive must be called in the server main function to setup room module before diarkis.Start

func StopClock

func StopClock(roomID string, name string) bool

StopClock stops a clock callback loop

Note

Uses mutex lock internally.

Parameters

roomID - Target room ID of the room to stop the clock callback
name   - Unique name of the clock to stop

func StopTick

func StopTick(roomID string)

StopTick stops room's tick event loop

Note

Uses mutex lock internally.

func SyncAllStatesByRoomID

func SyncAllStatesByRoomID(roomID string, userData *user.User, reliable bool) bool

SyncAllStatesByRoomID synchronizes all existing states to the target user client.

Invoking this function will forcefully send all existing states to the targeted user client.

Important

This function does NOT work if the room is not on the same server.

Note

Uses mutex lock internally.

Parameters

roomID   - The target room ID of the room.
userData - Room member user to receive all state synchronizations.
reliable - If true, synchronization for UDP communication will be RUDP.

func SyncChatMessage

func SyncChatMessage(roomID string, userData *user.User, ver uint8, cmd uint16, message string) bool

SyncChatMessage records the chat message data and synchronize the chat message with room members

Important

This function does NOT work if the room is not on the same server.

Note

Uses mutex lock internally.

func SyncCreateTime

func SyncCreateTime(roomID string, ver uint8, cmd uint16, memberIDs []string)

SyncCreateTime sends room's created time (in seconds) to the selected (or all) members of the room

Important

This function does NOT work if the room is not on the same server.

Note

Uses mutex lock internally.

Parameters

roomID    - Target room ID.
ver       - Command version to be used for the message.
cmd       - Command ID to be used for the message.
memberIDs - An array of member user IDs to sync the room creation time.

func UpdateProperties

func UpdateProperties(roomID string, operation func(properties map[string]interface{}) bool) map[string]interface{}

UpdateProperties updates or creates properties of a room and returns the updated or created properties.

Important

This function does NOT work if the room is not on the same server.

Important

This function DOES update room's internal TTL.

Important

Room properties do NOT support structs.

Important

Numeric properties will be float64. Use util.ToInt, ToUint etc. To convert to proper data type.

Important

Array properties will be []interface{}. Must apply type assertion per element.

Important

Byte array properties will be converted to base64 encoded string. Use util.ToBytes() to convert it back.

Important

Operation function is protected by mutex lock, using another mutex lock within the function may cause a deadlock.

Note

Uses mutex lock internally.

Operation example:

var updateErr error
_ := room.UpdateProperties(roomID, func(properties map[string]interface{}) {
	capsule := datacapsule.NewCapsule()
	err := capsule.Import(properties["roomPropertyCapsule"].(map[string]interface{}))
	if err != nil {
		// this is how to propagate an error
		updateErr = err
		return
	}
	counter := capsule.GetAsInt("counter")
	counter++
	capsule.SetAsInt("counter", counter)
	properties["roomPropertyCapsule"] = capsule.Export()
})
if updateErr != nil {
	// handle update error here
}

Use datacapsule.Capsule as property:

capsule := datacapsule.NewCapsule()
capsule.SetAsInt8("memberNum", memberNum)
properties["memberNum"] = capsule.Export() // setting capsule as a property

Parameters

roomID    - Room ID to update its properties.
operation - Callback function to perform update operations and returns updated properties as a map.
            Must return true, when property (properties) is updated and false when there is no update.

func UpdateStateByRoomID

func UpdateStateByRoomID(roomID string, userData *user.User, key string, value []byte, linkToUser, reliable bool) error

UpdateStateByRoomID updates/creates a state property and synchronize its value to all members of the room.

ver and cmd will be used as command ver and command ID when synchronizing with the room members.

User must be a member of the room to use this function.

Important

This function does NOT work if the room is not on the same server.

Important

Size of the state value and key combined should not exceed 40 bytes in length.

Important

If a state is updated multiple times before synchronized, only the last updated value will be synchronized.

Note

Uses mutex lock internally.

Error Cases:

┌─────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐
│ Error                               │ Reason                                                           │
╞═════════════════════════════════════╪══════════════════════════════════════════════════════════════════╡
│ Room not found                      │ The room tarted to update its state not found or does not exist. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Room state synchronizer not started │ EnableStateSync must be called to enable state synchronization.  │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ User must be a member of the room   │ The user that updates room state must be a member of the room.   │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Invalid value                       │ The value must not be nil or an empty byte array.                │
└─────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

room.IsStateUpdateError(err error) // Failed to update a room state

Parameters

roomID     - Target room ID of the room to update its state.
userData   - The user that is updating a state of the target room.
             If linkToUser flag is set to true, the state will be associated to the user
             and will be removed when the user leaves the room.
key        - Key represents the name of the state to be updated.
value      - Value is used to replace the previous state value.
linkToUser - If the flag is set to true, the state will be linked to the user given.
             When the linked user leaves the room all linked states will be removed.
reliable   - If true, synchronization for UDP communication will be RUDP.

func UpsertStateByRoomID

func UpsertStateByRoomID(roomID string, userData *user.User, key string, reliable bool, cb func(exists bool, current []byte) []byte) error

UpsertStateByRoomID updates/creates a state property and synchronize its value to all members of the room.

ver and cmd will be used as command ver and command ID when synchronizing with the room members.

User must be a member of the room to use this function.

Important

This function does NOT work if the room is not on the same server.

Important

Size of the state value and key combined should not exceed 40 bytes in length.

Important

If a state is updated multiple times before synchronized, only the last updated value will be synchronized.

Important

The callback is invoked while the mutex lock is held and release when the callback finishes its execution.

Note

Uses mutex lock internally.

Error Cases:

┌───────────────────────────────────────┬────────────────────────────────────────────────────────────────────────┐
│ Error                                 │ Reason                                                                 │
╞═══════════════════════════════════════╪════════════════════════════════════════════════════════════════════════╡
│ Room not found                        │ The room tarted to update its state not found or does not exist.       │
├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Room state synchronizer not started   │ EnableStateSync must be called to enable state synchronization.        │
├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ User must be a member of the room     │ The user that updates room state must be a member of the room.         │
├───────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ State value is not updated nor stored │ Upsert callback's return value must not be nil or an empty byte array. │
└───────────────────────────────────────┴────────────────────────────────────────────────────────────────────────┘

Error Evaluations

The possible error evaluations:

room.IsStateUpsertError(err error) // Failed to upsert a room state

Parameters

roomID     - Target room ID of the room to update its state.
userData   - The user that is updating a state of the target room.
             If linkToUser flag is set to true, the state will be associated to the user
             and will be removed when the user leaves the room.
key        - Key represents the name of the state to be updated.
reliable   - If true, synchronization for UDP communication will be RUDP.
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.

Usage Example

UpsertStateByRoomID is useful when you need to reference the value of a state that already exists and update its value based on the current value without the risk of race conditions. The concept is very similar to select for update SQL query.

// this will be the damage inflicted on the state called HP
damage := uint32(-40)

err := room.UpsertStateByRoomID(roomID, userData, "HP", true, func(exists bool, currentValue []byte) (updatedValue []byte) {

  // HP state does not exist yet, initialize it
  if !exists {
    // initial HP is 100
    hp := uint32(100)

    // state value must be a byte array
    bytes := make([]byte, 4)
    binary.BigEndian.PutUint32(bytes, hp)
    // returning bytes will set bytes as HP state's value
    return bytes
  }

  // calculate HP state's new value
  currentHP := binary.BigEndian.Uint32(currentValue)
  currentHP += damage

  // encode the updated HP back to byte array
  bytes := make([]byte, 4)
  binary.BigEndian.PutUint32(bytes, currentHP)

    // returning bytes will set bytes as HP state's value
    return bytes
})

if err != nil {
	// UpsertStateByRoomID failed, handle the error here...
}

Types

type BeforeAfterCommandCallback

type BeforeAfterCommandCallback func(ver uint8, cmd uint16, payload []byte, user *user.User, next func(error))

BeforeAfterCommandCallback Callback used to hook a room command before and after its execution.

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.

type DataDump

type DataDump struct {
	ID         string                 `json:"RoomID"`
	MaxMembers int                    `json:"MaxMembers"`
	AllowEmpty bool                   `json:"AllowEmpty"`
	MemberIDs  map[string]string      `json:"MemberIDs"`
	Properties map[string]interface{} `json:"Properties"`
}

DataDump implies a payload format for the dump room data command

type GetRoomInfoData

type GetRoomInfoData struct {
	RoomID                 string   `json:"roomID"`
	CurrentMembers         uint16   `json:"currentMembers"`
	MaxMembers             uint16   `json:"maxMembers"`
	MemberIDs              []string `json:"memberIDs"`
	OwnerID                string   `json:"ownerID"`
	AllowEmpty             bool     `json:"allowEmpty"`
	TTL                    int64    `json:"TTL"`
	LastPropUpdated        int64    `json:"lastPropUpdated"`
	UpdaterSID             string   `json:"updaterSID"`
	Interval               int64    `json:"interval"`
	Created                int64    `json:"created"`
	Reserves               []string `json:"reserves"`
	AllowTransferOwnership bool     `json:"AllowTransferOwnership"`
}

GetRoomInfoData represents internally used data

func GetRoomInfo

func GetRoomInfo(roomID string) (*GetRoomInfoData, error)

GetRoomInfo retrieves the information of the room.

This can be executed by anyone and they do not have to be part of the room.

Important

This function does NOT update room's internal TTL.

Important

This function works for all users including the users that are not members of the target room.

Parameters
roomID   - Target room ID to get the number of members from.

type JoinRoomCallback

type JoinRoomCallback func(err error, memberIDs []string, ownerID string, createdTime int64)

JoinRoomCallback is callback function for room.Join.

Important

This callback function is invoked on the server where the user is "originally" connected.
room.Join may move the user to a different server
if the room that the user is joining is not on the same server.
When the user is moved to another server, this callback function is invoked on the server where
the user was originally connected.

type Room

type Room struct {
	ID         string
	MaxMembers int
	AllowEmpty bool

	// an array of member SIDs
	Members []string
	// ID as key and SID as value
	MemberIDs map[string]string
}

Room Room data structure

func GetRoomByID

func GetRoomByID(roomID string) *Room

GetRoomByID returns a room

Important

This function does NOT work if the room is not on the same server.

Important

This function does NOT update room's internal TTL.

Note

Uses mutex lock internally.

Note

This will not update TTL of the room.

Parameters

roomID - Target room ID to get the room object.