Skip to main content

Client-Server Communication

Multiplayer games usually require the server and client to have communication. This is done by creating a server-side module and client-side scripts that send events to one another.

Overview

Here is a quick overview on setting up client to server communication:

  1. Create the server module using a TypeScript class extending the BaseModule.
  2. Include this module in the list within the ServerConfig.json file.
  3. Create a client script using TypeScript and use the NetworkEventManager to listen or trigger server events.

Client Server

Server Code

The Server folder is within the root Unity project folder (outside of the Assets folder) and contains the necessary server code and custom server modules.

Server Module Libraries

Under the Server > src > Core folder, there are multiple server module scripts. These are the essential libraries that custom modules will import.

Server Libraries

Server Module Examples

Under the Server > src > Examples folder, there are multiple custom server module scripts that have useful examples with logic such as collectibles, physics, and NPCs.

Server Examples

Updating Server Config

The ServerConfig.json file needs to be updated to include new server modules scripts. Only update the ServerConfig.json file located in the Assets > Experience > Server folder.

tip

See the example below for how to add a custom server module to the ServerConfig.json file.

Updating Server Code

Once a custom server script module is created and added to the server config file, the server code needs to be updated.

If using the localhost server target, then the server code is automatically updated with any changes. If using remote server target, then use the sync and verify server code buttons in the Multiplayer window after changing or adding any server code.

Sync Verify

Server Module API

The server module script uses the SFS2X API instead of the Unity API.

SFS2X Namespace

The Smart Fox Server API has its classes in the SFS2X namespace for the server module scripts to use.

Here is an example line of code to import the SFSUser class:

type SFSUser = SFS2X.Entities.SFSUser;
tip

Check out the SmartFoxServer 2X C# API documentation for more information.

Server Libraries

One key difference is the server-specific libraries available are all within the Unity project root folder Server > src > Core.

Here is an example line of code to import the BaseModule class:

import { BaseModule } from "Core/Modules/BaseModule";
tip

Open the BaseModule.ts file to see the inherited methods when creating a custom server module such as init or onUserJoined.

Trace Method

This method will display a string to the server logs:

trace(message: string)
tip

The server logs are visible using the Multiplayer window section named Remote Server Logs.

Add Request Handler Method

This method will connect a listener function to a specific event:

addRequestHandler(eventName: string, listenerFn: reqHandlerFn)

Send Method

This method will trigger a specific event to certain user recipients with any necessary parameters:

send(eventName: string, params: any, recipients: SFSUser[])

Network Event Manager API

The NetworkEventManager class manages all the events being sent across the server and the client. Client scripts can use it to listen and trigger server events.

import {NetworkEventManager} from "Genies.Components.Sdk.External.Multiplayer";

let eventManager: NetworkEventManager;

//Listen to server events
eventManager.AddListener();

//Trigger server events
eventManager.SendServerRequestAsync();

TypeScript Example

Here are three example scripts to create client to server communication.

Server Module Script

Here is an example script of a server module communicating with client scripts:

type SFSUser = SFS2X.Entities.SFSUser;
type BaseEvent = SFS2X.BaseEvent;

import { BaseModule } from "Core/Modules/BaseModule";

export class ServerModule extends BaseModule {
public name: string = "ServerModule";
private _usersJoined: SFSUser[] = [];

public constructor() {
super();
trace(`Server Module is created!`);
}

public init(modules: any): void {
//Adding listener method to event
addRequestHandler("start_game", this.onStartGame.bind(this));

trace(`Server Module is initialized!`);
}

public destroy(): void {
trace(`Server Module is destroyed!`);
}

public onUserJoined(event: BaseEvent): void {
var user = event.getParameter(SFSEventParam.USER);
this._usersJoined.push(user);
}

public onUserDisconnected(event: BaseEvent): void {
try {
var user = event.getParameter(SFSEventParam.USER);
this._usersJoined = this._usersJoined.filter(u => u !== user);
trace(`User disconnected: ${user.name} total users: ${this._usersJoined.length}`);
} catch (error) {
trace(`[delayStart] Error: ${error} | ${error.stack}`);
}
}

private onStartGame(params: any, user: SFSUser): void {
trace(`Received start game from client!`);
//Trigger an event
send("on_start_game", new SFSObject(), this._usersJoined);
}
}

Server Config JSON File

Here is the necessary module reference in the ServerConfig.json file for the server module to be recognized:

{
"v": 1,
"sdkVersion": "0.0.4",
"playerEnabled": true,
"itemsEnabled": true,
"inventoryEnabled": true,
"rewardsEnabled": true,
"storeEnabled": true,
"modules": [
{
"modulePath": "Examples/ServerModule.js",
"className": "ServerModule"
}
]
}
note

The module needs to be referenced as a .js file in order for it to work with the Smart Fox Server API.

Client Script

Here is an example client script to communicate with the server module:

import { NetworkEventManager, NetworkPlayerManager } from "Genies.Components.Sdk.External.Multiplayer";
import { NetworkPlayer } from "Genies.Components.Sdk.External.Multiplayer.Player";
import { SFSObject } from "Sfs2X.Entities.Data";
import { MonoBehaviour } from "UnityEngine";

export default class ClientScript extends MonoBehaviour {

public playerManager: NetworkPlayerManager;
public eventManager: NetworkEventManager;

private Awake() : void {
this.playerManager.OnLocalPlayerCreated.AddListener(this.OnLocalPlayerCreated);
//Adding listener method to event
this.eventManager.AddListener("on_start_game", this.OnStartGame);
}

private OnStartGame(command: string, data: SFSObject): void {
console.log("Received start game from server!");
}

public OnLocalPlayerCreated(player: NetworkPlayer): void {
console.log("Local player created");
//Triggering an event
this.eventManager.SendServerRequestAsync("start_game", new SFSObject());
}
}