I'm working for a project in which i have to make a multiplayer battleship game, i've already completed most of the game logic (Angular 6 for the client and node.js + express for the server side), but i'm currently stuck on this since i'm new to socket.io, i've managed to get this down to try and connect 2 players :
var waitingPlayer = null;
ios.on('connection', (socket) => {
console.log('new user connected');
if (waitingPlayer == null) {
waitingPlayer = socket;
waitingPlayer.emit('waitingOpponent', {
text: "waiting for an opponent"
});
} else {
console.log('Match Found');
waitingPlayer.emit('matchFound', {
text: "Match Found",
});
socket.emit('matchFound', {
text: "Match Found"
});
}
});
If i try this it seems more than 2 users can connect together, is there a way to make some sort of lobby just between the 2 users that will be playing in the same game and then make more for the ones that will connect after? I've looked up some documentation this but couldn't find much.
Sounds like a good situation to use a Room with Socket IO. You can create rooms on the fly, and Socket IO basically manages them for you. So, you could create a room for each individual "Battle" or game. Put the two users in that games room. After that, you can broadcast to that room specifically. You will need to track the rooms somehow, but this should give you a starting point. Perhaps if each game that occurs has its own unique ID, the room name can be that ID. Then, you can broadcast to that specific room ID when needed.
Joining:
var gameId = "game_1234";
io.on('connection', function(socket){
socket.join(gameId);
});
Emitting:
io.to(gameId).emit('some event');
https://socket.io/docs/rooms-and-namespaces/
Related
I am working on an online website with real-time chat and I've been trying to set up socket.io rooms for a few days now, but one of my custom events just doesn't emit.
My website has 2 paths, / and /play. When someone fills out a form in the / path, the website redirects them to the /play path.
const io = require('socket.io')(listener);
io.on('connection', socket => {
socket.on('add user', data => { // This event gets emitted when the user submits the form at `/`, in a client-side js file.
socket.username = data.username;
socket.room = data.room;
socket.score = 0;
socket.join(data.room);
io.sockets.in(data.room).emit('user joined', { // This event gets 'handled', in another (not the same one) client-size js file.
username: data.username,
room: data.room
});
});
socket.on('disconnect', function () {
io.sockets.in(socket.room).emit('user left', {
username: socket.username,
room: socket.room
});
socket.leave(socket.room)
});
});
In the other client-side js file:
var socket = io.connect();
let joined = 0;
socket.on('user joined', data => {
joined++;
console.log(joined, data)
const elemental = document.createElement("LI");
const info = document.createTextNode(data.username);
elemental.appendChild(info);
document.getElementById('people').appendChild(info)
});
The add user event code executes just fine, but the user joined one doesn't..
I'm almost certain that it has to do with the paths. I read on socket.io namespaces but it seems like they are just like a different type of rooms.
Can someone tell me what's wrong?
EDIT: I should mention that no errors come up.
Without seeing your whole code, I'm going to assume that the socket on client-side.js code, is not joined to the data.room room, and that's why you don't get anything on the 'user join' event listener and that happens because you probably have multiple socket.io connections on the client side code.
You have multiple ways to solve this, depending on what you're trying to achieve.
Instead of only emitting to people on the room, emit to all sockets that an user joined a specific room. io.emit('user joined') instead of io.sockets.in(data.room)...
There should only be one single var socket = io.connect(); on the front end, otherwise the socket that's emitting: add user and therefore joined to data.room is not the same socket that's listening on: user joined, and that's why you never get the event on that socket, because you have 2 different sockets, one that joined the room, and one that is doing absolutely nothing except waiting for an event that will never occur.
I want to implement multiple chat using socket.io can, iwas able to implement one to one chat using one socket.room but i want to create multiple socket rooms to chat with multiple people parallel
below is the example i got in git but i was not able to understand that how it will work for multiple chat can any one explain
Server side
io = socketio.listen(server);
// handle incoming connections from clients
io.sockets.on('connection', function(socket) {
// once a client has connected, we expect to get a ping from them
saying what room they want to join
socket.on('room', function(room) {
socket.join(room);
});
});
// now, it's easy to send a message to just the clients in a given
room
room = "abc123";
io.sockets.in(room).emit('message', 'what is going on, party
people?');
// this message will NOT go to the client defined above
io.sockets.in('foobar').emit('message', 'anyone in this room yet?');
Client side
// set-up a connection between the client and the server
var socket = io.connect();
// let's assume that the client page, once rendered, knows what room
it wants to join
var room = "abc123";
socket.on('connect', function() {
// Connected, let's sign-up for to receive messages for this room
socket.emit('room', room);
});
socket.on('message', function(data) {
console.log('Incoming message:', data);
});
Imagine a user with multiple Chat Room to choose. When he click on a specific room he will get the information of it : in this example ChatRoom1.
The client socket (belonging to the user who has click on this room) has first to join this room
→ so that's why we have :
socket.emit(room, ChatRoom1)
// on the other part the server side will add the socket id of this client to this room :
socket.on('room', function(room) {
socket.join(room);
});
Now if you want to emit a message to all socket belonging to a specific room you use this command on the server part:
io.sockets.in(ChatRoom1).emit('message', 'what is going on, party
people?');
→ in fact this command just send a message to all socket who is belonging to ChatRoom1
→ Basically a Room is just an array of socketId
SO now on the client side you have this :
socket.on('message', function(data) {
console.log('Incoming message:', data);
});
this is just a listener, and you will get in console log :
Incoming message: what is going on, party people?
As you soon you enter in a chatRoom your socket join a room and will listen for each event until you ask the socket to leave the room
So now you can imagine that in your message you have your Id , Your Room ID and your content, when you send it the server will know where to send it.
Example:
message: {
content: 'blabla',
user: me,
date: now,
RoomId: ChatRoom1
}
On the client side each time a user send a message:
socket.emit('sendMessage', message)
On the server side:
socket.on('sendMessage', function(message){
io.sockets.in(message.RoomId).emit('message', message);
})
I'm making a multiplayer game that is using websockets to share the gamestate between all the connected players.
I decided to use socket.io with koa and now I'm facing the following problem.
First when a user connects to the server a new player is created.
const playersMeta = {}
io.on('connect', socket => {
const playerId = uniqid() // Creates a new unique id for a player
playersMeta[socket.id] = { playerId } // Stores the players id using the socket.id as key
socket.on('disconnect', () => {
delete playersMeta[playerId]
})
})
The thing is that a player needs to know the unique id that the server assigned to it. The reason is that there is a game state that tells every connected player where all the entities are. The camera follows the player that was created when you enter the game, that's why I need to know which player the camera should follow.
I can create a new socket.io event, an then the player emits an event that returns the id that you want but it looks like is getting too much complicated.
Events are nice to sync between different clients, in real time, data that need too change but I'm sure that the id of the player is not going to change.
Maybe is better to just create an api rest endpoint to get this data. I'm using Koa and I'm not sure if I can use the same websocket connection instead of using http.
Can't you just emit it to the same socket?
const playersMeta = {}
io.on('connect', socket => {
const playerId = uniqid() // Creates a new unique id for a player
playersMeta[socket.id] = { playerId } // Stores the players id using the socket.id as key
socket.emit('connected', { serverId: 'foo'});
socket.on('disconnect', () => {
delete playersMeta[playerId]
})
});
And on your client:
var socket = io('http://server');
socket.on('connected', function (data) {
console.log(data); // { serverId: 'foo'}
// do whatever you want with the servid
});
I am trying to set up a webrtc app. For now, it connects two people when they click connect. But if I have multiple connections open, and then when one of the people from the very first connection clicks disconnect, it literally disconnects EVERYONE who has a connection. I tried this with 3 connections, and disconnected the 2nd connection, and that only makes the 3rd connection disconnect, while the first is still connected.
So basically, it's a downward spiral. If a connection disconnects, then all connections created AFTER that one connection also get to disconnect. But all connections before that connection are still active.
I think it has something to do with the socket.io code, because in the console.log I am receiving the message from socket.io as someone in a totally different connection disconnects. Server code:
socket.on("sessiondesc", function(sessiondesc)
{
if (sessiondesc == true || sessiondesc.type === 'answer')
{
//the random room is generated before the socket.on sessiondesc thing.
socket.join(room)
}
socket.in(room).emit("sessiondesc", sessiondesc);
});
socket.on("quit", function(quit)
{
socket.leave(room)
});
This is client code:
socket.on("sessiondesc", function(sessiondesc)
{
//stuff I do here with webrtc... like create offer, answer, and such.
else if (sessiondesc == false)
{
pc.close();
pc = null;
console.log("GOT THE FALSE SESSION DESC! GOT IT");
quit = true;
socket.emit("quit", quit);
}
document.getElementById("disconnect").addEventListener("click", function(e)
{
console.log("The person clicked disconnect!");
quit = true;
sessiondesc = false;
socket.emit("sessiondesc", sessiondesc);
socket.emit("quit", quit);
pc.close();
pc = null;
});
So basically on all the other connections that disconnect, I can see the console.log("GOT THE SESSION DESC") thing... And I'm thinking like, why are these other rooms getting this sessiondesc? They shouldn't be, I'm only emitting it to a specific room!
I've got a question regarding client-management socket.io with node.js
I'm running a very basic socket.io application where several socket.io-clients connect to a socket.io-server. When I try to populate a list of clients I do it like this:
server.js:
var clients = [];
io.on('connection', function (socket) {
socket.emit('whoareyou');
socket.on('hithere', function(name){
clients.push(name);
socket.emit('clients', clients);
console.log(name+" connected");
socket.on('disconnect', function(){
console.log(name+" disconnected");
clients.splice(clients.indexOf(name), 1);
});
});
});
clients.js
var socket = io.connect(server, {
port: 80
});
socket.on('whoareyou', function(){
socket.emit('hithere',hostname);
});
});
The clients-emit is for a webpage to populate the client-list because I don't really know how to exchange this list with a webserver running on the same machine without emitting.
Now, what I could do is skipping this whole whoareyou and hithere-crap and saving the socket as a JSON-array in clients. The ugly detail about this is that I just want to use the hostname of the client as a nickname and this is not a part of the socket-JSON (btw: the ip-address is part of it).
the socket-io docs show a nice example of a chat-room here: http://socket.io/get-started/chat/ but the interesting parts are left out.
Does somebody know a nice way how to do this?