INTEGRATION GUIDE
This guide will walk you through integrating your game with the Genome API using KODE, enabling you to manage matches, players, and tournament information.
Prerequisites
Node.js: Ensure you have Node.js installed on your system.
API secret: You need a Genome personal secret to interact with the API.
Game Server: You should have a server running your game, which can communicate with the Genome API.
Basic knowledge of Node.js: Familiarity with JavaScript, Node.js, and asynchronous programming is recommended.
Setup
Project Setup
Create a new directory for your project and navigate into it.
mkdir game-integration
cd game-integration
npm init -y
Install Dependencies
Install the required dependencies.
npm install --save socket.io-client jsonwebtoken dotenv zod
npm install --save-dev typescript ts-node nodemon
Setup Build and Run Scripts
Create a tsconfig.json
file in root of project.
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"rootDir": "./src",
"outDir": "./dist",
"noEmitOnError": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"strictNullChecks": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
Replace default scripts
and main
definition inside package.json
file with two commands:
"main": "dist/app.js",
"scripts": {
"build": "tsc",
"start": "node ./dist/app.js",
"dev": "nodemon ./src/app.ts"
}
Environment Variables
Create a .env
file to store your environment variables securely.
# .env
GAME_API_URL=ws://localhost:2593
PLATFORM_URL=http://localhost:2594
GAME_ID=game_id_2
GAME_SECRET=game-1-secret
Load and Validate Environments
Using zod we can validate the evironment. Create a src/environment.ts
file and copy next content to it.
import { config } from 'dotenv';
import { z } from 'zod';
config();
export const Env = z
.object({
GAME_API_URL: z.string().url(),
PLATFORM_URL: z.string().url(),
GAME_ID: z.string(),
GAME_SECRET: z.string(),
}
.parse(process.env);
Load Models and Validators
To simplify interaction and integration we provide ready to use zod
validators and type-guards for all message. Create a src/models.ts
file to store the next code.
Establishing a WebSocket Connection
This chapter focuses on establishing a WebSocket connection with the Genome API, which is crucial for real-time communication and receiving updates.
Prepare Authentication Helper
In order to pass handshake authentication, we need to sign authentication message with our GAME_SECRET
. Create a src/auth.ts
file and copy the next snippet.
import jwt from 'jsonwebtoken';
import { Env } from './environment';
export const signPayload = <T extends {}>(payload: T) => {
return jwt.sign(payload, Env.GAME_SECRET, { algorithm: 'HS256' });
};
Establish WebSocket Connection
Create the main file at src/app.ts
and copy next code there.
import { io } from 'socket.io-client';
import { signPayload } from './auth';
import { Env } from './environment';
import { AuthTokenPayload } from './models';
async function main() {
const client = io(Env.GAME_API_URL, {
auth: {
token: signPayload(AuthTokenPayload.parse({ gameId: Env.GAME_ID })),
},
});
client.on('connect', () => {
console.log(`Connected to Game API`);
});
client.on('startGame', (_payload) => {
throw new Error("not implemented yet")
});
client.on('disconnect', (reason) => {
console.log(`Disconnected with reason: ${reason}`);
});
}
main();
Explanation
signPayload()
function generates a JWT signature for arbitrary payload using the game secret configured in.env
file and loaded byconfig()
.io()
creates SocketIO connection with server usingGAME_API_URL
environment variable and signed auth payload uniquegameId
Handle API Events
In this part we explain how to handle the game start and game end events.
Replace content in main.ts
with handler of game start and commitment of result logic.
For demonstration purposes, in the example code, we’re using a dummy implementation based on artificial delays, but you need to create your own game client to create matches and wait for results.
Start Game
Wait for a
startGame
event.parsedPayload.games.map(async (game) => {
Loop though allgames
and proceed with a match for eachgame
:Create a match in the game (we’re just waiting 1 second:
await sleep(1000)
)Emit
gameStarted
event to our api
await client.emit(
'gameStarted',
GameStartedEvent.parse({
matchId: game.matchId,
tournamentId: game.tournamentId,
timestamp: toUnix(Date.now()),
} satisfies GameStartedEvent),
);
End Game
Wait for results (we’re just waiting 1 second and create random scores and winners)
Emit
gameEnded
event to our api
await client.emit(
'gameEnded',
GameEndedEvent.parse({
winners,
matchId: game.matchId,
} satisfies GameEndedEvent),
);
Linking Players
Game events operate with player IDs linked with the platform by your game server. Follow the steps below to link a user with the platform.
Last updated