socket.io-games

1.0.109 • Public • Published

Game Package

A package you can use to create your own game platform with an implemented match- and user-system with default games like TicTacToe using socket.io

Documentation

Typical Configuration

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const socketGames = require('socket.io-games');

socketGames.config.config(app, {
  file: "./db.json",
  usernameCharacterLength: {
    minimum: 2, // default => 0 (no minimum)
    maximum: 15 // default => 0 (no maximum)
  }, // optional
  pluginURL: "https://myPluginURL.com" // default => official plugin site
}).then(() => {
  socketGames.config.clearDatabaseSync();
});
app.use(express.static("pages"));
app.use(express.static("public"));

io.on('connection', (socket, name) => {});

app.all('/', (req, res) => {
  res.sendFile("pages/home/index.html");
});

http.listen(3000, () => {
  console.log("Server is ready");
});

Configuration

Setup

socketGames.config.config(app, {
  file: "./db.json" // database
});

Read Database

socketGames.config.readDatabase().then((result) => {
  console.log(result.data);
});

Clear Database

socketGames.config.clearDatabase().then((result) => {
  console.log("Cleared the database");
});

Matches

Create Match

socket.on("createMatch", (options) => {
  socketGames.matches.createMatch(socket.id, options).then((result) => {
    if (!result.err) {
      io.of("/").sockets.get(result.playerId).emit("newMatch", result);
    }
  });
});

Accept Match

socket.on("acceptMatch", (options) => {
  socketGames.matches.acceptMatch(socket.id, options).then((result) => {
    if (!result.err) {
      socket.emit("acceptMatch", result);
    }
  });
});

Reject Match

socket.on("rejectMatch", (options) => {
  if (socketGames.config.readDatabaseSync().data.matches[options.matchId]?.status === "pending") {
    socketGames.matches.rejectMatch(socket.id, options).then((result) => {
      if (!result.err) {
        socket.emit("rejectMatch", result);
      }
    });
  }
});

Open Match

socket.on("openMatch", (options) => {
  try {
    socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.players.forEach((player) => {
      io.of("/").sockets.get(player).emit("openMatch", {
        matchId: options.matchId,
        turn: socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.data.turn,
        players: socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.data?.players,
        users: socketGames.users.allUsersSync().users
      });
    });
  } catch (err) {}
});

Users

Create User

socket.on("createUser", (options) => {
  socketGames.users.createUser(socket.id, options).then(() => {
    socketGames.users.allUsers().then(({ users }) => {
      io.emit("userUpdate", { users });
    });
  });
});

Edit User

socket.on("editUser", (options) => {
  socketGames.users.editUser(socket.id, options).then(() => {
    socketGames.users.allUsers().then(({ users }) => {
      io.emit("userUpdate", { users });
    })
  });
})

Delete User

socket.on("disconnect", () => {
  socketGames.users.deleteUser(socket.id, io).then((deletedUser) => {
    if (!deletedUser.err) {
      socketGames.users.allUsers().then(({ users }) => {
        io.emit("userUpdate", { users });
        deletedUser.matches.forEach((match) => {
          match[1].players.filter((player) => player !== socket.id).forEach((player) => {
            io.of("/").sockets.get(player).emit("roomLeave", {
              username: result.users[player].username
            });
          });
        });
      });
    }
  });
});

Games

Create Match of TicTacToe

socket.on("createMatch", (options) => {
  socketGames.games.tictactoe.createMatch(socket.id, options).then((result) => {
    if (!result.err) {
      io.of("/").sockets.get(result.playerId).emit("newMatch", result);
    }
  });
});

Create Match of Connect Four

socket.on("createMatch", (options) => {
  socketGames.games.connectfour.createMatch(socket.id, options).then((result) => {
    if (!result.err) {
      io.of("/").sockets.get(result.playerId).emit("newMatch", result);
    }
  });
});

Place Field of TicTacToe

socket.on("placeField", (options) => {
  try {
    socketGames.games.tictactoe.placeField(socket.id, options).then((result) => {
      if (!result.err) {
        Object.keys(result.players).forEach((player) => {
          io.of("/").sockets.get(player).emit("placeField", {
            ...result,
            ...{
              users: socketGames.users.allUsersSync().users
            }
          });
        });
      }
    });
  } catch (err) {}
});

