Jump to content
Einlander

Extra Networking commands.

Recommended Posts

I have found at least with the server, I need a little more data than I am currently supplied in lua.

These are some things I would find commands for very helpful.

  • Commands for:
    • How many peers are connected to the server.
    • What are their ip addresses. ipv4/ipv6. Just in case I need to add someone to a ban list for a little bit.
    • Return a list/table of currently connected peers.
    • Disconnect all clients at once.
    • Get the client/servers own external ip address (if possible)
    • Finding out the ip/address of server a client is connected to.

Share this post


Link to post

I also found that once a client lags, it will never be able to catch up. There is no way to tell the client that it is lagging behind. There should be an option to explicitly get data from channels.

Share this post


Link to post

You can retrieve more than one message per loop, which allows the server to catch up if a bunch are received at once.

Share this post


Link to post

That the solution that I came up with.Makes the entities move in fast forward. I have not added user input so I dont know how that will work yet. 

Share this post


Link to post
Quote
  • What are their ip addresses. ipv4/ipv6. Just in case I need to add someone to a ban list for a little bit.

I suggest you use SteamWorks API for this and check the SteamIDs of players instead.

Quote
  • Get the client/servers own external ip address (if possible)

I'm interested what use you have in mind for this. You can't really do much with the info since you can't really interact with other clients without having the server acting as a bridge in between, if you're thinking of having your client application connect directly to other client using their IP that is.

You should be able to interact with other clients if you're the host of the session though. But others won't be able to interact with each other without going through you (the server).

Share this post


Link to post
On 7/26/2017 at 8:30 AM, jen said:

I suggest you use SteamWorks API for this and check the SteamIDs of players instead.

I'm want to put this on different indie store-fronts so Steamworks isn't always an option. This also is easily defeated if they have multiple accounts but use the same ip to troll people. Also it helps when a person gets disconnected from a server. In source games, if you have the console enabled you can type 'status' and it will give you the ip address so you can get it later. I do not want the clients to tell each other their ip addresses.

Also it helps when you are self hosting the server yourself. It would be much easier if it gave you an address thats not 127.0.0.1

 

Share this post


Link to post

Why would your entities fast forward? Are you not having a queue of positions/rotations that you're lagging behind by x ms and interpolating between current and next in queue? 

Share this post


Link to post

When I introduce lag, it's not losing packets, so the all get there eventually. So when they get there they are processed. I have it so that every client update loop it reads from the network 10 times unless it is null. This allows it to 'catch up' with the server if it falls behind. There is no real way other than timestamps synced with the server to know if you are falling behind.

http://einlander.duckdns.org:8000/f/6525b9e505824bbba98f/

This is a link of how it looks. Right side is the client. I can hold a button and it will not check the network at all. And after 10 seconds iirc it will disconnect from the server. When it starts reading the network messages it has to go through the entire backlog since eNet has reliable messages, and wont drop them.

Share this post


Link to post

Right, so on the client side you can be storing all position updates from the server of all the remote/ghost clients in a queue. Then be tweening between the current position to the next position on the queue. This would give you smooth constant movement. The goal would to be able to keep 2 position items in the queue always while you are popping the current tweening one off it. If you have less than 2 then you know you're lagging because you haven't gotten an update from the server. If you have more than 2 then you know you just got an update from the server because you were lagging. In either cases you can handle it how you see fit. If more than 2 you can skip a couple or increase your tween steps slightly to catch up (but not fast forward like). If you have less than 2 then not much you can do but keep them there OR extrapolate for a couple seconds and fix it when you get packets again.

From my understanding this is similar to how Source engine does it. It visually lags other remote clients on a client by 50-100ms so that it always has a future position so they can interpolate.

Just throwing out ideas.

  • Upvote 1

Share this post


Link to post
On 26/07/2017 at 5:00 PM, Josh said:

You can retrieve more than one message per loop, which allows the server to catch up if a bunch are received at once.

Is there a particular way to do this? Or are you suggesting something like while( client->update() != nullptr ) { ... } ?

Share this post


Link to post

I may be saying something totally stupid and lame, but very few packets should be ordered/guaranteed.  For position, etc. just have an iterator and discard packets that are "older" than the last one received.  Hmmm, new feature candidate?

Share this post


Link to post
22 hours ago, Rick said:

Right, so on the client side you can be storing all position updates from the server of all the remote/ghost clients in a queue. Then be tweening between the current position to the next position on the queue. This would give you smooth constant movement. The goal would to be able to keep 2 position items in the queue always while you are popping the current tweening one off it. If you have less than 2 then you know you're lagging because you haven't gotten an update from the server. If you have more than 2 then you know you just got an update from the server because you were lagging. In either cases you can handle it how you see fit. If more than 2 you can skip a couple or increase your tween steps slightly to catch up (but not fast forward like). If you have less than 2 then not much you can do but keep them there OR extrapolate for a couple seconds and fix it when you get packets again.

From my understanding this is similar to how Source engine does it. It visually lags other remote clients on a client by 50-100ms so that it always has a future position so they can interpolate.

Just throwing out ideas.

With regards to player input, the player would be x frames behind the server. Would the server be applying the input to the most recent frame or x - 1 frames?

Share this post


Link to post

The player position data will always be late on arrival. There's no point delaying the process further in the server end. The Source Engine applies Dead Reckoning and interpolates the data it receives rather than deliberately delaying the processing in order to allow clients to catch up with each other.

Josh's comment is correct, just receive the new data asap and reject the old/late data. Apply interpolation on the data and distribute it as  "best fit" render of what happened on the other end of the network instead of scavenging for the truest data to simulate and reenact the other player's actions.

