RevenantX / LiteNetLib

Lite reliable UDP library for Mono and .NET
https://revenantx.github.io/LiteNetLib/index.html
MIT License
3.04k stars 493 forks source link

Multiple channels per delivery type #67

Closed aienabled closed 5 years ago

aienabled commented 7 years ago

Hello! Are there any way of creating more than one sequenced channel? In Lidgren ( https://github.com/lidgren/lidgren-network-gen3/wiki/Sequence-Channels ) it's possible to have up to 31 sequence channels per any sequenced delivery method. I looked into the LiteNetLib source and it seems all the channels are created only once in NetPeer constructor. For me, it makes "sequenced" channel almost useless - I cannot even send health in one channel and ammo in another channel. Only the latest received NetPacket will be used - either ammo or health.

Regards!

RevenantX commented 7 years ago

Hi! There is only one channel per message type. I can implement if you really need. But library have option "MergeEnabled" that will merge packets (health and ammo) together if you send them immediately. You can send ammo and health together by hands (this is really small overhead. UDP header is 68 bytes). You can use Unreliable with manual sequence and "channels" :) I think multiple channels is rarely needed. But if you have opposite opinion - i will listen)

aienabled commented 7 years ago

I see. Well, it's not a satisfying for my needs. I mentioned health and ammo as an example. In most games there are much more things which need to be send in sequenced manner but in dedicated sequences. It's simply impossible (or too much extra network traffic) to put all the data into a single packet just because we cannot have dedicated sequences.

In my case, the idea is to have multiple channels per game entity for replication needs. The channels should be dynamically creatable and disposable when not needed anymore. For example, we need to replicate a few dozens of actors. Each one has its own properties (for example stats - such as health, shield, energy). Every property change needs to be replicated in a dedicated sequenced channel - dedicated per actor. So each actor will have a few dedicated sequenced channels (allocated when needed, disposed when not needed anymore) and network library will ensure that the client has the fresh properties of a every actor and no data is lost in transmission.

Of course, it's possible to write a custom "data" layer over the networking library (as mostly done in AAA games with custom engines). So this "data" layer will send the data in a single unreliable channel and manually do the reliablity and sequencing procedures to ensure all the data is transferred as expected. But it's a lot of work to do and it will have overhead.

Much better to have this functionaly in the network library (as done in Lidgren). The only problem with Lidgren is that it cannot dynamically allocate/dispose channels and the channels amount is limited to 31 per (sequenced) delivery method. I have hacked all that into my Lidgren fork but don't really like the code and now consider other networking libraries.

RevenantX commented 7 years ago

@aienabled do you need multiple channels only with "Sequenced" method?

aienabled commented 7 years ago

@RevenantX, not only, in my game I already use this with any net delivery method which uses sequencing - such as unreliable sequenced, reliable unordered, reliable sequenced, reliable ordered.

RevenantX commented 7 years ago

@aienabled in what situation you need multiple channels with "reliable unordered" message type?

aienabled commented 7 years ago

@RevenantX, if player need to receive data as soon as possible and packet order is not important. For example, chat incoming messages. The ordering could be applied later based on the timestamp of the message. But it's important to receive all incoming chat messages. Though, you're right, it's very rarely used and mostly could be replaced with reliable ordered without much problem to the player.

aienabled commented 7 years ago

The thing is, in Lidgren network you could specify sequence channel for any outgoing message. It's not used for the unreliable delivery method, but for any other delivery method, there are 31 channels.

RevenantX commented 7 years ago

@aienabled I understand useful scenario of multiple channels with "Sequenced" type and "Reliable Ordered" :) But not with "reliable unordered"

aienabled commented 7 years ago

@RevenantX, I think, if you can make it generalized for other delivery methods, it will be no problem to have it for "reliable unordered" also. That's how it done in Lidgren.

RevenantX commented 7 years ago

@aienabled I can implement this feature only for "Sequenced" and "Reliable Ordered". Because this feature will add little overhead in packet size, used memory and performance. And maybe this feature will be optional.

aienabled commented 7 years ago

@RevenantX, that's great! Especially if I will be able to dynamically allocate channels and dispose them when they're not needed anymore (i.e. packets are acknowledged and channel is empty/drained). Up to 256 channels per delivery method will be enough for our needs. Regarding "optional feature" - of course, not everyone need channel numbers (and extra byte per packet to determine channel number) for this. It could be optional with a compile flag or runtime boolean flag, I have nothing against it.

BTW, I missed - are there no unreliable sequenced channels? That's quite useful for me, for example, to send input - I never need to re-send it (no reliability is required as fresh data will be sent soon, it's simply sent with some interval) but it's important to use only latest input. Of course, I could add input Id number to determine if we have newer data, but it's simply better to have such option in network library.

RevenantX commented 7 years ago

@aienabled

BTW, I missed - there are no unreliable sequenced channels?

Sequenced - is unreliable sequenced. There is no "Lidgren" method "reliable sequenced".

aienabled commented 7 years ago

