prediction progress
This commit is contained in:
parent
cb05b707f0
commit
4172808fe2
@ -16,6 +16,10 @@
|
|||||||
*
|
*
|
||||||
* Rolling window for message reassembly.
|
* Rolling window for message reassembly.
|
||||||
* This would remove the need for random access message buffers.
|
* This would remove the need for random access message buffers.
|
||||||
|
*
|
||||||
|
* Connection timeouts.
|
||||||
|
*
|
||||||
|
* Challenges to verify receiving address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PACKET_MAGIC 0xd9e3b8b6
|
#define PACKET_MAGIC 0xd9e3b8b6
|
||||||
|
|||||||
75
src/sim.c
75
src/sim.c
@ -519,27 +519,30 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
|
|||||||
struct sim_cmd_frame **client_frames;
|
struct sim_cmd_frame **client_frames;
|
||||||
{
|
{
|
||||||
/* Create connecting clients */
|
/* Create connecting clients */
|
||||||
|
if (world->is_master) {
|
||||||
|
/* Create local client if it doesn't exist */
|
||||||
|
struct sim_client *local_client = sim_client_from_handle(world, world->local_client);
|
||||||
|
if (!local_client->valid) {
|
||||||
|
local_client = sim_client_alloc(world, HOST_CHANNEL_ID_NIL, SIM_CLIENT_KIND_SIM_MASTER);
|
||||||
|
world->local_client = local_client->handle;
|
||||||
|
}
|
||||||
|
/* Create slave sim clients */
|
||||||
for (struct sim_cmd_frame *frame = input_frames.first; frame; frame = frame->next) {
|
for (struct sim_cmd_frame *frame = input_frames.first; frame; frame = frame->next) {
|
||||||
struct sim_client *client;
|
struct sim_client *client;
|
||||||
if (frame->sender_is_local) {
|
if (!frame->sender_is_local) {
|
||||||
client = sim_client_from_handle(world, world->local_client);
|
|
||||||
if (!client->valid) {
|
|
||||||
client = sim_client_alloc(world, HOST_CHANNEL_ID_NIL, SIM_CLIENT_KIND_LOCAL);
|
|
||||||
world->local_client = client->handle;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
client = sim_client_from_channel_id(world, frame->sender_channel);
|
client = sim_client_from_channel_id(world, frame->sender_channel);
|
||||||
if (!client->valid) {
|
if (!client->valid) {
|
||||||
for (struct sim_cmd *cmd = frame->first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = frame->first; cmd; cmd = cmd->next) {
|
||||||
enum sim_cmd_kind kind = cmd->kind;
|
enum sim_cmd_kind kind = cmd->kind;
|
||||||
if (kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(frame->sender_channel)) {
|
if (kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(frame->sender_channel)) {
|
||||||
client = sim_client_alloc(world, frame->sender_channel, SIM_CLIENT_KIND_NETSIM);
|
client = sim_client_alloc(world, frame->sender_channel, SIM_CLIENT_KIND_SIM_SLAVE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Sort cmd frames by client */
|
/* Sort cmd frames by client */
|
||||||
client_frames = arena_push_array_zero(scratch.arena, struct sim_cmd_frame *, world->num_clients_reserved);
|
client_frames = arena_push_array_zero(scratch.arena, struct sim_cmd_frame *, world->num_clients_reserved);
|
||||||
for (struct sim_cmd_frame *frame = input_frames.first; frame; frame = frame->next) {
|
for (struct sim_cmd_frame *frame = input_frames.first; frame; frame = frame->next) {
|
||||||
@ -549,12 +552,13 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
|
|||||||
} else {
|
} else {
|
||||||
client = sim_client_from_channel_id(world, frame->sender_channel);
|
client = sim_client_from_channel_id(world, frame->sender_channel);
|
||||||
}
|
}
|
||||||
if (client->valid && frame->tick == world->tick) {
|
if (client->valid) {
|
||||||
client_frames[client->handle.idx] = frame;
|
client_frames[client->handle.idx] = frame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (world->is_master) {
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process client sim cmds
|
* Process client sim cmds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -1369,57 +1373,8 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
release_entities_with_prop(world, SIM_ENT_PROP_RELEASE_THIS_TICK);
|
release_entities_with_prop(world, SIM_ENT_PROP_RELEASE_THIS_TICK);
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Publish tick
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct sim_cmd_queue_list output_cmds = ZI;
|
|
||||||
for (u64 i = 0; i < ss_blended->num_clients_reserved; ++i) {
|
|
||||||
struct sim_client *client = &ss_blended->clients[i];
|
|
||||||
if (client->valid) {
|
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
|
||||||
|
|
||||||
struct sim_snapshot *ss0 = sim_snapshot_from_tick(snapshot_store, client->ack);
|
|
||||||
struct sim_snapshot *ss1 = ss_blended;
|
|
||||||
|
|
||||||
/* Create & encode snapshot cmd */
|
|
||||||
{
|
|
||||||
struct sim_cmd *cmd = arena_push(arena, struct sim_cmd);
|
|
||||||
cmd->kind = SIM_CMD_KIND_SNAPSHOT;
|
|
||||||
cmd->tick = ss_blended->tick;
|
|
||||||
cmd->snapshot_tick_start = ss0->tick;
|
|
||||||
cmd->snapshot_tick_end = ss1->tick;
|
|
||||||
|
|
||||||
{
|
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(encoder_bitbuff);
|
|
||||||
sim_snapshot_encode(&bw, ss0, ss1, client);
|
|
||||||
cmd->snapshot_encoded = bw_get_written(temp.arena, &bw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_cmds.last) {
|
|
||||||
output_cmds.last->next = cmd;
|
|
||||||
} else {
|
|
||||||
output_cmds.first = cmd;
|
|
||||||
}
|
|
||||||
output_cmds.last = cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Encode cmds */
|
|
||||||
struct string cmds_msg = ZI;
|
|
||||||
{
|
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(encoder_bitbuff);
|
|
||||||
sim_cmds_encode(&bw, output_cmds, 0);
|
|
||||||
cmds_msg = bw_get_written(temp.arena, &bw);
|
|
||||||
}
|
|
||||||
|
|
||||||
host_queue_write(host, client->channel_id, cmds_msg, 0);
|
|
||||||
|
|
||||||
arena_temp_end(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* End frame
|
* End frame
|
||||||
@ -1451,12 +1406,12 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
|
|||||||
* Cmd frame
|
* Cmd frame
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_cmd_frames_encode(struct bitbuff_writer *bw, struct sim_cmd_frame_list frames, u64 ack_tick)
|
void sim_cmd_frames_encode(struct bitbuff_writer *bw, struct sim_cmd_frame_list frames)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
for (struct sim_cmd_frame *frame = frames.first; frame; frame = frame->next) {
|
for (struct sim_cmd_frame *frame = frames.first; frame; frame = frame->next) {
|
||||||
bw_write_uv(bw, frame->tick);
|
bw_write_uv(bw, frame->tick);
|
||||||
bw_write_uv(bw, ack_tick);
|
bw_write_uv(bw, frame->ack);
|
||||||
|
|
||||||
for (struct sim_cmd *cmd = frame->first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = frame->first; cmd; cmd = cmd->next) {
|
||||||
bw_write_bit(bw, 1);
|
bw_write_bit(bw, 1);
|
||||||
|
|||||||
@ -131,7 +131,7 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
|
|||||||
|
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
||||||
void sim_cmd_frames_encode(struct bitbuff_writer *bw, struct sim_cmd_frame_list frames, u64 ack_tick);
|
void sim_cmd_frames_encode(struct bitbuff_writer *bw, struct sim_cmd_frame_list frames);
|
||||||
void sim_cmd_frames_decode(struct arena *arena, struct host_event_array host_events, struct sim_cmd_frame_list *frames_out);
|
void sim_cmd_frames_decode(struct arena *arena, struct host_event_array host_events, struct sim_cmd_frame_list *frames_out);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -57,30 +57,13 @@ struct sim_client *sim_client_alloc(struct sim_snapshot *ss, struct host_channel
|
|||||||
}
|
}
|
||||||
++ss->num_clients_allocated;
|
++ss->num_clients_allocated;
|
||||||
*client = *sim_client_nil();
|
*client = *sim_client_nil();
|
||||||
|
client->ss = ss;
|
||||||
client->valid = true;
|
client->valid = true;
|
||||||
client->kind = kind;
|
client->kind = kind;
|
||||||
client->handle = handle;
|
client->handle = handle;
|
||||||
|
|
||||||
if (kind == SIM_CLIENT_KIND_NETSIM) {
|
|
||||||
ASSERT(!host_channel_id_is_nil(channel_id));
|
|
||||||
u64 channel_hash = hash_from_channel_id(channel_id);
|
|
||||||
client->channel_id = channel_id;
|
|
||||||
client->channel_hash = channel_hash;
|
|
||||||
|
|
||||||
/* Insert into channel lookup */
|
/* Insert into channel lookup */
|
||||||
u64 bucket_index = channel_hash % ss->num_client_lookup_buckets;
|
sim_client_set_channel_id(client, channel_id);
|
||||||
struct sim_client_lookup_bucket *bucket = &ss->client_lookup_buckets[bucket_index];
|
|
||||||
{
|
|
||||||
struct sim_client *prev_in_bucket = sim_client_from_handle(ss, bucket->last);
|
|
||||||
if (prev_in_bucket->valid) {
|
|
||||||
prev_in_bucket->next_in_bucket = client->handle;
|
|
||||||
client->prev_in_bucket = prev_in_bucket->handle;
|
|
||||||
} else {
|
|
||||||
bucket->first = client->handle;
|
|
||||||
}
|
|
||||||
bucket->last = client->handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
@ -95,7 +78,16 @@ void sim_client_release(struct sim_client *client)
|
|||||||
--ss->num_clients_allocated;
|
--ss->num_clients_allocated;
|
||||||
|
|
||||||
/* Remove from channel lookup */
|
/* Remove from channel lookup */
|
||||||
if (client->kind == SIM_CLIENT_KIND_NETSIM) {
|
sim_client_set_channel_id(client, HOST_CHANNEL_ID_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id channel_id)
|
||||||
|
{
|
||||||
|
struct sim_snapshot *ss = client->ss;
|
||||||
|
struct host_channel_id old_channel_id = client->channel_id;
|
||||||
|
|
||||||
|
/* Remove from channel lookup */
|
||||||
|
if (!host_channel_id_is_nil(old_channel_id)) {
|
||||||
u64 bucket_index = client->channel_hash % ss->num_client_lookup_buckets;
|
u64 bucket_index = client->channel_hash % ss->num_client_lookup_buckets;
|
||||||
struct sim_client_lookup_bucket *bucket = &ss->client_lookup_buckets[bucket_index];
|
struct sim_client_lookup_bucket *bucket = &ss->client_lookup_buckets[bucket_index];
|
||||||
struct sim_client *prev = sim_client_from_handle(ss, client->prev_in_bucket);
|
struct sim_client *prev = sim_client_from_handle(ss, client->prev_in_bucket);
|
||||||
@ -111,6 +103,25 @@ void sim_client_release(struct sim_client *client)
|
|||||||
bucket->last = prev->handle;
|
bucket->last = prev->handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Insert into channel lookup */
|
||||||
|
u64 channel_hash = hash_from_channel_id(channel_id);
|
||||||
|
client->channel_id = channel_id;
|
||||||
|
client->channel_hash = channel_hash;
|
||||||
|
if (!host_channel_id_is_nil(channel_id)) {
|
||||||
|
u64 bucket_index = channel_hash % ss->num_client_lookup_buckets;
|
||||||
|
struct sim_client_lookup_bucket *bucket = &ss->client_lookup_buckets[bucket_index];
|
||||||
|
{
|
||||||
|
struct sim_client *prev_in_bucket = sim_client_from_handle(ss, bucket->last);
|
||||||
|
if (prev_in_bucket->valid) {
|
||||||
|
prev_in_bucket->next_in_bucket = client->handle;
|
||||||
|
client->prev_in_bucket = prev_in_bucket->handle;
|
||||||
|
} else {
|
||||||
|
bucket->first = client->handle;
|
||||||
|
}
|
||||||
|
bucket->last = client->handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
@ -10,8 +10,8 @@ struct sim_snapshot;
|
|||||||
|
|
||||||
enum sim_client_kind {
|
enum sim_client_kind {
|
||||||
SIM_CLIENT_KIND_INVALID,
|
SIM_CLIENT_KIND_INVALID,
|
||||||
SIM_CLIENT_KIND_LOCAL,
|
SIM_CLIENT_KIND_SIM_SLAVE,
|
||||||
SIM_CLIENT_KIND_NETSIM
|
SIM_CLIENT_KIND_SIM_MASTER
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sim_client_lookup_bucket {
|
struct sim_client_lookup_bucket {
|
||||||
@ -60,6 +60,7 @@ struct sim_client *sim_client_from_handle(struct sim_snapshot *ss, struct sim_cl
|
|||||||
struct sim_client *sim_client_from_channel_id(struct sim_snapshot *ss, struct host_channel_id channel_id);
|
struct sim_client *sim_client_from_channel_id(struct sim_snapshot *ss, struct host_channel_id channel_id);
|
||||||
struct sim_client *sim_client_alloc(struct sim_snapshot *ss, struct host_channel_id channel_id, enum sim_client_kind kind);
|
struct sim_client *sim_client_alloc(struct sim_snapshot *ss, struct host_channel_id channel_id, enum sim_client_kind kind);
|
||||||
void sim_client_release(struct sim_client *client);
|
void sim_client_release(struct sim_client *client);
|
||||||
|
void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id channel_id);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Lerp
|
* Lerp
|
||||||
|
|||||||
@ -194,6 +194,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct
|
|||||||
++store->num_ticks;
|
++store->num_ticks;
|
||||||
|
|
||||||
/* Copy src info */
|
/* Copy src info */
|
||||||
|
ss->is_master = src->is_master;
|
||||||
ss->real_dt_ns = src->real_dt_ns;
|
ss->real_dt_ns = src->real_dt_ns;
|
||||||
ss->real_time_ns = src->real_time_ns;
|
ss->real_time_ns = src->real_time_ns;
|
||||||
ss->world_timescale = src->world_timescale;
|
ss->world_timescale = src->world_timescale;
|
||||||
@ -272,6 +273,8 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct
|
|||||||
} else {
|
} else {
|
||||||
store->last_tick = tick;
|
store->last_tick = tick;
|
||||||
}
|
}
|
||||||
|
ss->next_tick = prev->next_tick;
|
||||||
|
ss->prev_tick = prev->tick;
|
||||||
prev->next_tick = ss->tick;
|
prev->next_tick = ss->tick;
|
||||||
} else {
|
} else {
|
||||||
struct sim_snapshot *first = sim_snapshot_from_tick(store, store->first_tick);
|
struct sim_snapshot *first = sim_snapshot_from_tick(store, store->first_tick);
|
||||||
@ -281,6 +284,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct
|
|||||||
} else {
|
} else {
|
||||||
store->last_tick = tick;
|
store->last_tick = tick;
|
||||||
}
|
}
|
||||||
|
ss->next_tick = store->first_tick;
|
||||||
store->first_tick = tick;
|
store->first_tick = tick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,10 +439,13 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_snapshot_store *sto
|
|||||||
* Encode
|
* Encode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_snapshot *ss0, struct sim_snapshot *ss1, struct sim_client *client)
|
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
|
/* TODO: Don't encode this */
|
||||||
|
bw_write_bit(bw, ss1->is_master);
|
||||||
|
|
||||||
bw_write_iv(bw, ss1->real_dt_ns);
|
bw_write_iv(bw, ss1->real_dt_ns);
|
||||||
bw_write_iv(bw, ss1->real_time_ns);
|
bw_write_iv(bw, ss1->real_time_ns);
|
||||||
|
|
||||||
@ -449,8 +456,8 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_snapshot *ss0, st
|
|||||||
bw_write_uv(bw, ss1->continuity_gen);
|
bw_write_uv(bw, ss1->continuity_gen);
|
||||||
bw_write_uv(bw, ss1->phys_iteration);
|
bw_write_uv(bw, ss1->phys_iteration);
|
||||||
|
|
||||||
bw_write_uv(bw, client->handle.gen);
|
bw_write_uv(bw, receiver->handle.gen);
|
||||||
bw_write_uv(bw, client->handle.idx);
|
bw_write_uv(bw, receiver->handle.idx);
|
||||||
|
|
||||||
/* Clients */
|
/* Clients */
|
||||||
if (ss1->num_clients_allocated == ss0->num_clients_allocated) {
|
if (ss1->num_clients_allocated == ss0->num_clients_allocated) {
|
||||||
@ -505,6 +512,9 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
|
/* TODO: Don't encode this */
|
||||||
|
ss->is_master = br_read_bit(br);
|
||||||
|
|
||||||
ss->real_dt_ns = br_read_iv(br);
|
ss->real_dt_ns = br_read_iv(br);
|
||||||
ss->real_time_ns = br_read_iv(br);
|
ss->real_time_ns = br_read_iv(br);
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,9 @@ struct sim_snapshot {
|
|||||||
|
|
||||||
struct arena arena;
|
struct arena arena;
|
||||||
|
|
||||||
|
/* Is this snapshot created by the master sim */
|
||||||
|
b32 is_master;
|
||||||
|
|
||||||
/* Time of local snapshot publish to user */
|
/* Time of local snapshot publish to user */
|
||||||
i64 publish_dt_ns;
|
i64 publish_dt_ns;
|
||||||
i64 publish_time_ns;
|
i64 publish_time_ns;
|
||||||
@ -132,7 +135,7 @@ struct sim_snapshot *sim_snapshot_from_tick(struct sim_snapshot_store *store, u6
|
|||||||
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_snapshot_store *store, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_snapshot_store *store, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
||||||
|
|
||||||
/* Encode / decode */
|
/* Encode / decode */
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_snapshot *ss0, struct sim_snapshot *ss1, struct sim_client *client);
|
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
||||||
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss);
|
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
195
src/user.c
195
src/user.c
@ -199,6 +199,9 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
|
|
||||||
G.arena = arena_alloc(GIGABYTE(64));
|
G.arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
|
/* TODO: Remove this */
|
||||||
|
G.connect_address_str = string_copy(&G.arena, connect_address_str);
|
||||||
|
|
||||||
/* Snapshot store */
|
/* Snapshot store */
|
||||||
G.unblended_snapshot_store = sim_snapshot_store_alloc();
|
G.unblended_snapshot_store = sim_snapshot_store_alloc();
|
||||||
G.blended_snapshot_store = sim_snapshot_store_alloc();
|
G.blended_snapshot_store = sim_snapshot_store_alloc();
|
||||||
@ -228,25 +231,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
G.window = window;
|
G.window = window;
|
||||||
sys_window_register_event_callback(G.window, &window_event_callback);
|
sys_window_register_event_callback(G.window, &window_event_callback);
|
||||||
|
|
||||||
/* TODO: Remove this */
|
|
||||||
#if 0
|
|
||||||
connect_address_str = STRING(0, 0);
|
|
||||||
if (connect_address_str.len == 0) {
|
|
||||||
G.local_sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, sim_snapshot_sr, 12345);
|
|
||||||
G.connect_address_str = LIT("127.0.0.1:12345");
|
|
||||||
G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P8] Local sim thread"));
|
G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P8] Local sim thread"));
|
||||||
} else {
|
|
||||||
G.connect_address_str = string_copy(&G.arena, connect_address_str);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
connect_address_str = STRING(0, 0);
|
|
||||||
if (connect_address_str.len == 0) {
|
|
||||||
G.connect_address_str = LIT("127.0.0.1:12345");
|
|
||||||
G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P8] Local sim thread"));
|
|
||||||
} else {
|
|
||||||
G.connect_address_str = string_copy(&G.arena, connect_address_str);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
G.debug_draw = true;
|
G.debug_draw = true;
|
||||||
|
|
||||||
@ -1477,10 +1462,10 @@ INTERNAL void user_update(void)
|
|||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Read from local sim: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_read.last_second * 8 / 1000 / 1000, 3)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Read from host: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_read.last_second * 8 / 1000 / 1000, 3)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Send to local sim: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_sent.last_second * 8 / 1000 / 1000, 3)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Sent from host: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_sent.last_second * 8 / 1000 / 1000, 3)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
@ -1733,10 +1718,30 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
#endif
|
#endif
|
||||||
(UNUSED)arg;
|
(UNUSED)arg;
|
||||||
|
|
||||||
struct bitbuff encoder_bitbuff = bitbuff_alloc(GIGABYTE(64));
|
b32 is_master = false;
|
||||||
struct sim_snapshot_store *snapshot_store = sim_snapshot_store_alloc();
|
if (G.connect_address_str.len > 0) {
|
||||||
|
struct sock_address addr = sock_address_from_string(G.connect_address_str);
|
||||||
|
host_queue_connect_to_address(host, addr);
|
||||||
|
} else {
|
||||||
|
is_master = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct bitbuff encoder_bitbuff = bitbuff_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
|
struct sim_snapshot_store *local_snapshot_store = sim_snapshot_store_alloc();
|
||||||
|
struct sim_snapshot_store *remote_snapshot_store = sim_snapshot_store_alloc();
|
||||||
|
u64 oldest_needed_remote_tick = 0;
|
||||||
|
u64 remote_ack = 0;
|
||||||
|
(UNUSED)remote_ack;
|
||||||
|
|
||||||
|
struct sim_snapshot *local_ss_prev = sim_snapshot_nil();
|
||||||
|
|
||||||
struct sim_snapshot *prev_ss = sim_snapshot_nil();
|
|
||||||
|
|
||||||
i64 last_publish_ns = 0;
|
i64 last_publish_ns = 0;
|
||||||
i64 last_tick_ns = 0;
|
i64 last_tick_ns = 0;
|
||||||
@ -1752,15 +1757,16 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
/* Release old snapshots */
|
/* Release old snapshots */
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
{
|
{
|
||||||
u64 keep_count = 50;
|
u64 keep_count = 100;
|
||||||
u64 keep_tick = prev_ss->tick > keep_count ? prev_ss->tick - keep_count : 0;
|
u64 keep_tick = local_ss_prev->tick > keep_count ? local_ss_prev->tick - keep_count : 0;
|
||||||
if (keep_tick > 0) {
|
if (keep_tick > 0) {
|
||||||
sim_snapshot_store_release_ticks_in_range(snapshot_store, 0, keep_tick);
|
sim_snapshot_store_release_ticks_in_range(local_snapshot_store, 0, keep_tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve cmds */
|
/* Retrieve cmds */
|
||||||
struct sim_cmd_frame_list input_cmds = ZI;
|
struct sim_cmd_frame_list input_cmds = ZI;
|
||||||
|
struct sim_cmd_frame *user_cmd_frame;
|
||||||
{
|
{
|
||||||
/* Grab cmds from host */
|
/* Grab cmds from host */
|
||||||
{
|
{
|
||||||
@ -1770,11 +1776,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generate user sim cmd from user thread */
|
/* Generate user sim cmd from user thread */
|
||||||
struct sim_cmd_frame *user_cmd_frame;
|
|
||||||
{
|
{
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.user_sim_cmd_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.user_sim_cmd_mutex);
|
||||||
user_cmd_frame = arena_push_zero(scratch.arena, struct sim_cmd_frame);
|
user_cmd_frame = arena_push_zero(scratch.arena, struct sim_cmd_frame);
|
||||||
user_cmd_frame->tick = prev_ss->tick + 1;
|
user_cmd_frame->tick = local_ss_prev->tick + 1;
|
||||||
user_cmd_frame->ack = G.user_sim_cmd_ack;
|
user_cmd_frame->ack = G.user_sim_cmd_ack;
|
||||||
user_cmd_frame->sender_is_local = true;
|
user_cmd_frame->sender_is_local = true;
|
||||||
|
|
||||||
@ -1794,14 +1799,71 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
input_cmds.last = user_cmd_frame;
|
input_cmds.last = user_cmd_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (struct sim_cmd_frame *frame = input_cmds.first; frame; frame = frame->next) {
|
||||||
|
/* FIXME: Verify cmd is from master */
|
||||||
|
if (!is_master && !frame->sender_is_local) {
|
||||||
|
struct sim_cmd *snapshot_cmd = NULL;
|
||||||
|
|
||||||
|
/* Grab newest snapshot cmd */
|
||||||
|
for (struct sim_cmd *cmd = frame->first; cmd; cmd = cmd->next) {
|
||||||
|
if (cmd->kind == SIM_CMD_KIND_SNAPSHOT && (!snapshot_cmd || cmd->snapshot_tick_end > snapshot_cmd->snapshot_tick_end)) {
|
||||||
|
snapshot_cmd = cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode newest snapshot cmd */
|
||||||
|
if (snapshot_cmd && snapshot_cmd->snapshot_tick_end > remote_snapshot_store->last_tick) {
|
||||||
|
remote_ack = frame->ack;
|
||||||
|
|
||||||
|
u64 ss0_tick = snapshot_cmd->snapshot_tick_start;
|
||||||
|
u64 ss1_tick = snapshot_cmd->snapshot_tick_end;
|
||||||
|
struct sim_snapshot *ss0 = sim_snapshot_from_tick(remote_snapshot_store, ss0_tick);
|
||||||
|
struct sim_snapshot *ss1 = sim_snapshot_from_tick(remote_snapshot_store, ss1_tick);
|
||||||
|
if (ss0->tick == ss0_tick) {
|
||||||
|
if (!ss1->valid) {
|
||||||
|
/* Decode remote snapshot */
|
||||||
|
ss1 = sim_snapshot_alloc(remote_snapshot_store, ss0, ss1_tick);
|
||||||
|
struct bitbuff bb = bitbuff_from_string(snapshot_cmd->snapshot_encoded);
|
||||||
|
struct bitbuff_reader br = br_from_bitbuff(&bb);
|
||||||
|
sim_snapshot_decode(&br, ss1);
|
||||||
|
|
||||||
|
if (ss0->tick > oldest_needed_remote_tick) {
|
||||||
|
oldest_needed_remote_tick = ss0->tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set master client channel id */
|
||||||
|
for (u64 i = 0; i < ss1->num_clients_reserved; ++i) {
|
||||||
|
struct sim_client *client = &ss1->clients[i];
|
||||||
|
if (client->valid && client->kind == SIM_CLIENT_KIND_SIM_MASTER) {
|
||||||
|
sim_client_set_channel_id(client, frame->sender_channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local_ss_prev = sim_snapshot_alloc(local_snapshot_store, ss1, ss1_tick + 20);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* User should always have src tick present */
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release old remote ticks */
|
||||||
|
if (oldest_needed_remote_tick > 0) {
|
||||||
|
sim_snapshot_store_release_ticks_in_range(remote_snapshot_store, 0, oldest_needed_remote_tick - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Step */
|
/* Step */
|
||||||
struct sim_snapshot *ss = sim_step(snapshot_store, prev_ss, input_cmds, target_dt_ns);
|
struct sim_snapshot *local_ss = sim_step(local_snapshot_store, local_ss_prev, input_cmds, target_dt_ns);
|
||||||
|
local_ss->is_master = is_master;
|
||||||
|
|
||||||
/* Publish snapshot to user */
|
/* Publish snapshot to user */
|
||||||
/* TODO: Double buffer */
|
/* TODO: Double buffer */
|
||||||
{
|
{
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.local_sim_ss_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.local_sim_ss_mutex);
|
||||||
struct sim_snapshot *pub_ss = sim_snapshot_alloc(G.local_sim_ss_store, ss, ss->tick);
|
struct sim_snapshot *pub_ss = sim_snapshot_alloc(G.local_sim_ss_store, local_ss, local_ss->tick);
|
||||||
sim_snapshot_store_release_ticks_in_range(G.local_sim_ss_store, 0, pub_ss->tick - 1);
|
sim_snapshot_store_release_ticks_in_range(G.local_sim_ss_store, 0, pub_ss->tick - 1);
|
||||||
i64 publish_ns = sys_time_ns();
|
i64 publish_ns = sys_time_ns();
|
||||||
pub_ss->publish_dt_ns = publish_ns - last_publish_ns;
|
pub_ss->publish_dt_ns = publish_ns - last_publish_ns;
|
||||||
@ -1810,19 +1872,20 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
sys_mutex_unlock(&lock);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Publish snapshot cmds to networked clients */
|
if (local_ss->is_master) {
|
||||||
|
/* Publish snapshot cmds to slave clients */
|
||||||
u64 oldest_ack_tick = 0;
|
u64 oldest_ack_tick = 0;
|
||||||
for (u64 i = 0; i < ss->num_clients_reserved; ++i) {
|
for (u64 i = 0; i < local_ss->num_clients_reserved; ++i) {
|
||||||
struct sim_client *client = &ss->clients[i];
|
struct sim_client *client = &local_ss->clients[i];
|
||||||
if (client->valid && client->kind == SIM_CLIENT_KIND_NETSIM) {
|
if (client->valid && client->kind == SIM_CLIENT_KIND_SIM_SLAVE) {
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
if (oldest_ack_tick == 0 || client->ack < oldest_ack_tick) {
|
if (oldest_ack_tick == 0 || client->ack < oldest_ack_tick) {
|
||||||
oldest_ack_tick = client->ack;
|
oldest_ack_tick = client->ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_snapshot *ss0 = sim_snapshot_from_tick(snapshot_store, client->ack);
|
struct sim_snapshot *ss0 = sim_snapshot_from_tick(local_snapshot_store, client->ack);
|
||||||
struct sim_snapshot *ss1 = ss;
|
struct sim_snapshot *ss1 = local_ss;
|
||||||
|
|
||||||
/* Create & encode snapshot cmd */
|
/* Create & encode snapshot cmd */
|
||||||
struct sim_cmd snapshot_cmd = ZI;
|
struct sim_cmd snapshot_cmd = ZI;
|
||||||
@ -1832,12 +1895,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
snapshot_cmd.snapshot_tick_end = ss1->tick;
|
snapshot_cmd.snapshot_tick_end = ss1->tick;
|
||||||
{
|
{
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&encoder_bitbuff);
|
struct bitbuff_writer bw = bw_from_bitbuff(&encoder_bitbuff);
|
||||||
sim_snapshot_encode(&bw, ss0, ss1, client);
|
sim_snapshot_encode(&bw, client, ss0, ss1);
|
||||||
snapshot_cmd.snapshot_encoded = bw_get_written(temp.arena, &bw);
|
snapshot_cmd.snapshot_encoded = bw_get_written(temp.arena, &bw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_cmd_frame snapshot_cmd_frame = ZI;
|
struct sim_cmd_frame snapshot_cmd_frame = ZI;
|
||||||
|
snapshot_cmd_frame.tick = ss1->tick;
|
||||||
|
snapshot_cmd_frame.ack = client->ack;
|
||||||
snapshot_cmd_frame.first = &snapshot_cmd;
|
snapshot_cmd_frame.first = &snapshot_cmd;
|
||||||
snapshot_cmd_frame.last = &snapshot_cmd;
|
snapshot_cmd_frame.last = &snapshot_cmd;
|
||||||
|
|
||||||
@ -1849,8 +1914,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
struct string cmds_msg = ZI;
|
struct string cmds_msg = ZI;
|
||||||
{
|
{
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&encoder_bitbuff);
|
struct bitbuff_writer bw = bw_from_bitbuff(&encoder_bitbuff);
|
||||||
/* FIXME: Ack tick */
|
sim_cmd_frames_encode(&bw, cmd_frames);
|
||||||
sim_cmd_frames_encode(&bw, cmd_frames, 0);
|
|
||||||
cmds_msg = bw_get_written(temp.arena, &bw);
|
cmds_msg = bw_get_written(temp.arena, &bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1859,17 +1923,62 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
arena_temp_end(temp);
|
arena_temp_end(temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Publish user cmd to master client */
|
||||||
|
for (u64 i = 0; i < local_ss->num_clients_reserved; ++i) {
|
||||||
|
struct sim_client *client = &local_ss->clients[i];
|
||||||
|
if (client->valid && client->kind == SIM_CLIENT_KIND_SIM_MASTER) {
|
||||||
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
|
user_cmd_frame->ack = remote_snapshot_store->last_tick;
|
||||||
|
user_cmd_frame->sender_is_local = false;
|
||||||
|
|
||||||
|
struct sim_cmd_frame_list l = ZI;
|
||||||
|
l.first = user_cmd_frame;
|
||||||
|
l.last = user_cmd_frame;
|
||||||
|
|
||||||
|
/* Encode cmds */
|
||||||
|
struct string cmds_msg = ZI;
|
||||||
|
{
|
||||||
|
struct bitbuff_writer bw = bw_from_bitbuff(&encoder_bitbuff);
|
||||||
|
/* FIXME: Ack tick */
|
||||||
|
sim_cmd_frames_encode(&bw, l);
|
||||||
|
cmds_msg = bw_get_written(temp.arena, &bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
host_queue_write(host, client->channel_id, cmds_msg, 0);
|
||||||
|
|
||||||
|
arena_temp_end(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send host messages */
|
/* Send host messages */
|
||||||
host_update(host);
|
host_update(host);
|
||||||
__profframe("Local sim");
|
__profframe("Local sim");
|
||||||
|
|
||||||
scratch_end(scratch);
|
{
|
||||||
|
/* Update network usage stats */
|
||||||
prev_ss = ss;
|
i64 stat_now_ns = sys_time_ns();
|
||||||
|
G.client_bytes_read.last_second_end = host->bytes_received;
|
||||||
|
G.client_bytes_sent.last_second_end = host->bytes_sent;
|
||||||
|
if (stat_now_ns - G.last_second_reset_ns > NS_FROM_SECONDS(1)) {
|
||||||
|
G.last_second_reset_ns = stat_now_ns;
|
||||||
|
G.client_bytes_read.last_second = G.client_bytes_read.last_second_end - G.client_bytes_read.last_second_start;
|
||||||
|
G.client_bytes_sent.last_second = G.client_bytes_sent.last_second_end - G.client_bytes_sent.last_second_start;
|
||||||
|
G.client_bytes_read.last_second_start = G.client_bytes_read.last_second_end;
|
||||||
|
G.client_bytes_sent.last_second_start = G.client_bytes_sent.last_second_end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sim_snapshot_store_release(snapshot_store);
|
scratch_end(scratch);
|
||||||
|
|
||||||
|
if (local_ss->is_master) {
|
||||||
|
local_ss_prev = local_ss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sim_snapshot_store_release(local_snapshot_store);
|
||||||
bitbuff_release(&encoder_bitbuff);
|
bitbuff_release(&encoder_bitbuff);
|
||||||
host_release(host);
|
host_release(host);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user