heroiclabs / nakama-dart

Pure Dart Client for Nakama Server
https://heroiclabs.com/docs/nakama/client-libraries/dart
157 stars 48 forks source link

How to communicate with authoritative multiplayer service? #60

Closed xsodus closed 1 year ago

xsodus commented 1 year ago

I created custom match handlers in the backend part for authoritative multiplayer service. The module was loaded successfully but the handlers were not called when I sent the match data through sendMatchData(). As I checked in the official docs (JS SDK), there is sendMatchState() which can communicate through the custom match handlers. I'm not sure the latest version supports this multiplayer type or do I need call other functions for this.

Custom Handler Scripts match_handler.js

const moduleName: string = "test";
const tickRate: number = 2;

let matchInit: nkruntime.MatchInitFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  params: { [key: string]: string }
) {
  let state: nkruntime.MatchState = {
    presences: {},
  };
  let label = "";
  logger.info("MATCH INITIALIZED :  matchInit CALLED ");
  return {
    state,
    tickRate,
    label,
  };
};

let matchJoinAttempt: nkruntime.MatchJoinAttemptFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  presence: nkruntime.Presence,
  metadata: { [key: string]: any }
) {
  logger.debug("matchJoinAttempt received: ");
  return {
    state: state,
    accept: true,
  };
};

let matchJoin: nkruntime.MatchJoinFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  presences: nkruntime.Presence[]
) {
  logger.debug("matchJoin received: ");
  return { state };
};

let matchLeave: nkruntime.MatchLeaveFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  presences: nkruntime.Presence[]
) {
  logger.debug("matchLeave received: ");
  return { state };
};

let matchLoop: nkruntime.MatchLoopFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  messages: nkruntime.MatchMessage[]
) {
  logger.debug("matchLoop received: ");
  return { state };
};

let matchTerminate: nkruntime.MatchTerminateFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  graceSeconds: number
) {
  logger.debug("matchTerminate received: ");
  return { state };
};

const matchSignal = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  dispatcher: nkruntime.MatchDispatcher,
  tick: number,
  state: nkruntime.MatchState,
  data: string
): { state: nkruntime.MatchState; data?: string } | null {
  logger.debug("Lobby match signal received: " + data);

  return {
    state,
    data: "Lobby match signal received: " + data,
  };
};

let makeMatch: nkruntime.MatchmakerMatchedFunction = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  matches: nkruntime.MatchmakerResult[]
): string | void {
  logger.info("MATCH CREATE IS BEING CALLED");
  let match_id: string = nk.matchCreate(moduleName);
  return match_id;
};

main.js

// Copyright 2020 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.

const rpcIdRewards = "rewards_js";
const rpcIdFindMatch = "find_match_js";

function InitModule(
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  initializer: nkruntime.Initializer
) {
  initializer.registerMatch(moduleName, {
    matchInit,
    matchJoinAttempt,
    matchJoin,
    matchLeave,
    matchLoop,
    matchTerminate,
    matchSignal,
  });

  initializer.registerMatchmakerMatched(makeMatch);

  logger.info("JavaScript logic loaded.");
}

Server Logs

backend           | {"level":"info","ts":"2023-03-20T14:57:06.370Z","caller":"server/runtime_javascript_logger.go:74","msg":"JavaScript logic loaded."}
backend           | {"level":"debug","ts":"2023-03-20T14:58:43.892Z","caller":"server/pipeline.go:65","msg":"Received *rtapi.Envelope_MatchDataSend message","uid":"f1bdd8c7-3e22-4843-b1fd-30910c3909ee","sid":"938d4f54-c72f-11ed-9cac-006100a0eb06","cid":"3","message":{"MatchDataSend":{"match_id":"18c5582b-34bd-478c-b4ac-b2df38d3bb91.","op_code":1,"data":"ZmZmZmY="}}}
backend           | {"level":"debug","ts":"2023-03-20T15:21:48.726Z","caller":"server/pipeline.go:65","msg":"Received *rtapi.Envelope_MatchDataSend message","uid":"f1bdd8c7-3e22-4843-b1fd-30910c3909ee","sid":"938d4f54-c72f-11ed-9cac-006100a0eb06","cid":"4","message":{"MatchDataSend":{"match_id":"18c5582b-34bd-478c-b4ac-b2df38d3bb91.","op_code":1,"data":"d3d3dw=="}}}
xsodus commented 1 year ago

I got the answer that we need the send & receive match state function which is still being developed. Ref: https://github.com/obrunsmann/flutter_nakama/issues/40

xsodus commented 1 year ago

I got the answer that we need the send & receive match state function which is still being developed. Ref: #40

I'm not sure that you still continue to implement that feature. Can someone confirm this?

obrunsmann commented 1 year ago

@xsodus the respective methods are sendMatchData and onMatchData.