Place Field of Connect Four

socket.on("placeField", (options) => {
  try {
    socketGames.games.connectfour.placeField(socket.id, options).then((result) => {
      if (!result.err) {
        Object.keys(result.players).forEach((player) => {
          io.of("/").sockets.get(player).emit("placeField", {
            ...result,
            ...{
              users: socketGames.users.allUsersSync().users
            }
          });
        });
      }
    });
  } catch (err) {}
});

Game Registry

Register File

socketGames.gameRegistry.registerGames({
  games: [
    {
      type: "file", // set type to file
      game: "./game.js" // path to your game
    }
  ]
});

Register URL

socketGames.gameRegistry.registerGames({
  games: [
    {
      type: "url", // set type to url
      game: "https://raw.githubusercontent.com/username/repository/root/file" // url to your game
    }
  ]
});

Register Plugin

socketGames.gameRegistry.registerGames({
  games: [
    {
      type: "plugin", // set type to plugin
      game: "My Plugin Id" // plugin id
    }
  ]
});

Unregister File

socketGames.gameRegistry.unregisterGames({
  games: [
    {
      type: "file", // set type to file
      game: "./game.js" // path to your game
    }
  ]
});

Unregister URL

socketGames.gameRegistry.unregisterGames({
  games: [
    {
      type: "url", // set type to url
      game: "https://raw.githubusercontent.com/username/repository/root/file" // url to your game
    }
  ]
});

Unregister Plugin

socketGames.gameRegistry.unregisterGames({
  games: [
    {
      type: "plugin", // set type to plugin
      game: "My Plugin Id" // plugin id
    }
  ]
});

Example

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const socketGames = require('socket.io-games');

socketGames.config.config(app, {
  file: "./db.json"
}).then(() => {
  socketGames.config.clearDatabaseSync();
});
app.use(express.static("pages"));
app.use(express.static("public"));

io.on('connection', (socket, name) => {
  socket.on("createUser", (options) => {
    socketGames.users.createUser(socket.id, options).then(() => {
      socketGames.users.allUsers().then((result) => {
        io.emit("userUpdate", result.users);
      });
    });
  });
  socket.on("createMatch", (options) => {
    socketGames.games.tictactoe.createMatch(socket.id, options).then((result) => {
      if (!result.err) {
        io.of("/").sockets.get(result.playerId).emit("newMatch", result);
      }
    });
  });
  socket.on("acceptMatch", (options) => {
    socketGames.matches.acceptMatch(socket.id, options).then((result) => {
      if (!result.err) {
        socket.emit("acceptMatch", result);
      }
    });
  });
  socket.on("rejectMatch", (options) => {
    if (socketGames.config.readDatabaseSync().data.matches[options.matchId]?.status === "pending") {
      socketGames.matches.rejectMatch(socket.id, options).then((result) => {
        if (!result.err) {
          socket.emit("rejectMatch", result);
        }
      });
    }
  });
  socket.on("openMatch", (options) => {
    try {
      socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.players.forEach((player) => {
        io.of("/").sockets.get(player).emit("openMatch", {
          matchId: options.matchId,
          turn: socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.data.turn,
          players: socketGames.config.readDatabaseSync().data?.matches?.[options.matchId]?.data?.players,
          users: socketGames.users.allUsersSync().users
        });
      });
    } catch (err) {}
  });
  socket.on("placeField", (options) => {
    try {
      socketGames.games.tictactoe.placeField(socket.id, options).then((result) => {
        if (!result.err) {
          Object.keys(result.players).forEach((player) => {
            io.of("/").sockets.get(player).emit("placeField", {
              ...result,
              ...{
                users: socketGames.users.allUsersSync().users
              }
            });
          });
        }
      });
    } catch (err) {}
  });
  socket.on("disconnect", () => {
    socketGames.users.deleteUser(socket.id, io).then((deletedUser) => {
      if (!deletedUser.err) {
        socketGames.users.allUsers().then((result) => {
          io.emit("userUpdate", result.users);
          deletedUser.matches.forEach((match) => {
            match[1].players.filter((player) => player !== socket.id).forEach((player) => {
              io.of("/").sockets.get(player).emit("roomLeave", {
                username: result.users[player].username
              });
            });
          });
        });
      }
    });
  });
});

app.all('/', (req, res) => {
  res.sendFile("pages/home/index.html");
});

