Looking for a rival on socket.io

Currently, I am working on a script utilizing socket.io with express in node.js to find an opponent.

In this setup, only two players are allowed in a room. If no free rooms are available, a new one should be created automatically.

The core logic of the code is as follows:

https://i.sstatic.net/OMHg6.png

I made an attempt like so:

io.on('connection', function (socket) {
    socket.on('search room', function() {
        for (var x in io.sockets.adapter.rooms) {
            if (x !== socket.id) {
                socket.opponent = x;
                socket.join(x);
                break;
            }
        }
    });
});

Queries:

  • The existing code searches for an opponent, but how can it be modified to make a player wait for others if no match is found?
  • What would be the most effective approach to determine whether a player is already engaged in a game?
  • Upon joining a room, how can we ensure that the user's default room remains unaffected?

Answer №1

For more intricate systems, it is common to create a custom client object that maintains a record of all connected users and the rooms they are currently in. This can also serve as a way to represent the current state of users on the server. I recommend using a Map(); for this purpose, where the socket.id is set as the key and the clients object is the value.

A simple approach to building this could be;

Client.js

// JavaScript source code
var client = function client(socket) {
    this.id = socket.id;
    this.state = "newly Connected";
    this.clientSocket = socket;
    this.LobbyArr = [];

    this.changeState = function (newState) {
        this.state = newState;
    }

    this.addLobby = function (lobbyId) {
        this.LobbyArr.push(lobbyId);
    }
}

module.exports = Client;

Server.js

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.use(express.static(__dirname + '/'));

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/public/index.html');
});

//loading server side modules
var Client = require('../Client.js');

//Gets all of the connected clients
var allConnectedClients = new Map();

io.on('connection', function (socket){
  var connectedUser = new Client(socket);
  allConnectedClients.set(socket.id, connectedUser);
});

The code above looks for an opponent, but if none is found, the user should wait for others.

Expanding on the example, by setting states for connected clients, we can loop through the map to identify where the user currently is based on this.state. If no suitable user is found, a new message can be emitted to the client.

What is the best way to check if a player is already playing?

To determine if a player is already playing, you can simply check the user's current state.

When a user joins a room, their default room is not removed.

In socket.io, each user is automatically placed into their own default room upon connecting to the server, so the default room will not be deleted.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What exactly does a module's scope entail in browsers and Node.js environments?

Can someone clarify the scope of a module in different environments like browsers and Node? I'm particularly interested in whether a module-level variable is initialized once for the entire application or multiple times. Is each import creating a new ...

React Star Rating Component: Issue with Image Display

To all who contributed their time and effort in responding to my previous question, I offer my sincerest apologies. Initially, I had assumed that assistance wouldn't be forthcoming, so I started working on the issue myself. As a result, I have made si ...

Connecting event listeners to offspring elements, the main element, and the entire document

My request is as follows: I have multiple boxes displayed on a webpage, each containing clickable divs and text. When a user clicks on a clickable div, an alert should appear confirming the click. Clicking on the text itself should not trigger any action. ...

Experiencing pagination problems with Vue / Laravel framework

Trying to implement pagination for fetched data in a Vue project, but encountering an issue: New Question Error encountered during rendering: "TypeError: this.estates.filter is not a function" Am I overlooking something here? Pagination.vue ...

Implementing automatic redirection upon clicking using React without the need for manual clicking

I'm experiencing an issue where the page seems to automatically navigate to another page without clicking on the div. Can anyone explain why this is happening? Here's the code snippet for reference: import React, { Component } from "react&q ...

Utilize a dynamic URL within the HTML audio element

Currently, I am working with the use of the audio tag in HTML and AngularJS. I need to specify the source of the audio file I want to play, as shown below. <audio src="http://localhost/audio/221122/play/212223.mp3" audio player controls p ...

Manipulating nested JSON objects with AngularJS by adding and pushing the data

I am looking at a JSON object structured like this : { "Name": "Shivansh", "RollNo": "1", "Stream": "CSE", "OverallScore": "76", "Semester": [ { "SemesterName": "FY-2012 - 1", "TotalScore": "78.00", ...

NodeJS: The functionality of my node files relies on the variables defined in another file

For my nodejs app, I have created a script called app.js that serves as the entry point. This script initializes both the expressjs app and the http server. To clarify: The modules mentioned are not npm modules; they are custom files that I have written m ...

Creating dynamic SQL queries for bulk inserting data into Postgres using Vercel

Can anyone help me with creating an SQL bulk insert query using the sql helper from @vercel/postgres? I have a array of objects with different property types (number, string, date) and need to dynamically build the query. Simply creating a string and passi ...

Is there a way for me to retrieve props that have been passed through the Vue router within a Vue component?

I have configured a route as shown below: { path: 'fit-details', name: 'fit-details', component: Fitment, props: true }, I am passing props via the route using data from the state: this.$router.push({ path: 'fit-details&a ...

What is the best way to reference a dynamic ID in JavaScript when clicking for an action on a different

Here is my HTML code snippet: <table> <tr> <td> @Html.DropDownList("Statues", (SelectList)ViewBag.UserType, string.Empty, new { @class = "NewIDCn",@id = "name1" }) </td> <td> ...

Eliminating Non-Breaking Spaces with the Click of a Button

Having some difficulty with the following Javascript code. I'm not very skilled in writing Javascript, so any assistance on adjusting it to replace any &nbsp; with a regular space would be greatly appreciated. Thank you function copyToClipboard( ...

Update the initial line of the GET response within Express

Is it possible to customize the message returned by the server when a client sends a GET request? How can I achieve this? I have searched through Stack Overflow and read the documentation, but I am still not sure how to do it. ...

Can passing parameters between nested map functions cause any issues?

While attempting to navigate to a page in reactjs and pass parameters using the useNavigate hook, I encounter an unexpected token error as soon as I include the navigation within the anchor tag. <a onClick={() ={ ...

The input value fails to update after the method is called

I am working on developing a todo-list application and here is the code I have so far: HTML: <div class="divPadder"> <input ref="makePlaceholderEmpty" class="inputBoxSize" type="text" :placeholder="placeholder"v-model="task"> <ul> ...

What is the best way to write an SQL query to safely insert a record into a table with a dynamic name?

I'm working on a function that can insert a record into a table in PostgreSQL. The catch is that the table name needs to be a parameter for the function, and the column names are determined dynamically. To ensure protection against SQL Injection, I am ...

Tips on sorting a FileList object selected by a directory picker in JavaScript/TypeScript

I need to filter or eliminate certain files from a FileList object that I obtained from a directory chooser. <input type="file" accept="image/*" webkitdirectory directory multiple> Within my .ts file: public fileChangeListener($event: any) { let ...

Enter data into the appropriate columns

Within my Angular 6 application, I am creating a table with the following structure: Html: <table> <thead> <tr> <th> Property Details &nbsp; &nbsp; &nbsp; &nbsp; ...

The HttpParams are reluctant to be established

Working with Angular 8, I am attempting to assign an HttpParam using the provided code snippet and observing the outcome on the final line. let newParams = new HttpParams(); newParams.set('ordering', 'name'); console.log('getting: ...

What is the reason that property spreading is effective within Grid components but not in FormControl components?

Explore the sandbox environment here: https://codesandbox.io/s/agitated-ardinghelli-fnoj15?file=/src/temp4.tsx:0-1206. import { FormControl, FormControlProps, Grid, GridProps } from "@mui/material"; interface ICustomControlProps { gridProps?: ...