Merge pull request #22 from josephbmanley/feature/match
Create Custom Match Plugin
This commit is contained in:
commit
b35208cbb0
8
.github/workflows/build_dev.yml
vendored
8
.github/workflows/build_dev.yml
vendored
@ -57,18 +57,16 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Build Plugin
|
- name: Build Nakma Plugin
|
||||||
id: build_plugin
|
id: build_plugin
|
||||||
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
||||||
with:
|
with:
|
||||||
nakamaVersion: "2.12.0"
|
nakamaVersion: "2.12.0"
|
||||||
moduleDirectory: server/plugins/world_rpc
|
moduleDirectory: server/plugin
|
||||||
- name: Move Binary
|
- name: Move Binary
|
||||||
env:
|
|
||||||
plugin: ${{ steps.build_plugin.outputs.binary }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p server/data/modules
|
mkdir -p server/data/modules
|
||||||
mv $plugin server/data/modules
|
mv ${{ steps.build_plugin.outputs.binary }} server/data/modules
|
||||||
- id: get_tag
|
- id: get_tag
|
||||||
name: Get Tag
|
name: Get Tag
|
||||||
env:
|
env:
|
||||||
|
8
.github/workflows/build_release.yml
vendored
8
.github/workflows/build_release.yml
vendored
@ -52,18 +52,16 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Build Plugin
|
- name: Build Nakma Plugin
|
||||||
id: build_plugin
|
id: build_plugin
|
||||||
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
||||||
with:
|
with:
|
||||||
nakamaVersion: "2.12.0"
|
nakamaVersion: "2.12.0"
|
||||||
moduleDirectory: server/plugins/world_rpc
|
moduleDirectory: server/plugin
|
||||||
- name: Move Binary
|
- name: Move Binary
|
||||||
env:
|
|
||||||
plugin: ${{ steps.build_plugin.outputs.binary }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p server/data/modules
|
mkdir -p server/data/modules
|
||||||
mv $plugin server/data/modules
|
mv ${{ steps.build_plugin.outputs.binary }} server/data/modules
|
||||||
- id: get_tag
|
- id: get_tag
|
||||||
name: Get Tag
|
name: Get Tag
|
||||||
env:
|
env:
|
||||||
|
8
.github/workflows/build_stage.yml
vendored
8
.github/workflows/build_stage.yml
vendored
@ -39,18 +39,16 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Build Plugin
|
- name: Build Nakma Plugin
|
||||||
id: build_plugin
|
id: build_plugin
|
||||||
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
uses: josephbmanley/build-nakama-plugin-action@v0.1.1
|
||||||
with:
|
with:
|
||||||
nakamaVersion: "2.12.0"
|
nakamaVersion: "2.12.0"
|
||||||
moduleDirectory: server/plugins/world_rpc
|
moduleDirectory: server/plugin
|
||||||
- name: Move Binary
|
- name: Move Binary
|
||||||
env:
|
|
||||||
plugin: ${{ steps.build_plugin.outputs.binary }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p server/data/modules
|
mkdir -p server/data/modules
|
||||||
mv $plugin server/data/modules
|
mv ${{ steps.build_plugin.outputs.binary }} server/data/modules
|
||||||
- name: Get Docker Repo Name
|
- name: Get Docker Repo Name
|
||||||
id: find_repo
|
id: find_repo
|
||||||
run: |
|
run: |
|
||||||
|
@ -31,9 +31,18 @@ func login(_text=""):
|
|||||||
# Check for error
|
# Check for error
|
||||||
if error:
|
if error:
|
||||||
passwordEdit.text = ""
|
passwordEdit.text = ""
|
||||||
errorLabel.add_color_override("font_color", Color.red)
|
display_message(error.message)
|
||||||
errorLabel.text = error.message
|
|
||||||
else:
|
else:
|
||||||
errorLabel.add_color_override("font_color", Color.green)
|
display_message("Logged in successfully!", Color.green)
|
||||||
errorLabel.text = "Logged in successfully!"
|
display_message("Connecting to server...", Color.gray)
|
||||||
print("Logged in successfully!")
|
error = yield(ServerConnection.connect_to_server_async(), "completed")
|
||||||
|
if error:
|
||||||
|
display_message(error.message)
|
||||||
|
else:
|
||||||
|
display_message("Connected to server!", Color.green)
|
||||||
|
yield(ServerConnection.join_world_async(), "completed")
|
||||||
|
|
||||||
|
func display_message(message="", color=Color.red):
|
||||||
|
errorLabel.add_color_override("font_color", color)
|
||||||
|
errorLabel.text = message
|
||||||
|
print(message)
|
||||||
|
@ -5,6 +5,7 @@ const SERVER_ENDPOINT := "nakama.cloudsumu.com"
|
|||||||
|
|
||||||
var _session : NakamaSession
|
var _session : NakamaSession
|
||||||
var _client : NakamaClient = Nakama.create_client(KEY, SERVER_ENDPOINT, 7350, "http")
|
var _client : NakamaClient = Nakama.create_client(KEY, SERVER_ENDPOINT, 7350, "http")
|
||||||
|
var _socket : NakamaSocket
|
||||||
|
|
||||||
func authenticate_async(email : String, password : String) -> NakamaException:
|
func authenticate_async(email : String, password : String) -> NakamaException:
|
||||||
var result : NakamaException = null
|
var result : NakamaException = null
|
||||||
@ -21,7 +22,7 @@ func authenticate_async(email : String, password : String) -> NakamaException:
|
|||||||
func signup_async(email : String, password : String) -> NakamaException:
|
func signup_async(email : String, password : String) -> NakamaException:
|
||||||
var result : NakamaException = null
|
var result : NakamaException = null
|
||||||
|
|
||||||
var new_session : NakamaSession = yield(_client.authenticate_email_async(email, password, null, true), "completed")
|
var new_session : NakamaSession = yield(_client.authenticate_email_async(email, password, email, true), "completed")
|
||||||
|
|
||||||
if not new_session.is_exception():
|
if not new_session.is_exception():
|
||||||
_session = new_session
|
_session = new_session
|
||||||
@ -29,3 +30,23 @@ func signup_async(email : String, password : String) -> NakamaException:
|
|||||||
result = new_session.get_exception()
|
result = new_session.get_exception()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
func connect_to_server_async() -> NakamaException:
|
||||||
|
_socket = Nakama.create_socket_from(_client)
|
||||||
|
var result : NakamaAsyncResult = yield(_socket.connect_async(_session), "completed")
|
||||||
|
if not result.is_exception():
|
||||||
|
_socket.connect("closed", self, "_on_socket_closed")
|
||||||
|
return null
|
||||||
|
return result.exception
|
||||||
|
|
||||||
|
func join_world_async() -> Dictionary:
|
||||||
|
var world : NakamaAPI.ApiRpc = yield(_client.rpc_async(_session, "get_world_id", ""), "completed")
|
||||||
|
if world.is_exception():
|
||||||
|
print("Join world error occured: %s" % world.exception.message)
|
||||||
|
return {}
|
||||||
|
var _world_id : String = world.payload
|
||||||
|
print(_world_id)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
func _on_socket_closed():
|
||||||
|
_socket = null
|
||||||
|
73
server/plugin/control/control.go
Normal file
73
server/plugin/control/control.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/heroiclabs/nakama-common/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Match struct{}
|
||||||
|
|
||||||
|
type MatchState struct {
|
||||||
|
presences map[string]runtime.Presence
|
||||||
|
inputs map[string]string
|
||||||
|
positions map[string]string
|
||||||
|
jumps map[string]string
|
||||||
|
colors map[string]string
|
||||||
|
names map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, params map[string]interface{}) (interface{}, int, string) {
|
||||||
|
state := &MatchState{
|
||||||
|
presences: map[string]runtime.Presence{},
|
||||||
|
inputs: map[string]string{},
|
||||||
|
positions: map[string]string{},
|
||||||
|
jumps: map[string]string{},
|
||||||
|
colors: map[string]string{},
|
||||||
|
names: map[string]string{},
|
||||||
|
}
|
||||||
|
tickRate := 10
|
||||||
|
label := "{\"name\": \"Game World\"}"
|
||||||
|
|
||||||
|
return state, tickRate, label
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, metadata map[string]string) (interface{}, bool, string) {
|
||||||
|
mState, _ := state.(*MatchState)
|
||||||
|
if _, ok := mState.presences[presence.GetUserId()]; ok {
|
||||||
|
return mState, true, ""
|
||||||
|
} else {
|
||||||
|
return mState, false, "User already logged in."
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchJoin(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
||||||
|
mState, _ := state.(*MatchState)
|
||||||
|
for _, precense := range presences {
|
||||||
|
mState.presences[precense.GetUserId()] = precense
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
||||||
|
mState, _ := state.(*MatchState)
|
||||||
|
for _, presence := range presences {
|
||||||
|
delete(mState.presences, presence.GetUserId())
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, messages []runtime.MatchData) interface{} {
|
||||||
|
// Custom code to:
|
||||||
|
// - Process the messages received.
|
||||||
|
// - Update the match state based on the messages and time elapsed.
|
||||||
|
// - Broadcast new data messages to match participants.
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) MatchTerminate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, graceSeconds int) interface{} {
|
||||||
|
return state
|
||||||
|
}
|
24
server/plugin/family_plugin.go
Normal file
24
server/plugin/family_plugin.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"github.com/heroiclabs/nakama-common/runtime"
|
||||||
|
"github.com/josephbmanley/family/server/plugin/control"
|
||||||
|
"github.com/josephbmanley/family/server/plugin/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
|
||||||
|
logger.Info("Loaded family plugin!")
|
||||||
|
|
||||||
|
if err := initializer.RegisterMatch("control", func(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) (runtime.Match, error) {
|
||||||
|
return &control.Match{}, nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := initializer.RegisterRpc("get_world_id", rpc.GetWorldId); err != nil {
|
||||||
|
logger.Error("Unable to register: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
module world_rpc
|
module github.com/josephbmanley/family/server/plugin
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
@ -13,8 +13,8 @@ github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgj
|
|||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/heroiclabs/nakama-common v1.5.1 h1:ViCm9AvYYdQOCSKEa34SuSQ80JyZOHl6ODawESWf2wk=
|
github.com/heroiclabs/nakama-common v1.5.1 h1:ViCm9AvYYdQOCSKEa34SuSQ80JyZOHl6ODawESWf2wk=
|
||||||
github.com/heroiclabs/nakama-common v1.5.1/go.mod h1:nZAXHdeo4SyPlCyf7pU9rCVizxEhBF74gt7teDe/EaQ=
|
github.com/heroiclabs/nakama-common v1.5.1/go.mod h1:nZAXHdeo4SyPlCyf7pU9rCVizxEhBF74gt7teDe/EaQ=
|
||||||
github.com/heroiclabs/nakama-common v1.6.0 h1:2ZUNI3y8LnEpLEXUXYfERgWS1nm1l0TKPAwnyGMU96U=
|
github.com/heroiclabs/nakama-common v1.7.2 h1:FQedePGCorBl3tXW4Ro8+XLGbEDQfGrT5Tb07j1UaLc=
|
||||||
github.com/heroiclabs/nakama-common v1.6.1 h1:A2n8Jsr+wGuK8qQj5enMpu65NigChrcAMZYDLAJMY88=
|
github.com/josephbmanley/family v0.0.0-20200815220504-0d9d05943cef h1:6oijVkew6eKI1fGE+YMaxmiNlp/hkN9wDpStoid9/ZI=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
52
server/plugin/rpc/rpc.go
Normal file
52
server/plugin/rpc/rpc.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"github.com/heroiclabs/nakama-common/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getFirstWorld(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) (string, error) {
|
||||||
|
|
||||||
|
// List existing matches
|
||||||
|
// that have been 1 & 4 players
|
||||||
|
minSize := 1
|
||||||
|
maxSize := 4
|
||||||
|
matches, listErr := nk.MatchList(ctx, 1, false, "", &minSize, &maxSize, "") //local matches = nakama.match_list()
|
||||||
|
|
||||||
|
// Return if listing error
|
||||||
|
if listErr != nil {
|
||||||
|
logger.Printf("Failed to list matches when grabing first world! Error: %v\n", listErr)
|
||||||
|
return "", listErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no matches exist, create one
|
||||||
|
if len(matches) <= 0 {
|
||||||
|
|
||||||
|
// Create match
|
||||||
|
//params := map[string]interface{}{}
|
||||||
|
matchID, createErr := nk.MatchCreate(ctx, "control", map[string]interface{}{})
|
||||||
|
//return nakama.match_create("world_control", {})
|
||||||
|
|
||||||
|
// Return if creation error
|
||||||
|
if createErr != nil {
|
||||||
|
logger.Printf("Failed to create match when grabing first world! Error: %v\n", createErr)
|
||||||
|
return "", createErr
|
||||||
|
}
|
||||||
|
logger.Info("Successfully created new match!")
|
||||||
|
|
||||||
|
// Return newly created match
|
||||||
|
return matchID, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Return first found match
|
||||||
|
return matches[0].GetMatchId(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWorldId(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
|
||||||
|
matchID, err := getFirstWorld(ctx, logger, nk)
|
||||||
|
return matchID, err
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/heroiclabs/nakama-common/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
|
|
||||||
logger.Info("Loaded World RPC plugin!")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Reference in New Issue
Block a user