fixed latency stuff, some gfx stuff

This commit is contained in:
Magnus Auvinen 2007-07-26 19:09:31 +00:00
parent e588bd3b3b
commit 1d34666164
7 changed files with 190 additions and 100 deletions

View file

@ -65,17 +65,84 @@ void snap_input(void *data, int size)
// -- snapshot handling ---
enum
{
SNAP_INCOMMING=2,
NUM_SNAPSHOT_TYPES=3,
NUM_SNAPSHOT_TYPES=2,
};
static snapshot_storage snapshots_new;
struct snapshot_info
{
snapshot_info *prev;
snapshot_info *next;
int tick;
int64 recvtime;
snapshot *snap;
};
static snapshot_info *first_snapshot = 0;
static snapshot_info *last_snapshot = 0;
static snapshot_info *client_snapshot_add(int tick, int64 time, void *data, int data_size)
{
snapshot_info *holder = (snapshot_info*)mem_alloc(sizeof(snapshot_info) + data_size, 1);
holder->tick = tick;
holder->recvtime = time;
holder->snap = (snapshot *)(holder+1);
mem_copy(holder->snap, data, data_size);
holder->next =0x0;
holder->prev = last_snapshot;
if(last_snapshot)
last_snapshot->next = holder;
else
first_snapshot = holder;
last_snapshot = holder;
return holder;
}
static snapshot_info *client_snapshot_find(int tick)
{
snapshot_info *current = first_snapshot;
while(current)
{
if(current->tick == tick)
return current;
current = current->next;
}
return 0;
}
static void client_snapshot_purge_until(int tick)
{
snapshot_info *current = first_snapshot;
while(current)
{
snapshot_info *next = current->next;
if(current->tick < tick)
mem_free(current);
else
break;
current = next;
current->prev = 0;
first_snapshot = current;
}
if(!first_snapshot)
last_snapshot = 0;
}
static snapshot_info *snapshots[NUM_SNAPSHOT_TYPES];
static int current_tick;
static snapshot *snapshots[NUM_SNAPSHOT_TYPES];
static char snapshot_data[NUM_SNAPSHOT_TYPES][MAX_SNAPSHOT_SIZE];
static int recived_snapshots;
static int64 snapshot_start_time;
static int64 local_start_time;
static int64 game_start_time;
static float latency = 0;
static int extra_polating = 0;
static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE];
float client_localtime()
{
@ -85,7 +152,7 @@ float client_localtime()
void *snap_get_item(int snapid, int index, snap_item *item)
{
dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
snapshot::item *i = snapshots[snapid]->get_item(index);
snapshot::item *i = snapshots[snapid]->snap->get_item(index);
item->type = i->type();
item->id = i->id();
return (void *)i->data();
@ -94,16 +161,16 @@ void *snap_get_item(int snapid, int index, snap_item *item)
int snap_num_items(int snapid)
{
dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
return snapshots[snapid]->num_items;
return snapshots[snapid]->snap->num_items;
}
static void snap_init()
{
snapshots[SNAP_INCOMMING] = (snapshot*)snapshot_data[0];
snapshots[SNAP_CURRENT] = (snapshot*)snapshot_data[1];
snapshots[SNAP_PREV] = (snapshot*)snapshot_data[2];
mem_zero(snapshot_data, NUM_SNAPSHOT_TYPES*MAX_SNAPSHOT_SIZE);
snapshots[SNAP_CURRENT] = 0;
snapshots[SNAP_PREV] = 0;
recived_snapshots = 0;
game_start_time = -1;
}
float client_intratick()
@ -124,9 +191,9 @@ int client_tickspeed()
void *snap_find_item(int snapid, int type, int id)
{
// TODO: linear search. should be fixed.
for(int i = 0; i < snapshots[snapid]->num_items; i++)
for(int i = 0; i < snapshots[snapid]->snap->num_items; i++)
{
snapshot::item *itm = snapshots[snapid]->get_item(i);
snapshot::item *itm = snapshots[snapid]->snap->get_item(i);
if(itm->type() == type && itm->id() == id)
return (void *)itm->data();
}
@ -276,6 +343,7 @@ void client_connect(const char *server_address_str)
void client::send_info()
{
recived_snapshots = 0;
game_start_time = -1;
msg_pack_start_system(NETMSG_INFO, MSGFLAG_VITAL);
msg_pack_string(config.player_name, 128);
@ -333,6 +401,9 @@ bool client::load_data()
void client::debug_render()
{
if(!config.debug)
return;
gfx_blend_normal();
gfx_texture_set(debug_font);
gfx_mapscreen(0,0,gfx_screenwidth(),gfx_screenheight());
@ -347,9 +418,10 @@ void client::debug_render()
}
char buffer[512];
sprintf(buffer, "send: %8d recv: %8d",
sprintf(buffer, "send: %8d recv: %8d latency: %4.0f %c",
(current.send_bytes-prev.send_bytes)*10,
(current.recv_bytes-prev.recv_bytes)*10);
(current.recv_bytes-prev.recv_bytes)*10,
latency*1000.0f, extra_polating?'E':' ');
gfx_quads_text(10, 10, 16, buffer);
}
@ -461,6 +533,30 @@ void client::run(const char *direct_connect_server)
frames++;
int64 frame_start_time = time_get();
// switch snapshot
if(recived_snapshots >= 3)
{
snapshot_info *cur = snapshots[SNAP_CURRENT];
int64 t = game_start_time + (cur->tick+1)*time_freq()/50;
if(latency > 0)
t += (int64)(time_freq()*(latency*1.1f));
if(t < time_get())
{
snapshot_info *next = snapshots[SNAP_CURRENT]->next;
if(next)
{
snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
snapshots[SNAP_CURRENT] = next;
snapshot_start_time = t;
}
else
extra_polating = 1;
}
else
extra_polating = 0;
}
// send input
if(get_state() == STATE_ONLINE)
{
@ -508,7 +604,8 @@ void client::run(const char *direct_connect_server)
break;
// be nice
thread_sleep(1);
if(config.cpu_throttle)
thread_sleep(1);
if(reporttime < time_get())
{
@ -704,14 +801,11 @@ void client::process_packet(NETPACKET *packet)
{
// TODO: clean this up abit
const char *d = (const char *)msg_unpack_raw(part_size);
mem_copy((char*)snapshots[SNAP_INCOMMING] + part*MAX_SNAPSHOT_PACKSIZE, d, part_size);
mem_copy((char*)snapshot_incomming_data + part*MAX_SNAPSHOT_PACKSIZE, d, part_size);
snapshot_part++;
if(snapshot_part == num_parts)
{
snapshot *tmp = snapshots[SNAP_PREV];
snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
snapshots[SNAP_CURRENT] = tmp;
current_tick = game_tick;
// decompress snapshot
@ -722,7 +816,7 @@ void client::process_packet(NETPACKET *packet)
unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE];
if(part_size)
{
int compsize = zerobit_decompress(snapshots[SNAP_INCOMMING], part_size, tmpbuffer);
int compsize = zerobit_decompress(snapshot_incomming_data, part_size, tmpbuffer);
int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
deltadata = tmpbuffer2;
deltasize = intsize;
@ -734,44 +828,65 @@ void client::process_packet(NETPACKET *packet)
emptysnap.num_items = 0;
snapshot *deltashot = &emptysnap;
int deltashot_size;
if(delta_tick >= 0)
{
void *delta_data;
deltashot_size = snapshots_new.get(delta_tick, 0, &delta_data);
if(deltashot_size >= 0)
{
deltashot = (snapshot *)delta_data;
}
//void *delta_data;
snapshot_info *delta_info = client_snapshot_find(delta_tick);
//deltashot_size = snapshots_new.get(delta_tick, 0, &delta_data);
if(delta_info)
deltashot = delta_info->snap;
else
{
// TODO: handle this
dbg_msg("client", "error, couldn't find the delta snapshot");
}
}
unsigned char tmpbuffer3[MAX_SNAPSHOT_SIZE];
int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)tmpbuffer3, deltadata, deltasize);
int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)snapshots[SNAP_CURRENT], deltadata, deltasize);
//snapshot *shot = (snapshot *)snapshots[SNAP_CURRENT];
// purge old snapshots
snapshots_new.purge_until(delta_tick);
snapshots_new.purge_until(game_tick-50); // TODO: change this to server tickrate
// purge old snapshots
int purgetick = delta_tick;
if(snapshots[SNAP_PREV] && snapshots[SNAP_PREV]->tick < purgetick)
purgetick = snapshots[SNAP_PREV]->tick;
if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick)
purgetick = snapshots[SNAP_PREV]->tick;
client_snapshot_purge_until(purgetick);
//client_snapshot_purge_until(game_tick-50);
// add new
snapshots_new.add(game_tick, time_get(), snapsize, snapshots[SNAP_CURRENT]);
snapshot_info *snap = client_snapshot_add(game_tick, time_get(), tmpbuffer3, snapsize);
// apply snapshot, cycle pointers
recived_snapshots++;
snapshot_start_time = time_get();
// we got two snapshots until we see us self as connected
if(recived_snapshots <= 2)
{
snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
snapshots[SNAP_CURRENT] = snap;
snapshot_start_time = time_get();
}
if(recived_snapshots == 2)
{
local_start_time = time_get();
set_state(STATE_ONLINE);
}
int64 now = time_get();
int64 t = now - game_tick*time_freq()/50;
if(game_start_time == -1 || t < game_start_time)
{
dbg_msg("client", "adjusted time");
game_start_time = t;
}
int64 wanted = game_start_time+(game_tick*time_freq())/50;
float current_latency = (now-wanted)/(float)time_freq();
latency = latency*0.95f+current_latency*0.05f;
if(recived_snapshots > 2)
modc_newsnapshot();

View file

@ -212,6 +212,8 @@ bool gfx_init()
textures[i].next = i+1;
textures[MAX_TEXTURES-1].next = -1;
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// create null texture, will get id=0
gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data);
@ -221,8 +223,37 @@ bool gfx_init()
return true;
}
video_mode fakemodes[] = {
{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
{2048,1536,8,8,8},
{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
{2048,1536,5,6,5}
};
int gfx_get_video_modes(video_mode *list, int maxcount)
{
if(config.display_all_modes)
{
mem_copy(list, fakemodes, sizeof(fakemodes));
return min((int)(sizeof(fakemodes)/sizeof(video_mode)), maxcount);
}
return context.getvideomodes((opengl::videomode *)list, maxcount);
}

View file

@ -5,11 +5,15 @@ MACRO_CONFIG_INT(screen_height, 600, 0, 0)
MACRO_CONFIG_INT(fullscreen, 1, 0, 1)
MACRO_CONFIG_INT(color_depth, 24, 16, 24)
MACRO_CONFIG_INT(vsync, 1, 0, 1)
MACRO_CONFIG_INT(debug, 0, 0, 1)
MACRO_CONFIG_INT(display_all_modes, 0, 0, 1)
MACRO_CONFIG_INT(volume, 200, 0, 255)
MACRO_CONFIG_INT(cpu_throttle, 0, 0, 1)
MACRO_CONFIG_STR(player_name, 32, "nameless tee")
MACRO_CONFIG_STR(clan_name, 32, "")
MACRO_CONFIG_STR(password, 32, "")
MACRO_CONFIG_STR(masterserver, 128, "master.teewars.com")
MACRO_CONFIG_INT(sv_port, 8303, 0, 0)

View file

@ -102,64 +102,6 @@ public:
return -1;
}
};
/*
class snapshot_delta_builder
{
public:
static const int MAX_ITEMS = 512;
char data[MAX_SNAPSHOT_SIZE];
int data_size;
int offsets[MAX_ITEMS];
int num_items;
int top_size;
int top_items;
int snapnum;
snapshot_delta_builder()
{
top_size = 0;
top_items = 0;
snapnum = 0;
}
void start()
{
data_size = 0;
num_items = 0;
}
int finish(void *snapdata)
{
snapnum++;
// flattern and make the snapshot
snapshot *snap = (snapshot *)snapdata;
snap->data_size = data_size;
snap->num_items = num_items;
int offset_size = sizeof(int)*num_items;
mem_copy(snap->offsets, offsets, offset_size);
mem_copy(snap->data_start(), data, data_size);
return sizeof(int) + offset_size + data_size;
}
void *new_item(int type, int id, int size)
{
snapshot::item *obj = (snapshot::item *)(data+data_size);
obj->type_and_id = (type<<16)|id;
offsets[num_items] = data_size;
data_size += sizeof(int) + size;
num_items++;
dbg_assert(data_size < MAX_SNAPSHOT_SIZE, "too much data");
dbg_assert(num_items < MAX_ITEMS, "too many items");
return &obj->data;
}
};
*/
class snapshot_builder
{

View file

@ -951,7 +951,7 @@ static void render_player(obj_player *prev, obj_player *player)
if (dir.x < 0.0f)
hadokenangle += pi;
gfx_quads_setrotation(hadokenangle);
float offsety = -data->weapons[iw].muzzleoffsety;
//float offsety = -data->weapons[iw].muzzleoffsety;
select_sprite(data->weapons[iw].sprite_muzzle[itex].psprite, 0);
vec2 diry(-dir.y,dir.x);
p = position;
@ -1707,7 +1707,7 @@ void modc_render()
render_tee(&idlestate, skin, vec2(1,0), vec2(offsetx + x+90, offsets[player->team]+24));
sprintf(buf, "%4d", player->latency);
float tw = gfx_pretty_text_width(48.0f, buf);
//float tw = gfx_pretty_text_width(48.0f, buf);
gfx_pretty_text(offsetx + x + 240, offsets[player->team], 48, buf);
offsets[player->team] += 58.0f;

View file

@ -40,8 +40,6 @@ void tilemap_render(float scale, int fg)
{
gfx_texture_set(img_get(tmap->image));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if(!batches[t])
{
gfx_quads_begin();

View file

@ -102,8 +102,8 @@ int run(int port, netaddr4 dest)
// update lag
double flux = rand()/(double)RAND_MAX;
int ms_spike = 0;
int ms_flux = 100;
int ms_ping = 50;
int ms_flux = 20;
int ms_ping = 20;
current_latency = ((time_freq()*ms_ping)/1000) + (int64)(((time_freq()*ms_flux)/1000)*flux); // 50ms
if((p->id%100) == 0)