zpl-c / librg Goto Github PK
View Code? Open in Web Editor NEW🚀 Making multi-player gamedev simpler since 2017
Home Page: https://zpl-c.github.io/librg/
License: BSD 3-Clause "New" or "Revised" License
🚀 Making multi-player gamedev simpler since 2017
Home Page: https://zpl-c.github.io/librg/
License: BSD 3-Clause "New" or "Revised" License
Accessing dimension outside of world bounds, leading to index wrap around
Just a question. In example-enet.c server and all clients in one file and ID's generation is easy:
for (int i = 0; i < MAX_CLIENTS; ++i) {
client_update(i, clients[i]);
}
in that case i is ID.
But in real case clients on different computers don't know about each other and therefore can't generate id's by itself.
But to recieve(read) something or to send(write) something it needs an ID as I understand.
librg_world_read(
world,
ID,
(char *)event.packet->data,
event.packet->dataLength,
NULL
);
librg_world_write(
world,
ID,
buffer,
&buffer_length,
NULL
);
I assume It's somehow must be generation on server.
How to generate different ID for different clients?
Maybe It's silly question and I don't understand something...
Hi,
Thanks for great library.
I wonder if the library support for encryption and checksum for packet/stream?
A per-dimension check is needed
An additional option is required for switching modes for (Invalidate, Repeat) to allow strict and repeated worlds respecively
Hey,
In the code documentation, the fist enum item is marked as “last” with “LIBRG_LAST_EVENT”.
Is that intended?
I think that should be moved to Line 390.
Related code:
https://github.com/librg/librg/blob/2f2dfd783bff7dceadf03dc7e514012a05822f50/include/librg.h#L388
Regards,
TheAifam5
https://github.com/reguider/librg/blob/6ac3b9c4e7865f28a2aea7d394ab422b3e4e1b6b/include/librg.h#L518
This causes unnecessary overhead when preparing call stack.
Either:
Currently, librg supports virtual worlds and an ability to set visibility on a per-entity level. The later feature can be extended to support both visibility and invisibility relations.
That would allow some entities sharing the same virtual world see specified entity only if:
Yo,
Will there be any possibility to add wrapper for C#?
Cheers.
On client side LIBRG_CLIENT_STREAMER_UPDATE
is still getting called after the client was disconnected from the server. I think streamed entities should be cleared after any sort of disconnect or at least not being called anymore.
Please excuse my naivety but I've never encountered single-header libraries till now.
I think this is a very nice library but I am rather confused about how I would go about using it.
I understand that if all the functions are 'inline' then there really isn't any true symbol definitions that could collide when linking multiple object files... But looking at the source of librg I am seeing functions which do not have any inline keyword specified anywhere, for example:
u64 librg_event_add(librg_ctx *ctx, u64 id, librg_event_cb callback) {
librg_assert(ctx);
librg_event_block *block = librg_event_pool_get(&ctx->events, id);
if (!block) {
librg_event_block arr;
zpl_array_init(arr, ctx->allocator);
librg_event_pool_set(&ctx->events, id, arr);
block = librg_event_pool_get(&ctx->events, id);
}
u64 offset = zpl_array_count(block);
zpl_array_append(*block, callback);
return offset;
}
I assume that there must be some non-conventional use of this header necessary to get it working otherwise if I were to include this file in multiple C files and then link them together I would get linker errors for multiple symbol definitions with the same name, wouldn't I?
Sorry if this is the wrong place to ask this question but I wasn't sure where else would be appropriate.
Also, why the #if 1 statements wrapping sections of code? Those seem pointless and I can't grasp what their purpose would be, other than to manually toggle the compilation of specific sections... But wouldn't that be better achieved by using actual #ifdef SOME_MACRO
switches where all the switches can be listed at the top of the file for ease of toggling?
What is the intended way to send inputs from client to server using this library?
By inputs I mean things like key held, look direction... They are sampled and sent at regular intervals. I can think of two ways:
Using message is one. However, messages are always sent as reliable which is not very optimal since client will keep sending (a buffer of) inputs anyway.
Another method is to create a "controller" entity and let client stream it. The data of that entity will be the client's inputs. This feels a bit weird.
Ideally, should there be a way to send unreliable messages? If I were to add another parameter, the number of librg_message_send
functions would double though.
Hey,
while reading the code I noticed that the vector3 is used. In 2D games, the z axis is used very rarely. Do you have plans to improve and minimize the packet size by supporting 2D only or allowing to use a custom implementation of vectors?
Regards,
TheAifam5
Hi, I'm testing librg in a huge world and I need relatively small chunks, so I'm currently using 1024x1024x1 chunks with a size of 10 x 10 x UINT16_MAX. The problem comes when entities mess around chunks above 2^15, a chunk is supposed to be up to 2^63 but for some reason, events, world_write etc won't work if the entities' chunks are above 2^15. I checked the code to see if there was any cast somewhere messing with the int64_t but couldn't find it, any idea why this could be happening?
A bit of a big thing, but if it can be implemented it will truely make librg cross-platform.
There is the Intel WebRTC Datachannel Microstack, a C99 little library which is conveniently also licensed under Apache 2.0:
https://github.com/HumbleNet/webrtc?files=1
And Humblenet has an example of a shared ABI between it and browser's RTC implementation:
https://github.com/HumbleNet/HumbleNet/blob/master/src/humblenet/src/libwebrtc.h
It's also a little similar to Enet with reliable/unreliable packets and peer to peer nature.
Raknet has feature called "timestamping": http://www.jenkinssoftware.com/raknet/manual/timestamping.html
librg media kit.
An error error: taking address of temporary array
occurred when compile C++ program include librg.h.
/home/user/app/src/librg.h: In function 'int32_t librg_world_fetch_owner(librg_world*, int64_t, int64_t*, size_t*)':
/home/user/app/src/librg.h:21559:59: error: taking address of temporary array
21559 | return librg_world_fetch_ownerarray(world, (int64_t[]){owner_id}, 1, entity_ids, entity_amount);
It works to change the line L21559 in librg.h
return librg_world_fetch_ownerarray(world, (int64_t[]){owner_id}, 1, entity_ids, entity_amount);
to
int64_t owner_ids[1]; owner_ids[0] = owner_id;
return librg_world_fetch_ownerarray(world, owner_ids, 1, entity_ids, entity_amount);
Client should be able to determine what state he currently is in, such as whether he's disconnected, currently connecting, awaiting authorization (waiting for connection accept event) and connected.
We already have librg_is_connected(..) method, which however is limited in its functionality. I'd recommend adding upper-mentioned states as a part of the library, so we can determine states easily.
Proposed methods:
librg_get_state(ctx)
for client-sidelibrg_peer_get_state(ctx, peer)
for server-side (optional)Can you post some examples or at least some notes regarding the projects emscripten port?
As title says, entities visibility seems like to have 'always' to owners instead of 'default'. Is this supposed to work like this or am I missing something?
I'm currently relying of the entity create/remove events to set the ownership.
In clients librg_event_owner_get(w, e) in client_read_create or client_read_update owner_id always the same for all entities_id.
I tested it in example-enet.c. Maybe it work like expected, but in that case client can't get real owner of entity... Maybe it's more related with enet than librg.
Can't get position data when entity created. In example example-enet.c I try to get position in client_read_create function but librg_event_size_get always returns actual_length 0.
librg_event_set(world, LIBRG_READ_CREATE, client_read_create);
int32_t client_read_create(librg_world *w, librg_event *e) {
int64_t owner_id = librg_event_owner_get(w, e);
int64_t entity_id = librg_event_entity_get(w, e);
printf("[client] An entity %d was created for owner: %d\n", (int)entity_id, (int)owner_id);
size_t actual_length = librg_event_size_get(w, e);
printf("[client] actual_length = %zu", actual_length);
if (actual_length != sizeof(vec3)) return 0;
char *buffer = librg_event_buffer_get(w, e);
vec3 position = {0};
memcpy(&position, buffer, actual_length);
return 0;
}
This not exist in eNet code (ENET_EVENT_TYPE_DISCONNECT_TIMEOUT)
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
and this function :
enet_packet_create_offset
using latest version of eNet from github
What is the intended way to send inputs from client to server using this library?
By inputs I mean things like key held, look direction... They are sampled and sent at regular intervals. I can think of two ways:
Using message is one. However, messages are always sent as reliable which is not very optimal since client will keep sending (a buffer of) inputs anyway.
Another method is to create a "controller" entity and let client stream it. The data of that entity will be the client's inputs. This feels a bit weird.
Ideally, should there be a way to send unreliable messages? If I were to add another parameter, the number librg_message_send
functions would double though.
The documentation says just to include "librg.h". But when I do just that and add this to my c++ project I got error:
librg/code/source/query.c: In function ‘int32_t librg_world_fetch_chunk(librg_world*, librg_chunk, int64_t*, size_t*)’:
error: taking address of temporary array
39 | return librg_world_fetch_chunkarray(world, (librg_chunk[]){chunk}, 1, entity_ids, entity_amount);
| ^~~~~~~
What I need to do to inlude library in c++ project? Maybe somehow link library like -lrg. Maybe I need add include some directories -I./librg/code. Or maybe I need to install somehow compiled lib. I use Ubuntu linux.
I'd like to use this library in my C++ project but due to some conversions that are only valid in C it won't compile:
ext/librg/librg.h|19756 col 20| error: cannot initialize a variable of type 'librg_world_t *' with an rvalue of type 'void *'
|| librg_world_t *wld = LIBRG_MEM_ALLOC(sizeof(librg_world_t));
|| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ext/librg/librg.h|19918 col 45| error: cannot initialize return object of type 'librg_event_type' with an rvalue of type 'int'
|| LIBRG_ASSERT(event); if (!event) return LIBRG_EVENT_INVALID;
|| ^~~~~~~~~~~~~~~~~~~
ext/librg/librg.h|2177 col 41| note: expanded from macro 'LIBRG_EVENT_INVALID'
|| #define LIBRG_EVENT_INVALID (-0x0006)
|| ^~~~~~~~~
ext/librg/librg.h|19921 col 12| error: cannot initialize return object of type 'librg_event_type' with an lvalue of type 'uint8_t' (aka 'unsigned char')
|| return e->type;
|| ^~~~~~~
ext/librg/librg.h|20656 col 14| error: cannot initialize a variable of type 'int64_t *' (aka 'long *') with an rvalue of type 'void *'
|| int64_t *results = LIBRG_MEM_ALLOC(LIBRG_WORLDWRITE_MAXQUERY * sizeof(int64_t));
|| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|| 4 errors generated.
Hey,
Would be nice to see the other possibilities if the function/variable/macro is marked as “deprecated”, so that others can find a better way to achieve similar thing than searching through whole code.
Related line:
https://github.com/librg/librg/blob/2f2dfd783bff7dceadf03dc7e514012a05822f50/include/librg.h#L374
Regards,
TheAifam5
When a client disconnects (or timeouts, doesn't matter) from the server there is one entity update event triggered after the disconnect event.
...
Update entity 1 for client 1773685128
Update entity 0 for client 647576079
Update entity 1 for client 1773685128
Update entity 0 for client 647576079
Update entity 1 for client 1773685128
Update entity 0 for client 647576079
Update entity 1 for client 1773685128
Update entity 0 for client 647576079
client 647576079 disconnected
Update entity 1 for client 1773685128
Update entity 0 for client 647576079
Log from discord:
../include/librg.h: In function ‘librg__space_insert’:
../include/librg.h:3104:31: error: inlining failed in call to always_inline ‘librg__space_insert’: recursive inlining
librg_inline librg_space *librg__space_insert(librg_ctx *ctx, librg_space *space, librg_space_node node) {
^~~~~~~~~~~~~~~~~~~
../include/librg.h:3139:26: note: called from here
librg_space *sub = librg__space_insert(ctx, (space->spaces+i), node);
Tested on: GCC 7.4
Hello,
I could be missing something, but when I shutdown my server, none of the connected clients receive any event; they all just timeout. Looking at librg_network_stop, there doesn't appear to be anything to handle currently connected clients. They just get deleted with the zpl table.
Would be happy to contribute here, but not sure if I am missing something.
Thanks.
returned indeces 0, -8, 8 for 8,8,0 world
no data gets included for 0 chunk size
If this is intended, why should handler return int32_t
and not u16
? I stumbled upon this, because I am sending kind of big packets and this just cuts it, without warning.
Update
I think i see, int32_t
because return negatives and handle those in some parts? So there is u16 precision limit per entity write?
After a client connects for the second time to a server it will not send any client streamed entity updates to the server. On first connect everything works just fine, but after reconnecting, the LIBRG_CLIENT_STREAMER_UPDATE
is called on client side but never reaches the server.
Proof of concept: https://github.com/markatk/librg-example
When initializing enet fails (for example due to an already bound port on server side), the librg_init
function does not give any result about it (except from the assert message). It would be nice to change the function to return a result or state so programs can do proper error management.
Librg is advertised as an MMO solution but authoritative servers, while possible, seem like an afterthought and I don't see any API for interest management. In fact I would say that librg is ideal for anything besides MMO.
Am I missing something obvious here?
When the server accepts a client connection, it would be nice for the server to be able to send data to the client with the LIBRG_CONNECTION_ACCEPT
event for initial setup (for example to set the initial position or health).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.