http.listen(3000, () => {
  console.log("Server is ready");
});

Client Side Documentation

Configuration

Setup

<script src="/socket.io/socket.io.js">
const socket = io();

Actions

Users

Create User
socket.emit("createUser", {
  username: "My Username"
});

Matches

Create Match
socket.emit("createMatch", {
  playerId: "player id"
});
Accept Match
socket.emit("acceptMatch", {
  matchId: "match id"
});
Reject Match
socket.emit("rejectMatch", {
  matchId: "match id"
});
Open Match
socket.emit("openMatch", {
  matchId: "match id"
});

Games

Place Field
socket.emit("placeField", {
  matchId: "match id",
  field: "1" // number from 1 to 9
})

Events

Users

User Update
socket.on("userUpdate", (options) => {
  console.log(options.users); // do some stuff with the users
});

Matches

New Match
socket.on("newMatch", (options) => {
  console.log(options.username, options.matchId); // do some stuff with the match request
});
Accept Match
socket.on("acceptMatch", (options) => {
  console.log(options.matchId); // do some stuff with the accepted match
  socket.emit("openMatch", { matchId: options.matchId }); // open the accepted match
});
Reject Match
socket.on("rejectMatch", (options) => {
  console.log(options.matchId); // do some stuff with the rejected match
});
Open Match
socket.on("openMatch", (options) => {
  console.log(options.users[socket.id], options.users[Object.entries(options.players).filter((item) => item[0] !== socket.id)[0][0]].username, options.turn); // do some stuff with the opened match
});

Games

Place Field
socket.on("placeField", (options) => {
  console.log(options.field); // do some stuff with the placed field
});

Rooms

Room Leave
socket.on("roomLeave", (options) => {
  console.log(options.username); // do some stuff with the user who left
});

Changelog

1.0.0 - Basic Version

Basic version of configuration, matches and users with TicTacToe and Connect Four as games

1.0.1 to 1.10 - Bug Fixes

Some bug fixes and updates for a better interface

1.11 to 1.20 - Game Updates

Updated games and security updates

1.21 - Templates (Client)

Templates (also called Client) added. Requires a http server or express app in config function

1.22 to 1.30 - Basic Updates

Some basic updates

1.31 - Leaderboard

Automatic leaderboard sorting for wins in all or specific games

1.32 - Game Engine (renamed to Game Registry)

Script to make adding custom games easy for beginners with file, urls and plugins (including plugin platform)

1.33 - Added data object to users and matches

Allow storing custom data in users and matches

1.34 to 1.42 - Bug fixes

Including fixing overwriting old fields

1.43 to 1.58 - Rock paper scissors

Added rock paper scissors as default game

1.59 - Added default options

Added default options which constains data about default changeable

1.60 to 1.72 - Bug fixes

Some bug fixes

1.73 to 1.80 - Memory

Added memory as default game

1.81 to 1.84 - Added shortcuts

Added shourtcuts with basically the same function as the game registry

1.85 - Added util functions

Added some util function

1.86 to 1.88 - Bug fixes

Some bug fixes

1.89 - Added random number generator

Added new util function called random number generator

1.90 to 1.94 - Bug fixes

Some bug fixes

1.95 to 1.96 - Added get quantity of each item

Added new util function called get quantity of each item

1.97 - Renamed read file

Renamed the read file function in config to read database

1.98 to 1.101 - Updated documentation

Updated the documentation in the readme file

1.102 to 1.104 - Added rounds

Added rounds to the default games

1.105 - Added changelog

Added changelog to the readme file

1.106 - Note and bugs

Added note and bugs to the readme file

1.107 to 1.109 - Bug fixes

Some bug fixes

Note

This package is based on promises, but every single function also contains a same synchronous function.

Bugs

Please report bugs in the following github repository: https://github.com/DinoscapeProgramming/Game-Package

Known issues

  • Fetch URL sync not working. Getting data from other web servers (also third party services) cannot be done synchronously. Use the asynchronous function instead.

Example Site

https://tictactoe.dinoscape.tk

Readme

Keywords

Package Sidebar

Install

npm i socket.io-games

Weekly Downloads

1

Version

1.0.109

License

ISC

Unpacked Size

144 kB

Total Files

18

Last publish

Collaborators

  • dinoscape