Have you ever wondered why is it always so hard to make a multi-player game, even the most basic one? And the complexity even increases with bigger amounts of players and things you need to sync between your clients. This library is designed exactly to solve that problem. It has a simple interface with highly flexible base which allows you to build great things!
Many people think that implementing networking solution for your game project is the most complicated and time consuming task. We believe many people are afraid to even try, which results in the fact, that you almost never see small games made by indie developers having any type of networking involved.
Thus we hope that with this library, which is just a small step in the direction, we might help anyone and everyone who wants to add a multi-player capabilities inside one's game.
librg is a light-weight "mid-level" (can be considered/used as both low-level and high-level) game networking library. It is based on our fork of ENet library, which gives us low-level UDP networking with optional reliablility. That, accompanied by our, hand-made general purpose zpl library, high-peformant network culling algorithms, event-based approach to creating and managing your flow and simple inteface, gives you tools to create a simple and at the same time powerful mutiplayer based project.
As we've mentioned before, librg has a simple interface. Like many C libraries, it has some sort of application context, which makes it thread-safe and offers the ability to run multiple instances under the same process. Here is sample server code:
Everything is built around events, something gets created - the related event gets triggered. Your task as a developer is to use these events and write appropriate handlers.
Let's look at the example, client connects to the server, spawns on the map, and librg triggers
LIBRG_ENTIY_CREATE event for every entity in the player's range:
void// ...// register the handler// ...
This way, the client on his side creates all entities that server tells him to create. And the best part is that, server will tell only about those entities that are in the specified range. This allows you to have bigger amounts of synced data, using the same amount of bandwidth.
Same concept applies when your client's entity needs to be removed, you just register the
LIBRG_ENTITY_REMOVE handler, and unspawn the entity from the game world.
What if you need, (and most likely you do), to send some data, on every server tick, like object position or rotation, or maybe even object color.
You need to register a handler for the
LIBRG_ENTITY_UDPATE event, but this time you need to do it on both sides!
/* server side */void/* client side */void
Now, when you write data on the server, you just read it back on the client in the same order as it was written. That's it, you have a server streamed sync!
Considering you've already synced your server and clients after reading the previous section, you might want to trigger some actions/commands on the server, so it could become interactive. And the way you can do it is quite simple, it is similar to events you are familiar already, so it should be an easy task:
/* server side */voidvoid// ...// .../* client side */// .../* send an empty message *//* send some clean data */
If you want your client to send updates about one or more entities to the server, and you need a simple and fast solution, you can stream your entities right from your clients. For example, you have a huge game world (e.g. open world sandbox game), where there are some entities which are not players, however you need someone to control them. Considering the fact that you probably don't have any game logic on the server, you need one of your clients to send updates about ingame entities to other clients.
This can be achieved quite easily, you can just call method
librg_entity_control_set on the server, for specific entity.
It will make provided client responsive for streaming this entity to the server.
Now, what you need to do is just to update that entity data from your local client's game world. And that can also be achieved quite easily:
/* client side */void// ...// ...
Now on the server side, you pretty much do the same, it is very similar to what we did for entity update, with only difference being that we use
LIBRG_CLIENT_STREAMER_UPDATE event id.
You can and MUST (not really, but we really advise you to) look into the source code (librg.h). There we have many helpful (and not really) comments that will guide you or at very least give you explanation what is this or that, why it's needed, and how to use it.
Also you can look inside our test folder, there are many different things. It's usually used for the development purposes, but I guarantee you can find something interesting in there.
There are multiple way of how you can "download" the library:
npm install librg.cin folder with your project, that's it!
node_modulesfolder, however you can move it or rename it, if you are not planning to fetch any udpates via npm)
Essentially, what you will need to have in the result is a set of single-header libraries. Which you can just put in the same folder and point the compiler include ther.
The library is built with single header-only file design. So everything librg provides is located in includes/librg.h file.
However it has dependencies. All of them are also single header-only libraries.
Current list and description of dependencies looks like this:
|enet||enet is a quite popular high performant low-level network library. A core for the librg.|
|zpl||zpl is a basic library containing many functions you would use in everyday programming.|
|zpl-math||zpl-math is obviously a math library. Used mostly in the streamer part.|
librg comes with a CMakeLists.txt file. You can use it to integrate the library inside your project. Or use it as a boilerplate for new project. There is also the build.sh shell script, which is usually used for the development purposes, however it also can be used as an example of instructions you need to provide to your compiler.
As "built-in" server:
Server can be merged with the client and run even from the same thread. It will result in a quite common concept of client-hosted game sessions for friends. However it requires user, or you, to deal with stuff like public ip/visibility.
As proxy server:
Would you like to have a dedicated server solution? Server will be used as a proxy to store and send accumulated player data. Considering the fact that you don't have (almost) any game logic on the server side, it can handle big amounts of clients. Similar example can be something like San-Andreas Multiplayer.
As thin client (advanced):
For client side, you will use thin-client "pattern". All user actions will be sent directly to the server. Requires you to write all the server side systems, like physics handling, game world management, and gameloop on the server side.
Any other possible way that was not mentioned.
We started testing the library for different platforms. This table provides some sort of description for compatibility. If you have tested it, and it compiles, or it perhaps stopped compiling, please feel free to describe the issue in the issues.
|Compiler / Target||Windows||Linux||macOS||iOS||Android|
list table of contributors looks like this:
If you want to help us - you are very welcome. New features, performance optimizations, fixes for bugs and errors are waiting for you!
Last time we checked it was Apache License 2.0. However we suggest you to check it again, what if it has been changed!