Commit 5d74bb0b authored by Andrei Mihu's avatar Andrei Mihu
Browse files

Add match signal function.

parent e5f52b53
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -6,6 +6,10 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
## [Unreleased]
### Added
- Add final notification sent to sockets closed via single socket option.
- Add match signal function to server framework.

### Changed
- Match handlers are now required to implement a signal handler function.

## [3.7.0] - 2021-09-28
### Added
+54 −8
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ Dispatcher exposes useful functions to the match. Format:
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, or match_leave.
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

@@ -137,7 +137,7 @@ Dispatcher exposes useful functions to the match. Format:
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, or match_leave.
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

@@ -189,7 +189,7 @@ Dispatcher exposes useful functions to the match. Format:
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, or match_leave.
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

@@ -241,7 +241,7 @@ Dispatcher exposes useful functions to the match. Format:
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, or match_leave.
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

@@ -268,9 +268,9 @@ local function match_loop(context, dispatcher, tick, state, messages)
    print("match " .. context.match_id .. " tick " .. tick)
    print("match " .. context.match_id .. " messages:\n" .. du.print_r(messages))
  end
  if tick < 10 then
--   if tick < 10 then
    return state
  end
--   end
end

--[[
@@ -300,7 +300,7 @@ Dispatcher exposes useful functions to the match. Format:
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, or match_leave.
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

@@ -317,6 +317,51 @@ local function match_terminate(context, dispatcher, tick, state, grace_seconds)
  return state
end

--[[
Called when the match handler receives a runtime signal.

Context represents information about the match and server, for information purposes. Format:
{
  env = {}, -- key-value data set in the runtime.env server configuration.
  executionMode = "Match",
  match_id = "client-friendly match ID, can be shared with clients and used in match join operations",
  match_node = "name of the Nakama node hosting this match",
  match_label = "the label string returned from match_init",
  match_tick_rate = 1 -- the tick rate returned by match_init
}

Dispatcher exposes useful functions to the match. Format:
{
  broadcast_message = function(op_code, data, presences, sender),
    -- numeric message op code
    -- a data payload string, or nil
    -- list of presences (a subset of match participants) to use as message targets, or nil to send to the whole match
    -- a presence to tag on the message as the 'sender', or nil
  match_kick = function(presences)
    -- a list of presences to remove from the match
  match_label_update = function(label)
    -- a new label to set for the match
}

Tick is the current match tick number, starts at 0 and increments after every match_loop call. Does not increment with
calls to match_join_attempt, match_join, match_leave, match_terminate, or match_signal.

State is the current in-memory match state, may be any Lua term except nil.

Data is arbitrary input supplied by the runtime caller of the signal.

Expected return these values (all required) in order:
1. An (optionally) updated state. May be any non-nil Lua term, or nil to end the match.
1. Arbitrary data to return to the runtime caller of the signal. May be a string, or nil.
--]]
local function match_signal(context, dispatcher, tick, state, data)
  if state.debug then
    print("match " .. context.match_id .. " tick " .. tick)
    print("match " .. context.match_id .. " data " .. data)
  end
  return state, "signal received: " .. data
end

-- Match modules must return a table with these functions defined. All functions are required.
return {
  match_init = match_init,
@@ -324,5 +369,6 @@ return {
  match_join = match_join,
  match_leave = match_leave,
  match_loop = match_loop,
  match_terminate = match_terminate
  match_terminate = match_terminate,
  match_signal = match_signal
}
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ require (
	github.com/gorilla/mux v1.8.0
	github.com/gorilla/websocket v1.4.2
	github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0
	github.com/heroiclabs/nakama-common v1.18.0
	github.com/heroiclabs/nakama-common v0.0.0-20211005124542-143e8d8ce05e
	github.com/jackc/pgconn v1.8.1
	github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451
	github.com/jackc/pgtype v1.7.0
+2 −0
+4 −55
Original line number Diff line number Diff line
@@ -16,23 +16,20 @@ package main

import (
	"context"
	"database/sql"
	"flag"
	"fmt"
	"google.golang.org/protobuf/encoding/protojson"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"

	"io/ioutil"
	"path/filepath"

	"github.com/gofrs/uuid"
	"github.com/heroiclabs/nakama/v3/ga"
	"github.com/heroiclabs/nakama/v3/migrate"
@@ -41,6 +38,7 @@ import (
	_ "github.com/jackc/pgx/v4/stdlib"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"google.golang.org/protobuf/encoding/protojson"
)

const cookieFilename = ".cookie"
@@ -116,7 +114,7 @@ func main() {
	}
	startupLogger.Info("Database connections", zap.Strings("dsns", redactedAddresses))

	db, dbVersion := dbConnect(startupLogger, config)
	db, dbVersion := server.DbConnect(startupLogger, config)
	startupLogger.Info("Database information", zap.String("version", dbVersion))

	// Global server context.
@@ -234,55 +232,6 @@ func main() {
	os.Exit(0)
}

func dbConnect(multiLogger *zap.Logger, config server.Config) (*sql.DB, string) {
	rawURL := config.GetDatabase().Addresses[0]
	if !(strings.HasPrefix(rawURL, "postgresql://") || strings.HasPrefix(rawURL, "postgres://")) {
		rawURL = fmt.Sprintf("postgres://%s", rawURL)
	}
	parsedURL, err := url.Parse(rawURL)
	if err != nil {
		multiLogger.Fatal("Bad database connection URL", zap.Error(err))
	}
	query := parsedURL.Query()
	if len(query.Get("sslmode")) == 0 {
		query.Set("sslmode", "prefer")
		parsedURL.RawQuery = query.Encode()
	}

	if len(parsedURL.User.Username()) < 1 {
		parsedURL.User = url.User("root")
	}
	if len(parsedURL.Path) < 1 {
		parsedURL.Path = "/nakama"
	}

	multiLogger.Debug("Complete database connection URL", zap.String("raw_url", parsedURL.String()))
	db, err := sql.Open("pgx", parsedURL.String())
	if err != nil {
		multiLogger.Fatal("Error connecting to database", zap.Error(err))
	}
	// Limit the time allowed to ping database and get version to 15 seconds total.
	ctx, ctxCancelFn := context.WithTimeout(context.Background(), 15*time.Second)
	defer ctxCancelFn()
	if err = db.PingContext(ctx); err != nil {
		if strings.HasSuffix(err.Error(), "does not exist (SQLSTATE 3D000)") {
			multiLogger.Fatal("Database schema not found, run `nakama migrate up`", zap.Error(err))
		}
		multiLogger.Fatal("Error pinging database", zap.Error(err))
	}

	db.SetConnMaxLifetime(time.Millisecond * time.Duration(config.GetDatabase().ConnMaxLifetimeMs))
	db.SetMaxOpenConns(config.GetDatabase().MaxOpenConns)
	db.SetMaxIdleConns(config.GetDatabase().MaxIdleConns)

	var dbVersion string
	if err = db.QueryRowContext(ctx, "SELECT version()").Scan(&dbVersion); err != nil {
		multiLogger.Fatal("Error querying database version", zap.Error(err))
	}

	return db, dbVersion
}

// Help improve Nakama by sending anonymous usage statistics.
//
// You can disable the telemetry completely before server start by setting the
Loading