Doug! Always great to see you.
Here's one that targets Mono/.NET and also includes setting up holes in NAT routers: https://github.com/RevenantX/LiteNetLib
Well... holy smokes on this one. This one is basically implementing everything we'd need, from the looks of it. It's very much like what I recall of Lidgren, except this looks a bit more evolved (to say the least). I'm quite happy to see the multicasting on there for LAN discovery. Dual mode for IPV6 is also of course very nice, since that's likely to (any year now, sigh) become more common. Basically running in "reliable mode" over UDP and then passing data of our own choosing is what we're doing. To some extent, that makes the network library itself a bit interchangeable.
Keith -- what might be nice is to migrate all the FORGE stuff and our networking code that goes with it out into the open-source moddable part of our code. All of that is open source now, anyhow. Depending on how similar the system above is, perhaps you or someone else could program that in as an option.
What might ultimately be a nice thing is a bit of an abstraction layer where we can swap out the underlying networking layer by just having it implement various interfaces or similar. That way in theory we could have a FORGE implementation and a LiteNetLib implementation, and the user can switch between them. Not useful in the long-term, probably, but in the next few months it would allow for some A:B performance testing in an easy fashion. Lidgren is also open source and has evolved in the past years, so it might also work as a third option to check on.
I imagine we have some folks here who would happily profile the transport layer for us if we had some options on that, while the actual "what we're sending via the transport layer" stays in its own logic area.
Basically kind of like how we can easily switch between DirectX and OpenGL and Vulkan and nobody notices a difference in actual functionality. Those in turn are running on top of variable drivers, etc. In our case, FORGE or LiteNetLib or Lidgren would be analogous to DirectX or OpenGL. The data we're passing in and getting out should be identical in all the cases, and these libraries tend to have a pretty similar setup for the bare-metal type approach that we take to things.
@Qoojo: Yep, endianness doesn't matter to us, partly because we're all in managed code and that abstracts that bit away from us. And yes, the host is the global manager for all things, and the clients talk to the host, which is also a client of itself. Clients request for things to happen, and then the host says "do this in future simulation step X" to all of them, and it happens on that step.
All of that logic is well above the transport layer, and pretty transport-layer agnostic. Even how Keith is serializing those commands into bytes is transport-layer-agnostic, because he has his own way of encoding things that is a lot more efficient than ascii, or even something like just raw int32s. We did a writeup with some table comparisons in an earlier design doc, and it's referred to as "BuzzSawBinary." It's actually smaller than gzip compressed data in a lot of cases, surprisingly.
Our problems are solely of the "hey I need to talk to you and I need you to talk back to me" variety with clients and hosts, not about knowing what to say after that's established. For customers, one of the big problems was always "who am I? who are you? why is there barbed wire between us??"