Currently I am using Amazon Windows server for my game. I am using lua Noobhub for gideros and I have developed my own socket system with C# which contains all game logic. It works really good for now Even if I am in Turkey and the Server is in West US.
Does Noobhub support private messages? It would be handy to send static property data (player name, for example) to new players subscribing to an existing channel.
After a little digging it seems private messages are not supported.
This is what I want to do:
1. Player A subscribes to channel and sends static properties to all players 2. Player B subscribes to channel and sends static properties to all players 3. Player A sends their static properties only to player B
Brainstorming how this could be done with Noobhub I've come up with two (inefficient) options:
Option 1: Player A and B create a new instance of Noobhub and subscribe to it to send this message. This is not ideal because it requires a new connection to Noobhub for all players already subscribed to the channel when player A joins, and they also have to wait for player B to subscribe before they can send the data to be sure they get it.
Option 2: Player A sends their static property to the entire channel. This is not ideal because all players already subscribed to the channel when player A joins will receive redundant data.
Is there a better option I'm overlooking?
If you didn't have to subscribe to a channel to send messages to it all players could have a public and a private channel, and these messages could be sent directly to the private one. In my tests it appears you have to be subscribed to a channel to send messages to it, though.
Thanks @jdbc. Looking at the code in your project it seems it's different in that it's a two player game. The game I'm building is an open world where players can drop in and out. There would probably be 100 players, or so, per public channel/game world.
Maybe I missed something in your code. Any idea of how to achieve the flow from my previous post?
1. Player A subscribes to channel and sends static properties to all players 2. Player B subscribes to channel and sends static properties to all players 3. Player A sends their static properties only to player B
Or maybe there is a better way for players to share their static properties.
I think the only way is to include user Id into the message, and make all other instances ignore the message if Id is not for current user. Yes you are still sending it to all users though
Well, yeah, you usually include sender userid and receiver userid in message, if youre publishing to some group channel, like "lobby". But then clients should unsubscribe and subscribe to uniq channel where game interaction should happen. Thats generally called matchmaking. First, you find out who is up for a game, and then send message "user_XXX_pls_join_uniq_channel_YYY". User XXX joins that channel, and there you go.
Creating another instance of Noobhub is no big deal (I always do that in multiplayer). Nodejs server can handle really high concurrency, up to a million on hi-end hardware and synthetic tests. Once your game reaches 1M concurrent users, Id say you've known success :-)
Thanks @overtorment. Well, the problem in my case wouldn't be the server, at least not initally; it would be the client. If mobile phone connections are slowed down because of redundant data continuously being sent and received, maybe the game isn't as likely to achieve success in the first place.
I suppose Noobhub is better suited for a set number of players and games with a start and an end, rather than games like Agario, or chats for that matter, that are ongoing and the player count is variable.
Although, private messages would solve this particular issue, as would sending messages without having to subscribe to a channel first. Would either of those changes be a bit tricky technically, or maybe just the wrong thing for this kind of multiplayer backend?
With a bit of tinkering, I've managed to solve the issue!
I'm used to multiplayer servers that rely on each message or action being verified by the server. Noobhub appears to be less strict, and allows a message to be sent together with the subscription of the channel.
This means I can send a private message to a player without first having to wait to join the channel.
So for:
"3. Player A sends their static properties only to player B"
I simply do this:
1. Each player is subscribed to a private channel named by their unique ID 2. Player A subscribes to player B's private channel 3. Player A immediately sends their static properties to player B's channel 4. Player A unsubscribes the channel immediately
Because of the way Noobhub works, player B gets the message and all is good in the world. No redundant data is sent or downloaded by clients at any time. Boom!
Hi @Overtorment. I'm using strict.lua to avoid accidentally creating global variables. This breaks noobhub.lua because the platform detection code is relying on global vars. Would it be possible to declare these vars before checking them, or solving this in some other way?
For now I'm commenting out the code for the other platforms.
@totebo - I have read many debates on TCP vs UDP in the last few days and in the end TCP is just fine. To make things more efficient you can modify the code (java and lua) to use smaller command string. I currently have the thing working with "BS" and ES" for BeginSubscribe/EndSubscribe and "BD" and "ED" for BeginData/EndData. If I can get away with just using the head Id that will be even better.
I'm now working on decoding the JSON strings sent from the client and performing operations on them inside noobhub. The decoding turns out to be rather trivial once you findout that JSON functionality is built into node.js
UDP is faster, but in most cases TCP/IP is good enough.
I was wondering about shortening the start/end strings. My impression was that this is risky, because the sever doesn't see the each individual message, rather it sees a continuous string if data. So if any of your messages contain "BD" or "ED" there would be an issue. Not sure if that's true?
@antix, @totebo , TCP is a stream and you cant just throw away markers of beginning & end of data, because sometimes in chunks of data you receive you might get several messages at once (for example, right after SUBSCRIBE you can get the first real json message).
But shortening the markers is an OK idea, if in your specific case they will _remain_unique_.
Slight problem here. If any client sends __JSON__END__ (or whatever identifier you use) as part of their mesage then all clients in the channel will freeze
After looking about in the lua code I see that in the enterFrame() function you are searching for "__JSON__END__" from the beginning of self.buffer which is causing the issue. Instead you should search for that at the very end of the buffer (minus the size of the string you are searching for), so in the case of the original noobhub...
local finish =string.find(self.buffer, "__JSON__END__", #self.buffer -13)
@Overtorment - yep, but you never know when some disgruntled client decides to crash the channel. scanning for the string from the end of the buffer fixes it anyways
*edit* With the exception of multiple messages in the buffer I think
Ah now I get you, yeah that's what I meant before - the message can't contain the identifier. This is a bit unstable regardless, because their username can contain the identifier by chance, or a message can. Scrambling all messages sent could fix it (and unscramble on receiving of course). Or, as you say, run all messages through a check before you send them.
@jdbc i want to ask about your sample project using this library. Is the ball's movement also synced between devices like the paddle? Or its not, the ball going on their own but still on the same route on each device?
Comments
This is what I want to do:
1. Player A subscribes to channel and sends static properties to all players
2. Player B subscribes to channel and sends static properties to all players
3. Player A sends their static properties only to player B
Brainstorming how this could be done with Noobhub I've come up with two (inefficient) options:
Option 1: Player A and B create a new instance of Noobhub and subscribe to it to send this message. This is not ideal because it requires a new connection to Noobhub for all players already subscribed to the channel when player A joins, and they also have to wait for player B to subscribe before they can send the data to be sure they get it.
Option 2: Player A sends their static property to the entire channel. This is not ideal because all players already subscribed to the channel when player A joins will receive redundant data.
Is there a better option I'm overlooking?
If you didn't have to subscribe to a channel to send messages to it all players could have a public and a private channel, and these messages could be sent directly to the private one. In my tests it appears you have to be subscribed to a channel to send messages to it, though.
It uses public and private channels.
Maybe I missed something in your code. Any idea of how to achieve the flow from my previous post?
1. Player A subscribes to channel and sends static properties to all players
2. Player B subscribes to channel and sends static properties to all players
3. Player A sends their static properties only to player B
Or maybe there is a better way for players to share their static properties.
Yes you are still sending it to all users though
But then clients should unsubscribe and subscribe to uniq channel where game interaction should happen. Thats generally called matchmaking.
First, you find out who is up for a game, and then send message "user_XXX_pls_join_uniq_channel_YYY". User XXX joins that channel, and there you go.
Creating another instance of Noobhub is no big deal (I always do that in multiplayer). Nodejs server can handle really high concurrency, up to a million on hi-end hardware and synthetic tests.
Once your game reaches 1M concurrent users, Id say you've known success :-)
Likes: jdbc
I suppose Noobhub is better suited for a set number of players and games with a start and an end, rather than games like Agario, or chats for that matter, that are ongoing and the player count is variable.
Although, private messages would solve this particular issue, as would sending messages without having to subscribe to a channel first. Would either of those changes be a bit tricky technically, or maybe just the wrong thing for this kind of multiplayer backend?
I'm used to multiplayer servers that rely on each message or action being verified by the server. Noobhub appears to be less strict, and allows a message to be sent together with the subscription of the channel.
This means I can send a private message to a player without first having to wait to join the channel.
So for:
"3. Player A sends their static properties only to player B"
I simply do this:
1. Each player is subscribed to a private channel named by their unique ID
2. Player A subscribes to player B's private channel
3. Player A immediately sends their static properties to player B's channel
4. Player A unsubscribes the channel immediately
Because of the way Noobhub works, player B gets the message and all is good in the world. No redundant data is sent or downloaded by clients at any time. Boom!
For now I'm commenting out the code for the other platforms.
Likes: antix
Likes: antix
Personally I don't think there is any need for "__ENDSUBSCRIBE__" but I thought I would ask here in case there are any ramifications I haven't seen.
I'm now working on decoding the JSON strings sent from the client and performing operations on them inside noobhub. The decoding turns out to be rather trivial once you findout that JSON functionality is built into node.js
I was wondering about shortening the start/end strings. My impression was that this is risky, because the sever doesn't see the each individual message, rather it sees a continuous string if data. So if any of your messages contain "BD" or "ED" there would be an issue. Not sure if that's true?
Likes: antix
But shortening the markers is an OK idea, if in your specific case they will _remain_unique_.
Likes: antix
After looking about in the lua code I see that in the enterFrame() function you are searching for "__JSON__END__" from the beginning of self.buffer which is causing the issue. Instead you should search for that at the very end of the buffer (minus the size of the string you are searching for), so in the case of the original noobhub...
Just modify the code as in my post and you shouldn't have any issues.
On the other hand, last time I touched Gideros port was a long time ago...
>> If any client sends __JSON__END__ (or whatever identifier you use) as part of their mesage
Don't send such markers in messages :-)
Or replace markers with your own very unique ones.
Likes: antix
*edit*
With the exception of multiple messages in the buffer I think
Likes: antix