Share this post


Link to post

Yeah i just found a blog talking about this. http://www.gabrielgambetta.com/client-side-prediction-server-reconciliation.html This will probably need to wait till I have another day off to implement a clientside buffer. The server already has a rolling buffer of 5 frames and 20 world states just because. I knew I would use it one day, but I didn't know it would be this soon. I'm learning all sorts of new things about networking!

  • Upvote 1

Share this post


Link to post
10 hours ago, Josh said:

I may be saying something totally stupid and lame, but very few packets should be ordered/guaranteed.  For position, etc. just have an iterator and discard packets that are "older" than the last one received.  Hmmm, new feature candidate?

 

Would actually be so handy, Unity calls this their "State Sync' channel and it helps a ton to have.

But you still need to send the users inputs reliably to the server...

Share this post


Link to post
17 hours ago, Josh said:

For position, etc. just have an iterator and discard packets that are "older" than the last one received.  Hmmm, new feature candidate?

According to http://enet.bespin.org/Features.html under the heading "Sequencing" (third paragraph), ENet already does that:

Quote

For unreliable packets, ENet will simply discard the lower sequence number packet if a packet with a higher sequence number has already been delivered

 

  • Upvote 1

Share this post


Link to post

I don't think Leadwerks supports unreliable packets. We only have the option of Message.Reliable and Message.Ordered

BTW the headers say Message.Sequenced and not Ordered.

Share this post


Link to post

Is it possible to reduce the buffer to allow just one packet at a time? You could just replenish that buffer as soon as a new packet arrives. The latest packet would be the only packet that you have to process then, no need to process an entire queue of reliable packets.

Share this post


Link to post
22 hours ago, Einlander said:

I don't think Leadwerks supports unreliable packets. We only have the option of Message.Reliable and Message.Ordered

BTW the headers say Message.Sequenced and not Ordered.

ENet certainly does support unreliable channels... they just also happen to be sequenced.

 

22 hours ago, jen said:

Is it possible to reduce the buffer to allow just one packet at a time? You could just replenish that buffer as soon as a new packet arrives. The latest packet would be the only packet that you have to process then, no need to process an entire queue of reliable packets.

Well, the idea of a state-sync style (Discard older packets) channel and reliability at the same time directly conflict conceptually.. you can't say "Hey, I want to guarantee this packet arrives and is handed in-order... oh but I want it discarded if a newer packet comes." reliable means you NEED that packet to arrive, and in order... if you only want to process the latest packet, use unreliable channels, as Ma-Shell pointed out ENet already handles this.

 

Not trying to sound like a hater (okay maybe a little) but I feel like the networking implementation in Leadwerks just forces you to use ENet in a more limited, undocumented way... if you're not going to implement a high-level networking layer over ENet then what's the point? A high level networking layer should handle things like specific-data type writing for the engine instead of having to convert everything to a character array and send it... this should be handled for you so it can also handle endianness in the background (Which can't be handled by Lua.). As is it feels like using ENet is easier, and it definitely gives you more freedom... In an ideal high level networking API you should also be able to create your own MasterServer (This being a separate class from Server) that acts as the median for NAT punchthrough so people can do peer-to-peer and can host their own master server lists! The current setup in LE hides your underlying ENet objects so it makes it hard for users to extend it and add their own high-level features... anyways that's my rant.

  • Upvote 2

Share this post


Link to post

If your client is sending more packets than your server can handle, you're doing something wrong. This is where the concept of tick rates come in, they sync both client and servers in the same rythm. No point wasting extra packet that can't be processed by the server while it's busy anyway.

Unreliable channel, I take it, is not yet implemented in Leadwerks so a buffer of 1 might be a good alternative. Leave no space for extra packet so your server can't form a queue, just take in one packet and process it then wait for the next latest packet to arrive.

Share this post


Link to post
13 minutes ago, jen said:

If your client is sending more packets than your server can handle, you're doing something wrong. This is where the concept of tick rates come in, they sync both client and servers in the same rythm. No point wasting extra packet that can't be processed by the server while it's busy anyway.

Unreliable channel, I take it, is not yet implemented in Leadwerks so a buffer of 1 might be a good alternative. Leave no space for extra packet so your server can't form a queue, just take in one packet and process it then wait for the next latest packet to arrive.

Message.Ordered/Message.Sequenced is an unreliable channel... by default reliable packets are sequenced in ENet and CANNOT be unsequenced... ENet however provides a flag called ENET_PACKET_FLAG_UNSEQUENCED  you can use to make a channel both unreliable AND un-sequenced.

Assuming the name doesn't lie, it's safe to assume that under the hood Message.Ordered simply passes no flags to the enet_packet_create function.

  • Upvote 1

Share this post


Link to post

That's stupidly complicated for a "simple and robust network communication layer". I have a perfectly working network system using a different library and I have no further interest in ENet, so I won't comment any further and I'll leave it to you guys to sort your problem out.

Share this post


Link to post
11 minutes ago, jen said:

That's stupidly complicated for a "simple and robust network communication layer". I have a perfectly working network system using a different library and I have no further interest in ENet, so I won't comment any further I'll leave it to you guys to sort your problem out.

It's not really complicated... that's just kind of the point I was making, it's easy if you READ the enet documentation.. it's hard when it's hidden behind Leadwerks abstractions and undocumented...

No flags = Unreliable, sequenced.

Unsequenced flag = Unreliable, unsequenced.

Reliable flag = Reliable, sequenced.
The documentation makes it very clear.

ENet is EXACTLY what it says it is, a low-level networking API... if you want to build a networking API into the engine it should be a higher-level design.

  • Upvote 2

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...