netsync improvements
parent
37db0c09fe
commit
4391fa7b33
|
@ -0,0 +1,176 @@
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
#define WS 32
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WALL=2, DOOR=4
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int16_t id:8;
|
||||||
|
int16_t flags:8;
|
||||||
|
} cell_t;
|
||||||
|
|
||||||
|
#define cell_t(...) C_CAST(cell_t, __VA_ARGS__)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
cell_t grid[WS*WS];
|
||||||
|
mesh_t level;
|
||||||
|
} world_t;
|
||||||
|
|
||||||
|
static world_t world;
|
||||||
|
|
||||||
|
void world_init() {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < WS; ++i) {
|
||||||
|
for (j = 0; j < WS; ++j) {
|
||||||
|
if (i == 0 || i == WS-1 || j == 0 || j == WS-1) {
|
||||||
|
// Border cells
|
||||||
|
world.grid[i*WS + j] = cell_t(0, WALL);
|
||||||
|
} else {
|
||||||
|
// Interior cells
|
||||||
|
world.grid[i*WS + j] = cell_t(rand()%3, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
world.level = mesh();
|
||||||
|
|
||||||
|
|
||||||
|
const int cube_vertices = 24;
|
||||||
|
const int cube_triangles = 12;
|
||||||
|
const int vertex_count = WS * WS * cube_vertices;
|
||||||
|
const int index_count = WS * WS * cube_triangles * 3;
|
||||||
|
|
||||||
|
struct vert {
|
||||||
|
vec3 pos;
|
||||||
|
vec3 normal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vert verts[vertex_count];
|
||||||
|
|
||||||
|
unsigned index_data[index_count];
|
||||||
|
|
||||||
|
int vertex_index = 0;
|
||||||
|
int index_index = 0;
|
||||||
|
|
||||||
|
static vec3 normals[6] = {
|
||||||
|
{1, 0, 0}, {-1, 0, 0},
|
||||||
|
{0, 1, 0}, {0, -1, 0},
|
||||||
|
{0, 0, 1}, {0, 0, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int z = 0; z < WS; ++z) {
|
||||||
|
for(int x = 0; x < WS; ++x) {
|
||||||
|
if(world.grid[z*WS + x].id >= 0) {
|
||||||
|
for(int face = 0; face < 6; ++face) {
|
||||||
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
|
||||||
|
vertex_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 12 triangles for the cube
|
||||||
|
static unsigned indices[12][3] = {
|
||||||
|
{0, 1, 2}, {2, 1, 3}, {4, 5, 6}, {6, 5, 7},
|
||||||
|
{0, 4, 1}, {1, 4, 5}, {2, 6, 3}, {3, 6, 7},
|
||||||
|
{0, 2, 4}, {4, 2, 6}, {1, 3, 5}, {5, 3, 7}
|
||||||
|
};
|
||||||
|
for(int i = 0; i < 12; ++i) {
|
||||||
|
for(int j = 0; j < 3; ++j) {
|
||||||
|
index_data[index_index++] = vertex_index - 24 + indices[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh_update(&world.level, "p3 n3", sizeof(struct vert), vertex_count, verts, index_count, index_data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_world() {
|
||||||
|
static mat44 M; do_once id44(M);
|
||||||
|
static mat44 VP; multiply44x2(VP, camera_get_active()->proj, camera_get_active()->view);
|
||||||
|
|
||||||
|
static const char *vs =
|
||||||
|
"#version 130\n"
|
||||||
|
"//" FILELINE "\n"
|
||||||
|
"uniform mat4 M,VP;\n"
|
||||||
|
"in vec3 att_position;\n"
|
||||||
|
"in vec3 att_normal;\n"
|
||||||
|
"out vec3 v_normal;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" v_normal = normalize(att_position);\n"
|
||||||
|
" gl_Position = M * VP * vec4( att_position, 1.0 );\n"
|
||||||
|
"}\n";
|
||||||
|
static const char *fs =
|
||||||
|
"#version 130\n"
|
||||||
|
"//" FILELINE "\n"
|
||||||
|
"in vec3 v_normal;\n"
|
||||||
|
"out vec4 fragcolor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
"fragcolor = vec4(v_normal, 1.0);\n" // diffuse
|
||||||
|
"}";
|
||||||
|
|
||||||
|
static unsigned program; do_once program = shader(vs, fs, "att_position,att_normal", "fragcolor");
|
||||||
|
shader_bind(program);
|
||||||
|
shader_mat44("VP", VP);
|
||||||
|
shader_mat44("M", M);
|
||||||
|
|
||||||
|
mesh_render(&world.level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
window_create(80, WINDOW_MSAA8);
|
||||||
|
window_title(__FILE__);
|
||||||
|
|
||||||
|
// init world
|
||||||
|
world_init();
|
||||||
|
|
||||||
|
// load all fx files
|
||||||
|
fx_load("fx**.fs");
|
||||||
|
|
||||||
|
// load skybox
|
||||||
|
skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0); // --mie for rayleigh/mie scattering
|
||||||
|
|
||||||
|
// camera
|
||||||
|
camera_t cam = camera();
|
||||||
|
cam.speed = 0.2f;
|
||||||
|
|
||||||
|
// audio (both clips & streams)
|
||||||
|
// audio_t SFX1 = audio_clip( "coin.wav" );
|
||||||
|
// audio_t SFX2 = audio_clip( "pew.sfxr" );
|
||||||
|
// audio_t BGM1 = audio_stream( "waterworld-map.fur"); // wrath_of_the_djinn.xm" );
|
||||||
|
// audio_t BGM2 = audio_stream( "larry.mid" );
|
||||||
|
// audio_t BGM3 = audio_stream( "monkey1.mid" ), BGM = BGM1;
|
||||||
|
// audio_play(SFX1, 0);
|
||||||
|
// audio_play(BGM1, 0);
|
||||||
|
|
||||||
|
while (window_swap()) {
|
||||||
|
// input
|
||||||
|
if( input_down(KEY_ESC) ) break;
|
||||||
|
if( input_down(KEY_F5) ) window_reload();
|
||||||
|
if( input_down(KEY_W) && input_held(KEY_LCTRL) ) break;
|
||||||
|
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
|
||||||
|
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
||||||
|
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
|
||||||
|
|
||||||
|
// fps camera
|
||||||
|
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||||
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||||
|
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
|
camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
|
||||||
|
camera_fps(&cam, mouse.x,mouse.y);
|
||||||
|
window_cursor( !active );
|
||||||
|
|
||||||
|
fx_begin();
|
||||||
|
skybox_render(&sky, cam.proj, cam.view);
|
||||||
|
|
||||||
|
draw_world();
|
||||||
|
fx_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ void bind_netbuffers(int64_t self_id) {
|
||||||
|
|
||||||
for (int64_t i=0; i<MAX_CLIENTS; ++i) {
|
for (int64_t i=0; i<MAX_CLIENTS; ++i) {
|
||||||
world.player[i].color = colors[i%(sizeof colors / sizeof colors[0])];
|
world.player[i].color = colors[i%(sizeof colors / sizeof colors[0])];
|
||||||
network_buffer(&world.player[i], sizeof(struct player_t), i!=self_id ? NETWORK_RECV : NETWORK_SEND, i /* each client owns exactly 1 buffer */);
|
network_buffer(&world.player[i], sizeof(struct player_t), (i!=self_id ? NETWORK_RECV : NETWORK_SEND) | NETWORK_UNRELIABLE, i /* each client owns exactly 1 buffer */);
|
||||||
};
|
};
|
||||||
|
|
||||||
// register server->client rpc
|
// register server->client rpc
|
||||||
|
@ -56,6 +56,8 @@ int main() {
|
||||||
window_create( 0.35f, WINDOW_MSAA8|WINDOW_SQUARE );
|
window_create( 0.35f, WINDOW_MSAA8|WINDOW_SQUARE );
|
||||||
struct player_t *self = &world.player[self_id];
|
struct player_t *self = &world.player[self_id];
|
||||||
|
|
||||||
|
network_put(NETWORK_SEND_MS, 33); // 0.033 s
|
||||||
|
|
||||||
// game loop
|
// game loop
|
||||||
while( window_swap() && !input(KEY_ESC) ) {
|
while( window_swap() && !input(KEY_ESC) ) {
|
||||||
// network sync
|
// network sync
|
||||||
|
|
|
@ -15921,17 +15921,18 @@ enum { MAX_CLIENTS = 32 };
|
||||||
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
||||||
|
|
||||||
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
||||||
//enum { NETWORK_UNRELIABLE, NETWORK_UNORDERED, NETWORK_PRIORITY }; // how
|
|
||||||
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
||||||
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
||||||
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
||||||
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
||||||
API void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank); // configures a shared/networked buffer
|
enum { NETWORK_UNRELIABLE = 8, NETWORK_UNORDERED = 16/*, NETWORK_PRIORITY = 32*/ };
|
||||||
|
API void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank); // configures a shared/networked buffer
|
||||||
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
||||||
|
|
||||||
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
||||||
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
||||||
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
||||||
|
enum { NETWORK_SEND_MS = 4 };
|
||||||
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
||||||
API int64_t network_get(uint64_t key);
|
API int64_t network_get(uint64_t key);
|
||||||
API int64_t network_put(uint64_t key, int64_t value);
|
API int64_t network_put(uint64_t key, int64_t value);
|
||||||
|
@ -15945,7 +15946,9 @@ API void network_rpc_send(unsigned id, const char *cmdline);
|
||||||
|
|
||||||
API bool server_bind(int max_clients, int port);
|
API bool server_bind(int max_clients, int port);
|
||||||
API void server_poll();
|
API void server_poll();
|
||||||
|
API void server_broadcast_bin_flags(const void *ptr, int len, uint64_t flags);
|
||||||
API void server_broadcast_bin(const void *ptr, int len);
|
API void server_broadcast_bin(const void *ptr, int len);
|
||||||
|
API void server_broadcast_flags(const char *msg, uint64_t flags);
|
||||||
API void server_broadcast(const char *msg);
|
API void server_broadcast(const char *msg);
|
||||||
API void server_terminate();
|
API void server_terminate();
|
||||||
API void server_send(int64_t handle, const char *msg);
|
API void server_send(int64_t handle, const char *msg);
|
||||||
|
@ -15953,7 +15956,9 @@ API void server_send_bin(int64_t handle, const void *ptr, int len);
|
||||||
API void server_drop(int64_t handle);
|
API void server_drop(int64_t handle);
|
||||||
|
|
||||||
API int64_t client_join(const char *ip, int port);
|
API int64_t client_join(const char *ip, int port);
|
||||||
|
#define client_send_flags(msg,flags) server_broadcast(msg, flags)
|
||||||
#define client_send(msg) server_broadcast(msg)
|
#define client_send(msg) server_broadcast(msg)
|
||||||
|
#define client_send_bin_flags(ptr,len,flags) server_broadcast_bin(ptr, len, flags)
|
||||||
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
||||||
#define client_terminate() server_terminate()
|
#define client_terminate() server_terminate()
|
||||||
|
|
||||||
|
@ -338447,10 +338452,12 @@ typedef struct rpc_call {
|
||||||
uint64_t function_hash;
|
uint64_t function_hash;
|
||||||
} rpc_call;
|
} rpc_call;
|
||||||
|
|
||||||
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a) // printf("%llx\n, HASH_STR("int(int,int,int)"));
|
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a)
|
||||||
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5) // printf("%llx\n, HASH_STR("int(int,int)"));
|
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5)
|
||||||
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12) // printf("%llx\n, HASH_STR("char*(char*)"));
|
#define RPC_SIGNATURE_i_s UINT64_C(0xf7b73162829ed667)
|
||||||
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80) // printf("%llx\n, HASH_STR("char*(void)"));
|
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12)
|
||||||
|
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80)
|
||||||
|
#define RPC_SIGNATURE_v_s UINT64_C(0xc1746990ab73ed24)
|
||||||
|
|
||||||
static
|
static
|
||||||
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
||||||
|
@ -338497,10 +338504,12 @@ char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[])
|
||||||
rpc_call *found = map_find(rpc_calls, (char*)method);
|
rpc_call *found = map_find(rpc_calls, (char*)method);
|
||||||
if( found ) {
|
if( found ) {
|
||||||
switch(found->function_hash) {
|
switch(found->function_hash) {
|
||||||
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
||||||
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
||||||
|
case RPC_SIGNATURE_i_s: return va("%d %d", id, (int)(intptr_t)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
||||||
|
case RPC_SIGNATURE_v_s: return va("%d", id), found->function(args[0]);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338718,11 +338727,19 @@ void client_poll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void server_broadcast_bin_flags(const void *msg, int len, uint64_t flags) {
|
||||||
|
ENetPacket *packet = enet_packet_create(msg, len, flags&NETWORK_UNRELIABLE ? ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT : ENET_PACKET_FLAG_RELIABLE | flags&(NETWORK_UNRELIABLE|NETWORK_UNORDERED) ? ENET_PACKET_FLAG_UNSEQUENCED : 0);
|
||||||
|
enet_host_broadcast(Server, 0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
void server_broadcast_bin(const void *msg, int len) {
|
void server_broadcast_bin(const void *msg, int len) {
|
||||||
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Server, 0, packet);
|
enet_host_broadcast(Server, 0, packet);
|
||||||
//enet_host_flush(Server); // flush if needed
|
//enet_host_flush(Server); // flush if needed
|
||||||
}
|
}
|
||||||
|
void server_broadcast_flags(const char *msg, uint64_t flags) {
|
||||||
|
server_broadcast_bin_flags(msg, strlen(msg)+1, flags);
|
||||||
|
}
|
||||||
void server_broadcast(const char *msg) {
|
void server_broadcast(const char *msg) {
|
||||||
server_broadcast_bin(msg, strlen(msg)+1);
|
server_broadcast_bin(msg, strlen(msg)+1);
|
||||||
}
|
}
|
||||||
|
@ -338820,12 +338837,15 @@ typedef struct netbuffer_t {
|
||||||
int64_t owner;
|
int64_t owner;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
unsigned flags;
|
uint64_t flags;
|
||||||
} netbuffer_t;
|
} netbuffer_t;
|
||||||
|
|
||||||
static array(char*) events; // @todo: make event 128 bytes max?
|
static array(char*) events; // @todo: make event 128 bytes max?
|
||||||
static array(int64_t) values; // @todo: map<key,values> instead?
|
static array(int64_t) values; // @todo: map<key,values> instead?
|
||||||
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
||||||
|
static double msg_send_cooldown = 0.0;
|
||||||
|
static double network_dt = 0.0;
|
||||||
|
static double last_netsync = 0.0;
|
||||||
|
|
||||||
void network_create(const char *ip, const char *port_, unsigned flags) {
|
void network_create(const char *ip, const char *port_, unsigned flags) {
|
||||||
if (buffers) map_clear(buffers);
|
if (buffers) map_clear(buffers);
|
||||||
|
@ -338895,7 +338915,7 @@ int64_t network_get(uint64_t key) {
|
||||||
return found ? *found : 0;
|
return found ? *found : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank) {
|
void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank) {
|
||||||
assert(flags);
|
assert(flags);
|
||||||
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
||||||
|
|
||||||
|
@ -338916,26 +338936,33 @@ char** network_sync(unsigned timeout_ms) {
|
||||||
bool is_server = whoami == 0;
|
bool is_server = whoami == 0;
|
||||||
bool is_client = !is_server;
|
bool is_client = !is_server;
|
||||||
if(timeout_ms < 2) timeout_ms = 2;
|
if(timeout_ms < 2) timeout_ms = 2;
|
||||||
// sleep_ms(timeout_ms); // @fixme. server only?
|
|
||||||
|
network_dt = time_ss() - last_netsync;
|
||||||
|
last_netsync = time_ss();
|
||||||
|
|
||||||
// Split buffers into clients @todo
|
// Split buffers into clients @todo
|
||||||
// clients need to do this before network polling; servers should do this after polling.
|
// clients need to do this before network polling; servers should do this after polling.
|
||||||
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
if (msg_send_cooldown <= 0.0) {
|
||||||
for(int i = 0, end = array_count(list); i < end; ++i) {
|
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
||||||
netbuffer_t *nb = &list[i];
|
for(int i = 0, end = array_count(list); i < end; ++i) {
|
||||||
if (!is_server && !(nb->flags & NETWORK_SEND))
|
netbuffer_t *nb = &list[i];
|
||||||
continue;
|
if (!is_server && !(nb->flags & NETWORK_SEND))
|
||||||
static array(char) encapsulate;
|
continue;
|
||||||
array_resize(encapsulate, nb->sz + 28);
|
static array(char) encapsulate;
|
||||||
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
array_resize(encapsulate, nb->sz + 28);
|
||||||
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
||||||
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
||||||
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
||||||
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
||||||
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
||||||
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
||||||
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
||||||
|
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
msg_send_cooldown = (double)network_get(NETWORK_SEND_MS)/1000.0;
|
||||||
|
} else {
|
||||||
|
msg_send_cooldown -= network_dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// network poll
|
// network poll
|
||||||
|
|
|
@ -6,10 +6,12 @@ typedef struct rpc_call {
|
||||||
uint64_t function_hash;
|
uint64_t function_hash;
|
||||||
} rpc_call;
|
} rpc_call;
|
||||||
|
|
||||||
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a) // printf("%llx\n, HASH_STR("int(int,int,int)"));
|
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a)
|
||||||
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5) // printf("%llx\n, HASH_STR("int(int,int)"));
|
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5)
|
||||||
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12) // printf("%llx\n, HASH_STR("char*(char*)"));
|
#define RPC_SIGNATURE_i_s UINT64_C(0xf7b73162829ed667)
|
||||||
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80) // printf("%llx\n, HASH_STR("char*(void)"));
|
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12)
|
||||||
|
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80)
|
||||||
|
#define RPC_SIGNATURE_v_s UINT64_C(0xc1746990ab73ed24)
|
||||||
|
|
||||||
static
|
static
|
||||||
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
||||||
|
@ -56,10 +58,12 @@ char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[])
|
||||||
rpc_call *found = map_find(rpc_calls, (char*)method);
|
rpc_call *found = map_find(rpc_calls, (char*)method);
|
||||||
if( found ) {
|
if( found ) {
|
||||||
switch(found->function_hash) {
|
switch(found->function_hash) {
|
||||||
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
||||||
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
||||||
|
case RPC_SIGNATURE_i_s: return va("%d %d", id, (int)(intptr_t)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
||||||
|
case RPC_SIGNATURE_v_s: return va("%d", id), found->function(args[0]);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,11 +281,19 @@ void client_poll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void server_broadcast_bin_flags(const void *msg, int len, uint64_t flags) {
|
||||||
|
ENetPacket *packet = enet_packet_create(msg, len, flags&NETWORK_UNRELIABLE ? ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT : ENET_PACKET_FLAG_RELIABLE | flags&(NETWORK_UNRELIABLE|NETWORK_UNORDERED) ? ENET_PACKET_FLAG_UNSEQUENCED : 0);
|
||||||
|
enet_host_broadcast(Server, 0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
void server_broadcast_bin(const void *msg, int len) {
|
void server_broadcast_bin(const void *msg, int len) {
|
||||||
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Server, 0, packet);
|
enet_host_broadcast(Server, 0, packet);
|
||||||
//enet_host_flush(Server); // flush if needed
|
//enet_host_flush(Server); // flush if needed
|
||||||
}
|
}
|
||||||
|
void server_broadcast_flags(const char *msg, uint64_t flags) {
|
||||||
|
server_broadcast_bin_flags(msg, strlen(msg)+1, flags);
|
||||||
|
}
|
||||||
void server_broadcast(const char *msg) {
|
void server_broadcast(const char *msg) {
|
||||||
server_broadcast_bin(msg, strlen(msg)+1);
|
server_broadcast_bin(msg, strlen(msg)+1);
|
||||||
}
|
}
|
||||||
|
@ -379,12 +391,15 @@ typedef struct netbuffer_t {
|
||||||
int64_t owner;
|
int64_t owner;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
unsigned flags;
|
uint64_t flags;
|
||||||
} netbuffer_t;
|
} netbuffer_t;
|
||||||
|
|
||||||
static array(char*) events; // @todo: make event 128 bytes max?
|
static array(char*) events; // @todo: make event 128 bytes max?
|
||||||
static array(int64_t) values; // @todo: map<key,values> instead?
|
static array(int64_t) values; // @todo: map<key,values> instead?
|
||||||
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
||||||
|
static double msg_send_cooldown = 0.0;
|
||||||
|
static double network_dt = 0.0;
|
||||||
|
static double last_netsync = 0.0;
|
||||||
|
|
||||||
void network_create(const char *ip, const char *port_, unsigned flags) {
|
void network_create(const char *ip, const char *port_, unsigned flags) {
|
||||||
if (buffers) map_clear(buffers);
|
if (buffers) map_clear(buffers);
|
||||||
|
@ -454,7 +469,7 @@ int64_t network_get(uint64_t key) {
|
||||||
return found ? *found : 0;
|
return found ? *found : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank) {
|
void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank) {
|
||||||
assert(flags);
|
assert(flags);
|
||||||
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
||||||
|
|
||||||
|
@ -475,26 +490,33 @@ char** network_sync(unsigned timeout_ms) {
|
||||||
bool is_server = whoami == 0;
|
bool is_server = whoami == 0;
|
||||||
bool is_client = !is_server;
|
bool is_client = !is_server;
|
||||||
if(timeout_ms < 2) timeout_ms = 2;
|
if(timeout_ms < 2) timeout_ms = 2;
|
||||||
// sleep_ms(timeout_ms); // @fixme. server only?
|
|
||||||
|
network_dt = time_ss() - last_netsync;
|
||||||
|
last_netsync = time_ss();
|
||||||
|
|
||||||
// Split buffers into clients @todo
|
// Split buffers into clients @todo
|
||||||
// clients need to do this before network polling; servers should do this after polling.
|
// clients need to do this before network polling; servers should do this after polling.
|
||||||
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
if (msg_send_cooldown <= 0.0) {
|
||||||
for(int i = 0, end = array_count(list); i < end; ++i) {
|
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
||||||
netbuffer_t *nb = &list[i];
|
for(int i = 0, end = array_count(list); i < end; ++i) {
|
||||||
if (!is_server && !(nb->flags & NETWORK_SEND))
|
netbuffer_t *nb = &list[i];
|
||||||
continue;
|
if (!is_server && !(nb->flags & NETWORK_SEND))
|
||||||
static array(char) encapsulate;
|
continue;
|
||||||
array_resize(encapsulate, nb->sz + 28);
|
static array(char) encapsulate;
|
||||||
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
array_resize(encapsulate, nb->sz + 28);
|
||||||
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
||||||
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
||||||
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
||||||
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
||||||
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
||||||
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
||||||
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
||||||
|
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
msg_send_cooldown = (double)network_get(NETWORK_SEND_MS)/1000.0;
|
||||||
|
} else {
|
||||||
|
msg_send_cooldown -= network_dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// network poll
|
// network poll
|
||||||
|
|
|
@ -18,17 +18,18 @@ enum { MAX_CLIENTS = 32 };
|
||||||
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
||||||
|
|
||||||
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
||||||
//enum { NETWORK_UNRELIABLE, NETWORK_UNORDERED, NETWORK_PRIORITY }; // how
|
|
||||||
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
||||||
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
||||||
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
||||||
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
||||||
API void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank); // configures a shared/networked buffer
|
enum { NETWORK_UNRELIABLE = 8, NETWORK_UNORDERED = 16/*, NETWORK_PRIORITY = 32*/ };
|
||||||
|
API void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank); // configures a shared/networked buffer
|
||||||
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
||||||
|
|
||||||
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
||||||
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
||||||
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
||||||
|
enum { NETWORK_SEND_MS = 4 };
|
||||||
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
||||||
API int64_t network_get(uint64_t key);
|
API int64_t network_get(uint64_t key);
|
||||||
API int64_t network_put(uint64_t key, int64_t value);
|
API int64_t network_put(uint64_t key, int64_t value);
|
||||||
|
@ -42,7 +43,9 @@ API void network_rpc_send(unsigned id, const char *cmdline);
|
||||||
|
|
||||||
API bool server_bind(int max_clients, int port);
|
API bool server_bind(int max_clients, int port);
|
||||||
API void server_poll();
|
API void server_poll();
|
||||||
|
API void server_broadcast_bin_flags(const void *ptr, int len, uint64_t flags);
|
||||||
API void server_broadcast_bin(const void *ptr, int len);
|
API void server_broadcast_bin(const void *ptr, int len);
|
||||||
|
API void server_broadcast_flags(const char *msg, uint64_t flags);
|
||||||
API void server_broadcast(const char *msg);
|
API void server_broadcast(const char *msg);
|
||||||
API void server_terminate();
|
API void server_terminate();
|
||||||
API void server_send(int64_t handle, const char *msg);
|
API void server_send(int64_t handle, const char *msg);
|
||||||
|
@ -50,7 +53,9 @@ API void server_send_bin(int64_t handle, const void *ptr, int len);
|
||||||
API void server_drop(int64_t handle);
|
API void server_drop(int64_t handle);
|
||||||
|
|
||||||
API int64_t client_join(const char *ip, int port);
|
API int64_t client_join(const char *ip, int port);
|
||||||
|
#define client_send_flags(msg,flags) server_broadcast(msg, flags)
|
||||||
#define client_send(msg) server_broadcast(msg)
|
#define client_send(msg) server_broadcast(msg)
|
||||||
|
#define client_send_bin_flags(ptr,len,flags) server_broadcast_bin(ptr, len, flags)
|
||||||
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
||||||
#define client_terminate() server_terminate()
|
#define client_terminate() server_terminate()
|
||||||
|
|
||||||
|
|
70
engine/v4k.c
70
engine/v4k.c
|
@ -9483,10 +9483,12 @@ typedef struct rpc_call {
|
||||||
uint64_t function_hash;
|
uint64_t function_hash;
|
||||||
} rpc_call;
|
} rpc_call;
|
||||||
|
|
||||||
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a) // printf("%llx\n, HASH_STR("int(int,int,int)"));
|
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a)
|
||||||
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5) // printf("%llx\n, HASH_STR("int(int,int)"));
|
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5)
|
||||||
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12) // printf("%llx\n, HASH_STR("char*(char*)"));
|
#define RPC_SIGNATURE_i_s UINT64_C(0xf7b73162829ed667)
|
||||||
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80) // printf("%llx\n, HASH_STR("char*(void)"));
|
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12)
|
||||||
|
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80)
|
||||||
|
#define RPC_SIGNATURE_v_s UINT64_C(0xc1746990ab73ed24)
|
||||||
|
|
||||||
static
|
static
|
||||||
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
||||||
|
@ -9533,10 +9535,12 @@ char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[])
|
||||||
rpc_call *found = map_find(rpc_calls, (char*)method);
|
rpc_call *found = map_find(rpc_calls, (char*)method);
|
||||||
if( found ) {
|
if( found ) {
|
||||||
switch(found->function_hash) {
|
switch(found->function_hash) {
|
||||||
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
||||||
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(intptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
||||||
|
case RPC_SIGNATURE_i_s: return va("%d %d", id, (int)(intptr_t)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
||||||
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
||||||
|
case RPC_SIGNATURE_v_s: return va("%d", id), found->function(args[0]);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9754,11 +9758,19 @@ void client_poll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void server_broadcast_bin_flags(const void *msg, int len, uint64_t flags) {
|
||||||
|
ENetPacket *packet = enet_packet_create(msg, len, flags&NETWORK_UNRELIABLE ? ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT : ENET_PACKET_FLAG_RELIABLE | flags&(NETWORK_UNRELIABLE|NETWORK_UNORDERED) ? ENET_PACKET_FLAG_UNSEQUENCED : 0);
|
||||||
|
enet_host_broadcast(Server, 0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
void server_broadcast_bin(const void *msg, int len) {
|
void server_broadcast_bin(const void *msg, int len) {
|
||||||
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Server, 0, packet);
|
enet_host_broadcast(Server, 0, packet);
|
||||||
//enet_host_flush(Server); // flush if needed
|
//enet_host_flush(Server); // flush if needed
|
||||||
}
|
}
|
||||||
|
void server_broadcast_flags(const char *msg, uint64_t flags) {
|
||||||
|
server_broadcast_bin_flags(msg, strlen(msg)+1, flags);
|
||||||
|
}
|
||||||
void server_broadcast(const char *msg) {
|
void server_broadcast(const char *msg) {
|
||||||
server_broadcast_bin(msg, strlen(msg)+1);
|
server_broadcast_bin(msg, strlen(msg)+1);
|
||||||
}
|
}
|
||||||
|
@ -9856,12 +9868,15 @@ typedef struct netbuffer_t {
|
||||||
int64_t owner;
|
int64_t owner;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
unsigned flags;
|
uint64_t flags;
|
||||||
} netbuffer_t;
|
} netbuffer_t;
|
||||||
|
|
||||||
static array(char*) events; // @todo: make event 128 bytes max?
|
static array(char*) events; // @todo: make event 128 bytes max?
|
||||||
static array(int64_t) values; // @todo: map<key,values> instead?
|
static array(int64_t) values; // @todo: map<key,values> instead?
|
||||||
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
|
||||||
|
static double msg_send_cooldown = 0.0;
|
||||||
|
static double network_dt = 0.0;
|
||||||
|
static double last_netsync = 0.0;
|
||||||
|
|
||||||
void network_create(const char *ip, const char *port_, unsigned flags) {
|
void network_create(const char *ip, const char *port_, unsigned flags) {
|
||||||
if (buffers) map_clear(buffers);
|
if (buffers) map_clear(buffers);
|
||||||
|
@ -9931,7 +9946,7 @@ int64_t network_get(uint64_t key) {
|
||||||
return found ? *found : 0;
|
return found ? *found : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank) {
|
void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank) {
|
||||||
assert(flags);
|
assert(flags);
|
||||||
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
|
||||||
|
|
||||||
|
@ -9952,26 +9967,33 @@ char** network_sync(unsigned timeout_ms) {
|
||||||
bool is_server = whoami == 0;
|
bool is_server = whoami == 0;
|
||||||
bool is_client = !is_server;
|
bool is_client = !is_server;
|
||||||
if(timeout_ms < 2) timeout_ms = 2;
|
if(timeout_ms < 2) timeout_ms = 2;
|
||||||
// sleep_ms(timeout_ms); // @fixme. server only?
|
|
||||||
|
network_dt = time_ss() - last_netsync;
|
||||||
|
last_netsync = time_ss();
|
||||||
|
|
||||||
// Split buffers into clients @todo
|
// Split buffers into clients @todo
|
||||||
// clients need to do this before network polling; servers should do this after polling.
|
// clients need to do this before network polling; servers should do this after polling.
|
||||||
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
if (msg_send_cooldown <= 0.0) {
|
||||||
for(int i = 0, end = array_count(list); i < end; ++i) {
|
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
|
||||||
netbuffer_t *nb = &list[i];
|
for(int i = 0, end = array_count(list); i < end; ++i) {
|
||||||
if (!is_server && !(nb->flags & NETWORK_SEND))
|
netbuffer_t *nb = &list[i];
|
||||||
continue;
|
if (!is_server && !(nb->flags & NETWORK_SEND))
|
||||||
static array(char) encapsulate;
|
continue;
|
||||||
array_resize(encapsulate, nb->sz + 28);
|
static array(char) encapsulate;
|
||||||
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
array_resize(encapsulate, nb->sz + 28);
|
||||||
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
|
||||||
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
|
||||||
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
|
||||||
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
|
||||||
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
|
||||||
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
|
||||||
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
memcpy(&encapsulate[28], nb->ptr, nb->sz);
|
||||||
|
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
msg_send_cooldown = (double)network_get(NETWORK_SEND_MS)/1000.0;
|
||||||
|
} else {
|
||||||
|
msg_send_cooldown -= network_dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// network poll
|
// network poll
|
||||||
|
|
|
@ -2004,17 +2004,18 @@ enum { MAX_CLIENTS = 32 };
|
||||||
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
|
||||||
|
|
||||||
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
|
||||||
//enum { NETWORK_UNRELIABLE, NETWORK_UNORDERED, NETWORK_PRIORITY }; // how
|
|
||||||
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
|
||||||
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
|
||||||
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
|
||||||
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
|
||||||
API void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank); // configures a shared/networked buffer
|
enum { NETWORK_UNRELIABLE = 8, NETWORK_UNORDERED = 16/*, NETWORK_PRIORITY = 32*/ };
|
||||||
|
API void* network_buffer(void *ptr, unsigned sz, uint64_t flags, int64_t rank); // configures a shared/networked buffer
|
||||||
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
|
||||||
|
|
||||||
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
|
||||||
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
|
||||||
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
|
||||||
|
enum { NETWORK_SEND_MS = 4 };
|
||||||
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
|
||||||
API int64_t network_get(uint64_t key);
|
API int64_t network_get(uint64_t key);
|
||||||
API int64_t network_put(uint64_t key, int64_t value);
|
API int64_t network_put(uint64_t key, int64_t value);
|
||||||
|
@ -2028,7 +2029,9 @@ API void network_rpc_send(unsigned id, const char *cmdline);
|
||||||
|
|
||||||
API bool server_bind(int max_clients, int port);
|
API bool server_bind(int max_clients, int port);
|
||||||
API void server_poll();
|
API void server_poll();
|
||||||
|
API void server_broadcast_bin_flags(const void *ptr, int len, uint64_t flags);
|
||||||
API void server_broadcast_bin(const void *ptr, int len);
|
API void server_broadcast_bin(const void *ptr, int len);
|
||||||
|
API void server_broadcast_flags(const char *msg, uint64_t flags);
|
||||||
API void server_broadcast(const char *msg);
|
API void server_broadcast(const char *msg);
|
||||||
API void server_terminate();
|
API void server_terminate();
|
||||||
API void server_send(int64_t handle, const char *msg);
|
API void server_send(int64_t handle, const char *msg);
|
||||||
|
@ -2036,7 +2039,9 @@ API void server_send_bin(int64_t handle, const void *ptr, int len);
|
||||||
API void server_drop(int64_t handle);
|
API void server_drop(int64_t handle);
|
||||||
|
|
||||||
API int64_t client_join(const char *ip, int port);
|
API int64_t client_join(const char *ip, int port);
|
||||||
|
#define client_send_flags(msg,flags) server_broadcast(msg, flags)
|
||||||
#define client_send(msg) server_broadcast(msg)
|
#define client_send(msg) server_broadcast(msg)
|
||||||
|
#define client_send_bin_flags(ptr,len,flags) server_broadcast_bin(ptr, len, flags)
|
||||||
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
|
||||||
#define client_terminate() server_terminate()
|
#define client_terminate() server_terminate()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue