Skip to main content

Creating and Hosting the Game Backend using Node.js in Render

This is the first development blog post in a series for "Masters of Mischief". This post specifically is about the development of a backend for our 3D multiplayer game.

Let's move the card in our Trello board and start on the journey.

Trello Board

The selected technologies are:

➣ Database Development: MySQL, hosted on freesqldatabase.com.
Web Server Environment: Node.js powered by Express.js framework, hosted on Render.com.

Setting up the Database:

First things first, we're getting our database set up on freesqldatabase.com. It's pretty straightforward - just sign in, create a database, and you're ready to roll. They'll shoot you an email with all the credentials you need to access your new database.

Fig 1. Database setup in freesqldatabase.com

Fig 2. Database credentials

You can get into the database using the phpMyAdmin portal by clicking the link `▶ Follow this link for phpMyAdmin` as shown in the above snapshot.

Creating a Table:

In the database, create a table named `players` with the following structure to store user information.

Fig 3. Structure of the `players` table

We added records of 2 players in the table manually from phpMyAdmin itself, for testing purpose while we initially start web service development and database integration.

Fig 4. Records of players in the table

We'll add more fields into this table and the database as per the need in the future. For now, this will suffice in the creation of a simple player login/registration system.

Setting up the Render deployment environment:

Following steps were taken to setup a basic architecture to roll out a live web server for the game.

➣ Create a Github account.
➣ Create a repository in github for pushing out the server code.

Fig 5. Server Repository in Github

➣ Register an account on Render using Github.

Fig 6. Snap of registration screen on Render

Select Web Services and connect to your server's github repository.
➣ You will then be able to create a deploy profile on Render and after a few minutes, your server will be up and running.
➣ You will also be able to add environment variables in Render. Follow the snap below.

Fig 7. Adding Env variables in Render

Render automatically employs CI/CD into your service, so every push to the registered git branch will trigger re-deployment of the server.

For a detailed tutorial on how to host backend server using Github repository on Render, here is a youtube tutorial you can follow. We've rolled up our service for this game here.

Setting up the development environment:

The first step is to clone the blank github repository (The same one used in the Render deployment profile) locally. Then open the root directory in vscode or the editor of your choice.

In the terminal at the root directory, enter the following command to initialise the project as a Node.js project.

🟒 Init. npm project 🟫 Terminal
mandeep@Masters-Of-Mischief /server_root %:
npm init -y

We will be using `express` framework to create server and routes, and `mysql2` library for database integration.

The database credentials from before should not be exposed in code. For that we use environment variables to store credentials and fetch that in code. For simulating that in our local, we create a .env file and store our variables there. To work with .env locally, we need yet another dependency `dotnev`. We don't need it in a production build.

We will also create a full-fledge registration and login system in the next blog post. A good authentication system makes use of password hashing instead of regular plain password. We will be using `bcrypt` library for the purpose.

Enter the following command to install dependencies.

🟒 Install dependencies 🟫 Terminal
mandeep@Masters-Of-Mischief /server_root %:
npm install express, mysql2, bcrypt
mandeep@Masters-Of-Mischief /server_root %:
npm install dotenv --save-dev

Create a `app.js` file in the root directory and write the following script.

🟒 app.js 🟨 Javascript 🟦 Express
import express from 'express';
import pool from './database.js';

const app = express();
const port = process.env.PORT || 8080;

app.get('/', (req, res) = >{
  res.send('Welcome to the game backend')
})

app.get('/players', async(req, res) = >{
  try {
    const connection = await pool.getConnection();
    const[rows] = await connection.query('SELECT * FROM players');
    connection.release();
    res.json(rows);
  } catch(error) {
    console.error('Error executing query:', error);
    res.status(500).json({
      error: 'Database error'
    });
  }
});

app.listen(port, () = >{
  console.log(`Server running at http: //localhost:${port}`);
});

This script basically spins a web server at a port defined in the process environment (which is dynamically set on Render and we need to use it) or fallback to use port 8080 if the port is not defined in the environment.

We also created a default index route which just responds with a welcome text.

The other route (temporary, we'll change this once we implement authentication) will connect to the database and responds with a list of players registered in the database.

As we can see, we have an import of `database.js` file that is used to perform db operations. Let's see the content of the file.

🟒 database.js 🟨 Javascript 🟦 Express
import mysql from 'mysql2';
import dotenv from 'dotenv';
dotenv.config();

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
}).promise();

export default pool;

We import dotenv and configure it, again, this is for local use.

We create a pool of mysql connections. The .promise() will allow us to use Javascript promise syntax and async/await instead of callbacks while performing database operations.

As you can see, we have fetched the credentials from the environment file by using process.env.VAR_NAME. Let's see how we define the environment variables in a `.env` file.

Fig 10. Environment file .env

Our database credentials are all string. Do note we can create numeric environment variables as well.

We can upload this file content directly in Add from .env file in Render, as shown in Fig 7.

Finally we push this updated codebase into the remote github branch to trigger re-deployment in Render. But before that, we need to create a `.gitignore` file in the root directory to block pushing our `.env` and unwanted files/directories in the remote public repository.

Fig 11. .gitignore file 

Now, push the codebase into the remote using the following commands and wait until the update is deployed.

🟒 Push update to remote 🟫 Terminal
mandeep@Masters-Of-Mischief /server_root %:
git add .
mandeep@Masters-Of-Mischief /server_root %:
git commit -m "Added basic server function"
mandeep@Masters-Of-Mischief /server_root %:
git push --set-upstream origin main

After the server is live, we see the list of players successfully retrieved.

Fig 12. Live server

In the next blog post, we'll update the codebase to create a full-fledge authentication system for players.

Comments

Popular posts from this blog

Implement Authentication (in Unity) | Link and Unlink account using PlayerPrefs

In this blog post, we'll delve into the process of implementing authentication in Unity, along with user account linking and unlinking using PlayerPrefs. Let's break down each step, from setting up the UI canvas to managing player data effectively.

How I Set Up GitHub Collaboration and CI/CD with GitHub Actions for our Unity Game Project

Transitioning to GitHub collaboration and CI/CD for "Masters of Mischief" was a game-changer. It all started with the frustration of the old-school ZIP file transfers among developers, waiting for one another to finish their tasks before diving in. That approach was inefficient, to say the least. So, we decided to bid farewell to that headache and revamp our workflow.