-
-
Notifications
You must be signed in to change notification settings - Fork 21
Rooms
You can think of a core.Room
as a place on the server where a core.User
can enter to interact with other User
s. Room
s can be created by the server, or by a client if your custom server rules allow it. Before a Room
can be made, the server needs to know what type of Room
s can be made, and only those types of Room
will be accepted for creation.
⚠️ Warning: When you have a*core.Room
pointer in your code, DO NOT de-reference it. Instead, there are many methods for*Room
for retrieving any information about them you could possibly need. De-referencing them could cause data races (which will panic and stop the server) in theRoom
fields that get locked for synchronizing access.
A RoomType
defines a type of room that can be made on the server. RoomType
s can only be created before starting the server. Here's an example of how to use the NewRoomType()
method to make a RoomType
:
package main
import (
"github.com/hewiefreeman/GopherGameServer"
"github.com/hewiefreeman/GopherGameServer/core"
)
func main() {
// Make a RoomType
rt := core.NewRoomType("gameRoom", true)
// Start the server
gopher.Start(nil)
}
This creates a new RoomType
named "gameRoom" before starting the server. The second boolean parameter makes the room a server-only room when true, which means clients cannot create, destroy, or manipulate Room
s of that RoomType
in any way.
RoomType
s can have broadcasts set for when a User
enters or leaves. A broadcast sends a message to all Users
in the Room
notifying them that another User
has entered or left the room. You can set the broadcasts for a RoomType
when creating one with the EnableBroadcastUserEnter()
and EnableBroadcastUserLeave()
methods:
package main
import (
"github.com/hewiefreeman/GopherGameServer"
"github.com/hewiefreeman/GopherGameServer/core"
)
func main() {
// Make a RoomType
rt := core.NewRoomType("gameRoom", true)
// Enable broadcasts
rt.EnableBroadcastUserEnter()
rt.EnableBroadcastUserLeave()
// Can also be typed like:
// rt.EnableBroadcastUserEnter().EnableBroadcastUserLeave()
// Start the server
gopher.Start(nil)
}
Now, when a User
enters a Room
of type "gameRoom", all other User
s in the room will be sent a message notifying them of the entrance. Same goes for when a User
leaves a Room
of that type.
RoomType
s can have callbacks set for when you want to run your own code when a specific action is taken upon it. RoomType
s have 4 callbacks: create, delete, User
enter, and User
leave. They can be set with the methods SetCreateCallback()
, SetDeleteCallback()
, SetUserEnterCallback()
, and SetUserLeaveCallback()
:
package main
import (
"github.com/hewiefreeman/GopherGameServer"
"github.com/hewiefreeman/GopherGameServer/core"
)
func main() {
// Make a RoomType
rt := core.NewRoomType("gameRoom", true)
// Set callbacks
rt.SetCreateCallback(onCreateGameRoom)
rt.SetDeleteCallback(onDeleteGameRoom)
rt.SetUserEnterCallback(onEnterGameRoom)
rt.SetUserLeaveCallback(onLeaveGameRoom)
// Start the server
gopher.Start(nil)
}
func onCreateGameRoom(room *core.Room) {
// Code to run after a Room of type "gameRoom" is created
}
func onDeleteGameRoom(room *core.Room) {
// Code to run after a Room of type "gameRoom" is deleted
}
func onEnterGameRoom(room *core.Room, roomUser *core.RoomUser) {
// Code to run after a User enters a Room of type "gameRoom"
// To get the *User:
// u := roomUser.User()
}
func onLeaveGameRoom(room *core.Room, roomUser *core.RoomUser) {
// Code to run after a User leaves a Room of type "gameRoom"
// To get the *User:
// u := roomUser.User()
}
The create and delete callback functions need to accept a *core.Room
, which you can use to manipulate the newly created (or deleted) Room
, or whatever else you may want to do with it. The enter and leave callbacks accept a *core.Room
as well as a *core.RoomUser
, which represents the entering/leaving User
. You can use the *RoomUser.User()
method to get the *User
from a *RoomUser
, as per the example above.
The methods to create and delete Room
s are core.NewRoom()
and *Room.Delete()
:
package main
import (
"github.com/hewiefreeman/GopherGameServer"
"github.com/hewiefreeman/GopherGameServer/core"
"fmt"
"time"
)
func main() {
// Make a RoomType
core.NewRoomType("gameRoom", true)
// Make a new Room named "game#958427" of type "gameRoom"
room, roomErr := core.NewRoom("game#958427", "gameRoom", false, 20, "")
if roomErr != nil {
fmt.Println(roomErr)
return
}
// Run a goroutine that deletes the room after 15 seconds
go deleteRoom(room)
// Start the server
gopher.Start(nil)
}
func deleteRoom(room *core.Room) {
// Sleep goroutine for 15 seconds
time.Sleep(time.Second * 15)
// Delete the previously created Room
room.Delete()
}
In the main
thread I've created a RoomType
and a Room
of that type, caught any error that might have happened creating the Room
, ran a goroutine, and started the server. The spawned goroutine waits 15 seconds, then deletes the new Room
created from the main
thread. This is just a simple program to showcase creating and deleting a Room
.
Room variables provide you with a means of storing and receiving data attached to a room. You can set a Room
variable with *Room.SetVariable()
, or multiple at once with *Room.SetVariables()
. Likewise, you can get a Room
variable with *Room.GetVariable()
, or multiple with *Room.GetVariables()
. Here's an example using all four methods:
// Make a Room
room, roomErr := core.NewRoom("test", "game", false, 0, "")
if roomErr != nil {
fmt.Println(roomErr)
return
}
// Set a Room variable
room.SetVariable("team1Points", 0)
// Make or use a map[string]interface{} to set multiple Room variables at once
varMap := map[string]interface{}{
"team2Points": 0,
"team1Players": []string{},
"team2Players": []string{},
}
room.SetVariables(varMap)
// Get a single Room variable at a time
t1Points, _ := room.GetVariable("team1Points") // Expected: 0
something, _ := room.GetVariable("doesntExist") // Expected: nil
// Get multiple Room variables at a time
t2, _ := room.GetVariables([]string{"team2Points", "team2Players"}) // Expected: map["team2Points": 0, "team2Players": []]
Chat messaging is taken care of by the client API. All Room
s have chat built-in and does not require any additional configuration on the server side. Though, if you wish to send a fake chat message to a Room
you can use the *Room.ChatMessage()
method described in the documentation. Notice the method takes in an interface{}
. This allows chat messages to use any data type compatible with JSON, so you can send almost any sort of information along with your chat messages.
Much like chat messaging, voice chat is (for the most part) taken care of by the client API. The only difference is you need to enable voice chat for your RoomType
s. You can enable voice chat for a RoomType
with the *RoomType.EnableVoiceChat
method:
// Make a RoomType
gameRoomType := core.NewRoomType("gameRoom", true)
// Enable voice chat for "gameRoom" RoomType
gameRoomType.EnableVoiceChat()
A server message is essentially a chat message generated and sent from the server itself for any notices, warnings, etc. You can send a server message to a room with the *Room.ServerMessage()
method:
message := "Team 1 wins!"
messageType := core.ServerMessageGame
room.ServerMessage(message, messageType, nil)
ServerMessage()
takes in a message, message type, and a list of recipients. The message can be any data type compatible with JSON (like chat messages), and the message type is an integer that you can either make custom definitions for, or use one of ServerMessageGame
, ServerMessageNotice
, or ServerMessageImportant
. The recipients is a slice of string that lists the User
name of the User
s you want to send the message to. A nil
recipient list will send the message to all users in the Room
.
A data message is also a message generated and sent directly from the server. Unlike a server message, a data message's primary usage is to send some sort of data to User
s in the Room
as efficiently as possible. A data message is more efficient for sending real-time data to User
s because it doesn't come with an author (like chat messages), or a message type (like server messages). Only the data itself is sent. You can send a data message with the *Room.DataMessage()
method:
data := make(map[string]interface{})
data[x] = 12
data[y] = 56
room.DataMessage(data, nil)
The second parameter in DataMessage()
is a recipients list, and works exactly like the recipients list in ServerMessage()
. You can either pass a slice of string with a list of User
names, or nil
to send the data message to all Users
in the Room
.
If you notice there is lacking information, missing features, or bad explanations, please open an issue. All requests are acceptable and will be taken into consideration.