Last active
September 21, 2017 15:25
-
-
Save novabyte/54217a8b8540e3b7c0d69104c6705a30 to your computer and use it in GitHub Desktop.
Implement custom asynchronous match "rooms" on Nakama server.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Copyright 2017 The Nakama Authors | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
]]-- | |
local nk = require("nakama") | |
------------ | |
-- A module which implements room-based matches which store state for a card game. | |
-- @module matchrooms | |
local M = {} | |
local matchrooms_mt = { | |
__name = "matchrooms_system", | |
__index = M | |
} | |
--- Display Matchrooms "object" in a readable way when printed. | |
function M:__tostring() | |
local matches_json = nk.json_encode(self.matches) | |
return ("matchrooms{bucket=%q, collection=%q, matches=%q}"):format(self.bucket, self.collection, matches_json) | |
end | |
--- Add a matchroom to the server unless it has been restored. | |
-- @param match_id The ID of the matchroom to add. | |
-- @param name The name for the matchroom. | |
function M:add_room(match_id, name) | |
local update_ops = { | |
{Op = "init", Path = "/state", Value = {}}, | |
{Op = "init", Path = "/name", Value = name}, | |
{Op = "replace", Path = "/name", Value = name} | |
} | |
local record = { | |
Bucket = self.bucket, | |
Collection = self.collection, | |
Record = match_id, | |
UserId = nil, | |
Update = update_ops, | |
PermissionRead = 2, | |
PermissionWrite = 0 | |
} | |
nk.storage_update({ record }) | |
self.matches[match_id] = nk.storage_fetch({ record })[1] | |
end | |
--- Check if a matchroom id has been defined. | |
-- @param match_id The ID of the match to validate. | |
function M:isvalid(match_id) | |
return self.matches[match_id] ~= nil | |
end | |
--- List matchrooms available on the server. | |
function M:list() | |
return self.matches | |
end | |
--- Join a match and receive the latest match state. | |
-- @param match_id The ID of the match to join. | |
-- @return The current state of the match. | |
function M:join_match(match_id, user_id) | |
local record = { | |
Bucket = self.bucket, | |
Collection = self.collection, | |
Record = match_id, | |
UserId = nil | |
} | |
local records = nk.storage_fetch({ record }) | |
local match_state = records[1].Value.state | |
-- execute join callback | |
match_state = self.match_logic_onjoin(match_state, records[1].Value.name, user_id) | |
self.matches[match_id] = match_state | |
return match_state | |
end | |
--- Run logic callback on match state and update. | |
-- @param match_id The ID of the match. | |
-- @param user_id The ID of the user who's sent the command. | |
-- @param command The Lua table for the command message. | |
function M:send_command(match_id, user_id, command) | |
local record = { | |
Bucket = self.bucket, | |
Collection = self.collection, | |
Record = match_id, | |
UserId = nil | |
} | |
local records = nk.storage_fetch({ record }) | |
local match_state = records[1].Value.state | |
match_state = self.match_logic_oncommand(match_state, match_id, user_id, command) | |
record.Value.state = match_state | |
record.PermissionRead = 2 | |
record.PermissionWrite = 0 | |
nk.storage_write({ record }) | |
end | |
--- Restore matchrooms from the storage engine at server start. | |
-- @param bucket The bucket to store matches in. | |
-- @param collection The collection to store matches in. | |
local function restore_rooms(bucket, collection) | |
local matches = {} | |
local records = nk.storage_list(nil, bucket, collection, 100, nil) | |
for k, v in pairs(records) | |
do | |
matches[k] = v | |
end | |
return matches | |
end | |
--- Build a new matchrooms object. | |
-- @param bucket The bucket to store matches in. | |
-- @param collection The collection to store matches in. | |
local function new_matchrooms(bucket, collection) | |
bucket = bucket or error("'bucket' parameter must be set.") | |
collection = collection or error("'collection' parameter must be set.") | |
return setmetatable({ | |
bucket = bucket, | |
collection = collection, | |
matches = restore_rooms(bucket, collection), | |
match_logic_oncommand = function(match_state, match_id, user_id, command) | |
nk.logger_info(("User %q played."):format(user_id)) | |
return match_state | |
end, | |
match_logic_onjoin = function(match_state, match_id, user_id) | |
nk.logger_info(("User %q joined."):format(user_id)) | |
return match_state | |
end | |
}, matchrooms_mt) | |
end | |
return { | |
new = new_matchrooms | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Copyright 2017 The Nakama Authors | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
]]-- | |
local nk = require("nakama") | |
local matchrooms = require("matchrooms").new("mygamebucket", "matchrooms") | |
-- define logic for a match | |
matchroom:setup_matchlogic( | |
-- called on each command message from a user | |
function(match_state, match_id, user_id, command) | |
local command_json = nk.json_encode(command) | |
local match_state_json = nk.json_encode(match_state) | |
local message = ("match{match_id=%q, user_id=%q, command=%q, match_state=%q}"):format(match_id, user_id, command_json, match_state_json) | |
nk.logger_info(message) | |
--[[ | |
ADD CUSTOM COMMAND LOGIC FOR GAME | |
]]-- | |
-- must return match_state for sync | |
return match_state | |
end, | |
-- called when a user joins | |
function(match_state, match_id, user_id) | |
local match_state_json = nk.json_encode(match_state) | |
local message = ("match{match_id=%q, user_id=%q, match_state=%q}"):format(match_id, user_id, match_state_json) | |
nk.logger_info(message) | |
-- must return match_state for sync | |
return match_state | |
end) | |
-- add/restore rooms at startup | |
matchrooms:add_room("eca4a141-20a3-4a61-9957-f1986bc37bef", "Room 1") | |
matchrooms:add_room("27918c32-ad8e-4113-a82d-de7409c87ba1", "Room 2") | |
matchrooms:add_room("3d98b68a-e193-43b7-8a54-d19da2bcdd6d", "Room 3") | |
matchrooms:add_room("b0d20dfc-1c67-42e5-a11b-34cbb680b208", "Room 4") | |
matchrooms:add_room("41c1a0d4-9934-44bd-8efa-8e0392cf6cd9", "Room 5") | |
-- enable clients to "join" a matchroom | |
-- payload input: | |
-- { "id": "some_match_id" } | |
local function join_matchroom(context, payload) | |
local json = nk.json_decode(payload) | |
local match_id = json.id or error("'id' parameter must be sent in payload.") | |
local _ = matchrooms:isvalid(match_id) or error(("match with id %q does not exist."):format(match_id)) | |
local match_state = matchrooms:join_match(match_id, context.UserId) | |
return nk.json_encode(match_state) | |
end | |
nk.register_rpc(join_matchroom, "join_matchroom_rpc") | |
-- enable clients to fetch available rooms | |
local function list_matchrooms(_context, _payload) | |
local allmatches = matchrooms:list() | |
return nk.json_encode(allmatches) | |
end | |
nk.register_rpc(list_matchrooms, "list_matchrooms_rpc") | |
-- send a command from a client to the match | |
-- payload input: | |
-- { "id": "some_match_id", "command": { "some": "json" } } | |
local function send_matchroom_command(context, payload) | |
local json = nk.json_decode(payload) | |
local match_id = json.id or error("'id' parameter must be sent in payload.") | |
local _ = matchrooms:isvalid(match_id) or error(("match with id %q does not exist."):format(match_id)) | |
local command = json.command or error("'command' parameter must be sent in payload.") | |
matchrooms:send_command(match_id, context.UserId, command) | |
end | |
nk.register_rpc(send_matchroom_command, "send_matchroom_command_rpc") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment