ColyseusJS Lightweight Multiplayer Game Server Development Framework-Chinese Manual (System Guarantee)

ColyseusJS Lightweight Multiplayer Game Server Development Framework-Chinese Manual (System Guarantee)

Get started quickly with multiplayer game server development. Follow-up will be based on

Google Agones
, Update related
K8S
Operation and maintenance, large-scale and rapid expansion of dedicated game server articles. Embrace Native Cloud-Native!

series

Monitoring panel (
@colyseus/monitor
)

@colyseus/monitor
It is a convenient tool that allows you to view and check the current room list generated by the server.

characteristic

  • List all activity rooms
    • Mandatory arrangement of a specific room
  • Check a specific room
    • Check the status of the room
    • Send/broadcast messages for clients
    • Forcibly disconnect the client

installation

Install the module:

npm install --save @ colyseus/monitor copy the code

Include it in your project:

//... import {monitor} from "@colyseus/monitor" ; ...// app.use ( "/colyseus" , Monitor ()); Copy the code

Use a password to restrict access to the panel

you can use it

express
Middleware in
monitor
Enable authentication on the route, for example
express-basic-middleware
:

npm install --save express-basic-auth duplicated code

use

express-basic-auth
Create users and passwords.

import basicAuth from "express-basic-auth" ; const basicAuthMiddleware = basicAuth({ //list of users and passwords users : { "admin" : "admin" , }, //sends WWW-Authenticate header, which will prompt the user to fill //credentials in challenge : true }); app.use( "/colyseus" , basicAuthMiddleware, monitor()); Copy code

Set custom room list column

app.use( "/colyseus" , basicAuthMiddleware, monitor({ columns : [ 'roomId' , 'name' , 'clients' , { metadata : "spectators" }, // display'spectators' from metadata'locked ' , 'elapsedTime' ] })); Copy code

If not specified, the default room list is listed as:

['roomId','name','clients','maxClients','locked','elapsedTime']
.

Load test/stress test (
@colyseus/loadtest
)

When you want to conduct actual combat tests on the server and understand its performance in a real-time environment,

@colyseus/loadtest
The tool is very useful.

installation

installation

@colyseus/loadtest
Module:

npm install --save-dev @ colyseus/ loadtest duplicated code

usage

colyseus-loadtest
The command requires some parameters to work:

  • script
    : The custom script that the tool will use
  • --endpoint
    : Your server endpoint (use by default
    ws://localhost:2567
    )
  • --room
    : The name of the room you want to connect to
  • --numClients
    : You want to connect to
    room
    The number of clients.

Example

This is an example of a script file. Based on the room life cycle events of each connected client, you can implement a

"bot"
Come with
room
Interactive.

//script.ts import {Room, Client} from "colyseus.js" ; export function requestJoinOptions ( this : Client, i: number ) { return { requestNumber : i }; } export function onJoin ( this : Room ) { console .log( this .sessionId, "joined." ); this .onMessage( "*" , ( type , message ) => { console .log( "onMessage:" , type , message); }); } export function onLeave ( this : Room ) { console .log( this .sessionId, "left." ); } export function onError ( this : Room, err ) { console .error( this .sessionId, "!! ERROR !!" , err.message); } export function onStateChange ( this : Room, state ) { } Copy code

Connect 50 clients to one
"battle"
room

npx colyseus-loadtest script.ts --room battle --numClients 50 --endpoint ws://localhost: 2567 copy the code

Certification + Social (
@colyseus/social
)

In this section

Configuration and usage.

@colyseus/social
It is an experimental module that provides general back-end services to speed up your multiplayer game development experience. The
API
Openly solicit suggestions and improvements.

If you want to implement your own authentication method, see Room onAuth()

installation

  1. Download and install MongoDB

  2. installation

    @colyseus/social
    Module.

npm install @colyseus/social npm install express-jwt Copy code
  1. Import
    and
    expose
    by
    @colyseus/social
    which provided
    Express
    routing.
import express from "express" ; import socialRoutes from "@colyseus/social/express" const app = express(); app.use( "/" , socialRoutes); app.listen( 8080 ); copy the code
const express = require ( "express" ); const socialRoutes = require ( "@colyseus/social/express" ).default; const app = express(); app.use( "/" , socialRoutes); app.listen( 8080 ); copy the code

Server-side configuration

Environment variable

  • MONGO_URI
    : MongoDB connection URI
  • JWT_SECRET
    : The security secret string used for authentication.
  • FACEBOOK_APP_TOKEN
    : Facebook App Token (
    "appid|appsecret"
    )

Server-side API

@colyseus/social
The module provides
MongoDB
models and
token
The verification function is for you to use.

import {User, FriendRequest, verifyToken} from "@colyseus/social" ; Copy code

achieve
onAuth
To retrieve the current user

import {User, verifyToken} from "@colyseus/social" ; class MyRoom extends Room { async onAuth ( client, options ) { //verify token authenticity const token = verifyToken(options.token); //query the user by its id return await User.findById(token._id); } onJoin ( client, options, user ) { console .log(user.username, "has joined the room!" ); } } Copy code

Hooks

hooks.beforeAuthenticate

beforeAuthenticate
The hook is triggered before the user logs in or registers.

import {hooks} from "@colyseus/social" ; hooks.beforeAuthenticate( ( provider, $setOnInsert, $set ) => { //assign default metadata upon registration $setOnInsert.metadata = { coins : 100 , trophies : 0 }; }); Copy code

hooks.beforeUserUpdate

beforeUserUpdate
The hook is triggered before the user updates his own information through the save() method .

import Filter from "bad-words" ; const filter = new Filter(); hooks.beforeUserUpdate( ( _id, fields ) => { if (fields[ 'username' ] && filter.isProfane(fields[ 'username' ])) { throw new Error ( "no_swearing_allowed" ); } }) Copy code

Client API

log in

anonymous

await client.auth.login(); Copy code

Email + password

await client.auth.login({ email : "user@example.com" , password : "12345" }); Copy code

Facebook

// //the Make the Sure you have have Facebook SDK Installed at The First and the Configured //- https://developers.facebook.com/docs/javascript/quickstart //- https://developers.facebook.com/docs/facebook- login/web // FB.login( function ( response ) { if (response.authResponse) { client.auth.login({ accessToken : response.authResponse.accessToken }); } }, { scope : 'public_profile,email,user_friends' }); Copy code

Update user data

You can modify from the client

username
,
displayName
,
avatarUrl
,
lang
,
location
with
timezone
And then call
save()
method.

client.auth.username = "Hello world!" await client.auth.save(); Copy code

Logout

client.auth.logout(); Copy code

Get friends list

const friends = await client.auth.getFriends(); friends.forEach( friend => { console .log(friend.username); }); Copy code

Get a list of online friends

const friends = await client.auth.getOnlineFriends(); friends.forEach( friend => { console .log(friend.username); }); Copy code

Get the list of friend requests

const friends = await client.auth.getFriendRequests(); friends.forEach( friend => { console .log(friend.username); }); Copy code

Accept friend's request

await client.auth.acceptFriendRequest(friendId); Copy code

Reject friend request

await client.auth.declineFriendRequest(friendId); Copy code

Send friend request

await client.auth.sendFriendRequest(friendId); Copy code

Block users

await client.auth.blockUser(friendId); Copy code

Unblock user

await client.auth.unblockUser(friendId); Copy code

debugging

Inspector

can use

Node.js
Built-in
inspector
To debug the application.

Read more about debugging Node.js applications .

Use the inspector in a production environment

Be careful when using the inspector in production. Using memory snapshots and breakpoints will directly affect the user experience.

1. Connect to the remote server:

ssh root@remote.example.comCopy code

2. Check the PID of the Node process

ps aux | grep node copy the code

3. Attach the inspector to the process

kill -usr1 PID copy the code

4. Create an SSH tunnel from the local machine to the remote inspector

ssh -L 9229: localhost: 9229 root@remote.example.com copy the code

Your production server should now appear in

on.

Debug message

The server provides some debugging messages, you can set

DEBUG
Environment variables to enable these messages one by one.

To enable all logs, you can run the server with the following command:

DEBUG = colyseus: * node server.js copy the code

See all available debug categories and sample output below.

colyseus:patch

Record the number of bytes and time interval for broadcasting patches to all clients.

colyseus: patch "chat" (roomId : "ryWiL5rLTZ") is sending 28 bytes: + 57ms copy the code

colyseus:errors

Log when unexpected (or internally expected) errors occur on the server side.

colyseus:matchmaking

Whenever the room

spanwed
or
disposed
Record every time.

colyseus:matchmaking spawning'chat' on worker 77218 +52s colyseus:matchmaking disposing'chat' on worker 77218 +2s Copy code

deploy

Heroku

Heroku
Only for prototyping. You can deploy the colyseus-examples project by clicking this button :

Nginx (recommended)

Recommended for use in a production environment

pm2
with
nginx
.

PM2

Install in your environment

pm2
.

npm install -g pm2 copy the code

Then use it to start your server:

pm2 start your-server.js duplicated code

Nginx configuration

server { listen 80; server_name yourdomain.com; location/{ proxy_pass http://localhost:2567; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } } Copy code

Configure Nginx with SSL

It is recommended to obtain the certificate from LetsEncrypt .

server { listen 80; listen 443 ssl; server_name yourdomain.com; ssl_certificate/path/to/your/cert.crt; ssl_certificate_key/path/to/your/cert.key; location/{ proxy_pass http://localhost:2567; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } } Copy code

Apache

Here is how to use

Apache
As
Node.js Colyseus
Application proxy (Thanks tomkleine !)

Required for installation

Apache
Module:

sudo a2enmod ssl sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_html sudo a2enmod proxy_wstunnel Copy code

Virtual host configuration:

<VirtualHost *:80> ServerName servername.xyz # Redirect all requests received from port 80 to the HTTPS variant (force ssl) RewriteEngine On RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L] </VirtualHost> <VirtualHost *:443> ServerName servername.xyz # enable SSL SSLEngine On SSLCertificateFile/PATH/TO/CERT/FILE SSLCertificateKeyFile/PATH/TO/PRIVATE/KEY/FILE # # setup the proxy to forward websocket requests properly to a normal websocket # and vice versa, so there's no need to change the colyseus library or the # server for that matter) # # (note: this proxy automatically converts the secure websocket (wss) RewriteEngine On RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR] RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC] RewriteRule .* ws://127.0.0.1:APP-PORT-HERE%{REQUEST_URI} [P,QSA,L] # setup the proxy to forward all https requests to http backend # (also automatic conversion from https to http and vice versa) ProxyPass "/" "http://localhost:APP-PORT-HERE/" ProxyPassReverse "/" "http://localhost:APP-PORT-HERE/" </VirtualHost> Copy code

greenlock-express

If you want to quickly configure on the server

SSL
, Without the need to configure a reverse proxy (
reverse-proxy
),
Greenlock
It is a very good tool.

When using

At this time, you should not configure any reverse proxy behind it, such as Nginx or Apache .

npm install --save greenlock-express duplicated code

Please follow the README section of greenlock-express first .

The following is to deal with the development environment (

development
) And the production environment (
production
) Recommended method:

import http from "http" ; import express from "express" ; import {Server} from "colyseus" ; function setup ( app: express.Application, server: http.Server ) { const gameServer = new Server({ server }); //TODO: configure `app` and `gameServer` accourding to your needs. //gameServer.define("room", YourRoom); return app; } if (process.env.NODE_ENV === "production" ) { require ( 'greenlock-express' ) .init( function () { return { greenlock : require ( './greenlock' ), cluster : false }; }) .ready( function ( glx ) { const app = express(); //Serves on 80 and 443 //Get's SSL certificates magically! glx.serveApp(setup(app, glx.httpsServer( undefined , app))); }); } else { //development port const PORT = process.env.PORT || 2567 ; const app = express(); const server = http.createServer(app); setup(app, server); server.listen(PORT, () => console .log( `Listening on http://localhost: ${PORT} ` )); } Copy code

Docker

prerequisites:

  • package.json
    with
    package-lock.json
    In the project.

  • Set up

    npm start
    Command to start the server.

step:

Step 1 install Docker

Step 2 Create in the root directory of the colyseus project

Dockerfile

FROM node: 12 ENV PORT 8080 WORKDIR /usr/src/app # A wildcard is used to ensure both package.json AND package-lock.json are copied COPY package*.json ./ RUN npm ci # run this for production # npm ci --only=production COPY .. EXPOSE 8080 The CMD [ "NPM" , "Start" ] Copy Code

Step 3 Create in the same directory

.dockerginore
file

node_modules npm-debug.log Copy code

This will prevent your local modules and debug logs from being copied to your Docker image and may overwrite the modules installed in the image.

Step 4 enter

Dockerfile
In the directory, run the following command to build
Docker
Mirror.
-t
flag allows you to mark your
image
, So use later
docker images
The command is easier to find:

docker build -t <your username>/ colyseus-server. duplicated code

Step 5 your

image
Will now be
Docker
Use the following command to list:

docker images Copy code

Output:

# Example REPOSITORY TAG ID CREATED node 12 1934b0b038d1 About a minute ago <your username>/colseus-server latest d64d3505b0d2 About a minute ago Copy code

Step 6 Use the following command to run the Docker image:

docker run -p 8080: 8080 -d < your username>/colyseus-server copy the code

use

-d
Running the image will start with
detached
Run the container in mode, making the container run in the background.
-p flag
Redirect the public port to the private port in the container.

Step 7 completed, you can now

localhost:8080
Connect to server

More information:

Highly available and scalable

This document is a work in progress.

To

Colyseus
To scale to multiple processes or servers, you need to have
Redis
,
MongoDB
And a dynamic proxy (
dynamic proxy
).

Redis

Download and install Redis . use

RedisPresence
:

import {Server, RedisPresence} from "colyseus" ; const gameServer = new Server({ //... presence : new RedisPresence(), }); Copy code
const colyseus = require ( "colyseus" ); const gameServer = new colyseus.Server({ //... presence : new colyseus.RedisPresence(), }); Copy code

presence
Used to call the room from one process to another
"seat reservation"
Functionality and allow developers to cross
rooms
Take advantage of some data sharing features. See Presence API .

Each

Colyseus
Process will also own
processId
And the network location is registered to
presence
API, dynamic proxy later be used by services
API
. in
graceful shutdown
In the meantime, the process logs itself off.

MongoDB

Download and install MongoDB . installation

mongoose
Package:

npm install --save mongoose copy the code

use

MongooseDriver
:

import {Server, RedisPresence} from "colyseus" ; import {MongooseDriver} from "colyseus/lib/matchmaker/drivers/MongooseDriver" const gameServer = new Server({ //... driver : new MongooseDriver(), }); Copy code
const colyseus = require ( "colyseus" ); const MongooseDriver = require ( "colyseus/lib/matchmaker/drivers/MongooseDriver" ).MongooseDriver; const gameServer = new colyseus.Server({ //... driver : new MongooseDriver(), }); Copy code

You can add

MongoDB
connection
URI
Pass to
new MongooseDriver(uri)
Constructor, or set
MONGO_URI
Environment variables.

driver
Can be used for storage and query
matchmaking
of
rooms
.

Run multiple Colyseus processes

To run multiple on the same server

Colyseus
Instances, each instance needs to monitor a different port number. Recommended to use
3001
,
3002
,
3003
Wait for the port. The Colyseus process should not be made public. only
dynamic proxy
Yes.

It is strongly recommended to use PM2 Process Manager to manage multiple

Node.js
Application example.

PM2 provides a

NODE_APP_INSTANCE
Environment variables, which contain different numbers for each process. Use it to define the port number.

import {Server} from "colyseus" ; //binds each instance of the server on a different port. const PORT = Number (process.env.PORT) + Number (process.env.NODE_APP_INSTANCE); const gameServer = new Server({ /* ... */ }) gameServer.listen(PORT); console .log( "Listening on" , PORT); Copy code
npm install -g pm2 copy the code

Use the following

ecosystem.config.js
Configuration:

//ecosystem.config.js const os = require ( 'os' ); module .exports = { apps : [{ port : 3000 , name : "colyseus" , script : "lib/index.js" , //your entrypoint file watch : true , //optional instances : os.cpus().length, exec_mode : 'fork' , //IMPORTANT: do not use cluster mode. env: { DEBUG : "colyseus:errors" , NODE_ENV : "production" , } }] } Copy code

Now you are ready to start multiple

Colyseus
Progress.

pm2 startCopy code

"PM2 and TypeScript": It is recommended to run

pm2 start
Passed before
npx tsc
Compile
.ts
file. Or you can
PM2
installation
TypeScript
Interpreter (
pm2 install typescript
) And set
exec_interpreter: "ts-node"
( read more ).

Dynamic proxy

@colyseus/proxy is a dynamic proxy, it will automatically monitor

Colyseus
Up and down changes in the process, allowing
WebSocket
Connect to the correct process and server that created the room.

The proxy should be bound to the port

80
/
443
, Because it is the only public endpoint of the application. All requests must go through a proxy.

npm install -g @ colyseus/proxy copy the code

Environment variable

Configure the following environment variables to meet your needs:

  • PORT
    Is the port on which the agent will run.
  • REDIS_URL
    It's you
    Colyseus
    The same one used in the process
    Redis
    The path of the instance.

Run the agent

colyseus-proxy > {"name":"redbird","hostname":"Endels-MacBook-Air.local","pid":33390,"level":30,"msg":"Started a Redbird reverse proxy server on port 80 ","time":"2019-08-20T15:26:19.605Z","v":0} Copy code

Refs

The Chinese manual is updated synchronously at:

  • https:/colyseus.hacker-linner.com
I am for less WeChat: uuhells123 Public Account: Afternoon Tea for Hackers Add me on WeChat (learn from each other), follow the official account (get more learning materials~) Copy code