@RevenantX, wow, that's frustrating. I just checked my code for ReliableSequenced usage and found that I'm using it already in 21 places and where it's important to reduce traffic (by sequencing), but have reliablity. It's most popular network delivery method for me. For example, character stats (health/energy/etc), crafting progress, weapon firing mode. It's all important to have, reliably, latest value, but with reduced traffic (by sequencing - not re-sending late data). Should I create another issue here for this feature?

RevenantX commented 7 years ago

Should I create another issue here for this feature?

If you need this feature - sure. :)

miketheprogrammer commented 6 years ago

@aienabled @RevenantX : Bump, but let me add some clarity. @aienabled , you should really rethink the reliability of messages. Amazon lumberyard would tell you that health, energy, etcetera are all eventually consistent, and that a reliable message should only be pumped, after those values have stopped updating for some grace period.

@RevenantX . This feature is essential to any game trying to implement fine grained Interest Based replication, with dedicated channels so that reliable channels can have their own buffers, this prevents all your events from locking up, instead of just the channel that is being abused currently.

I see no reason why channels should be implemented for unreliable messaging except for uniformity. The user of the library can implement it themselves at the application level, however alot can be said for uniformity of implementation.

I give my +1 for this feature, and will gladly donate to see it implemented. Thankfully it is one of those things that is not necessary for a project on day 1 but can be added when it is complete.

RevenantX commented 6 years ago

@miketheprogrammer i will add multichannel mode after i complete ReliableSequenced packet type)

rikimaru0345 commented 6 years ago

So far I have worked around this by simply opening multiple connections to the server.

Are there any arguments against this except for a tiny bit more memory consumption?

aienabled commented 5 years ago

I see there is still no multichannel support, though a lot of great improvements are done and I'm really impressed with all these changes and overall project activity.

I wish to try LiteNetLib with my MMO project I talked about before (game page, now available as a free open alpha and getting very positive reviews; currently using Lidgren.Network) but multiple channels support is one of the requirements. It's possible but not reasonable to implement on the application level (by using unreliable channel and manually sending and processing ACKs) - I believe it will be beneficial to have this feature for everyone, implemented and perfected in the network library itself.

Ability to transfer certain packets as sequenced (with or without reliability) is very useful. But the usefulness of the sequenced channel is very limited if there is only a single channel of this kind for the whole game connection - it could be beneficial for a certain kind of session-based games like a FPS shooter where a basic set of data is replicated every other frame and client should receive only the latest version of this data (but in that case it's actually could be easily implemented on an application level just by checking the relative sequence number of the packet). For any large project (like an MMO game I'm building) multiple channels support is a real necessity and implementing this in a proper way (performance-wise) is a serious challenge.

Also, I would prefer to contribute in an open-source project to make this feature useful and optimized for everyone than to implement it on an application level specifically for my game engine.

Regards!

RevenantX commented 5 years ago

@aienabled i am working on this feature. Just want to make it with maximum usability, so it takes some time)

TimonPost commented 5 years ago

I am researching this topic also and was curious if this library had this functionality and saw this. I originally saw this idea in Raknet. RakNet is a C++ lib like this one. They call it ordering streams. You could use this as a reference: http://www.raknet.net/raknet/manual/sendingpackets.html

Just a summary of what they are:

What?

You can think of ordering streams as something to separate the ordering of packets that have totally no relations to one and another. A game-developer might want to send some data ordered; some data unordered while other data needs to be send sequenced etc. This idea from RakNet who already has implemented this functionality (check out ordering streams for more info)

How?

To make this more clear let's imagine the following scenario's:

  1. Let's say the player firing packets had to be ordered relative to player movement packets because you wouldn't want the shot to originate from the wrong position.
  2. You want to chat messages to be ordered.

Player movement and chat messages are totally not related to one and another. You don't want the movement packets to be disturbed if a chat message is dropped. It would be nice if we can order player movement, chat messages separated from each other.

This is exactly where ordering streams are for. The user can, for example, say: "Let me put all chat messages on ordering stream 1 and all player and bullet movement packets on ordering stream 2". Since once a bullet is shot

This way you can have different types of packets ordered separately from each other.

rikimaru0345 commented 5 years ago

@RevenantX I assume this will be implemented (correct me if I'm wrong) and I have a question.

How will the implementation look like roughly? Will we be able to set what channels there are and what their transport settings are?

Like before/while constructing the NetManager maybe we could do something like:

AddChannel(id: 1, deliveryMethod: DeliveryMethod.ReliableOrdered, debugChannelName: "abc");

and LiteNetLib would just ensure that the channel IDs start at 1, there are no IDs skipped, no IDs are assigned twice... and of course some upper limit (32 channels at most I thought was mentioned at some point?)

RevenantX commented 5 years ago

@rikimaru0345

I assume this will be implemented (correct me if I'm wrong) and I have a question.

Yes. There is work in progress. Right now there is some things that i don't solved, so i cannot say anything this)

Krakean commented 5 years ago

@RevenantX any progress on this ticket?

RevenantX commented 5 years ago

@Krakean @aienabled you can test bleeding edge here: https://github.com/RevenantX/LiteNetLib/tree/channels

RevenantX commented 5 years ago

https://github.com/RevenantX/LiteNetLib/commit/8d7336e68c57422189161f94fea60f0c2d87b3c4 integrated to master