diff --git a/datasrc/network.py b/datasrc/network.py index 318007f99..2d71abe39 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -237,7 +237,11 @@ Messages = [ NetIntRange("pass", 0, 'MAX_CLIENTS'), NetIntRange("total", 0, 'MAX_CLIENTS'), ]), - + + NetMessage("sv_maplist", [ + NetString("names"), + ]), + ### Client messages NetMessage("cl_say", [ NetBool("team"), diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c index 845a3f22e..1ae1d51af 100644 --- a/src/engine/client/ec_client.c +++ b/src/engine/client/ec_client.c @@ -78,6 +78,9 @@ static int mapdownload_crc = 0; static int mapdownload_amount = -1; static int mapdownload_totalsize = -1; +/* */ +static SERVER_INFO current_server_info = {0}; + /* current time */ static int current_tick = 0; static float intratick = 0; @@ -490,6 +493,7 @@ void client_connect(const char *server_address_str) dbg_msg("client", "connecting to '%s'", server_address_str); + mem_zero(¤t_server_info, sizeof(current_server_info)); str_copy(buf, server_address_str, sizeof(buf)); for(k = 0; buf[k]; k++) @@ -534,7 +538,9 @@ void client_disconnect_with_reason(const char *reason) mapdownload_crc = 0; mapdownload_totalsize = -1; mapdownload_amount = 0; - + + /* clear the current server info */ + mem_zero(¤t_server_info, sizeof(current_server_info)); } void client_disconnect() @@ -1069,7 +1075,10 @@ static void client_process_packet(NETCHUNK *packet) if(msg != NETMSG_SNAPEMPTY && snapshot_crc((SNAPSHOT*)tmpbuffer3) != crc) { if(config.debug) - dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d", snapcrcerrors, game_tick, crc, snapshot_crc((SNAPSHOT*)tmpbuffer3), complete_size); + { + dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d", + snapcrcerrors, game_tick, crc, snapshot_crc((SNAPSHOT*)tmpbuffer3), complete_size, delta_tick); + } snapcrcerrors++; if(snapcrcerrors > 10) diff --git a/src/engine/client/ec_srvbrowse.c b/src/engine/client/ec_srvbrowse.c index 20a80e973..d40b921c9 100644 --- a/src/engine/client/ec_srvbrowse.c +++ b/src/engine/client/ec_srvbrowse.c @@ -502,7 +502,7 @@ void client_serverbrowse_refresh(int type) } } -static void client_serverbrowse_request(SERVERENTRY *entry) +static void client_serverbrowse_request(NETADDR *addr, SERVERENTRY *entry) { /*unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];*/ NETCHUNK p; @@ -510,15 +510,15 @@ static void client_serverbrowse_request(SERVERENTRY *entry) if(config.debug) { dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d", - entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2], - entry->addr.ip[3], entry->addr.port); + addr->ip[0], addr->ip[1], addr->ip[2], + addr->ip[3], addr->port); } /*mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)); buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;*/ p.client_id = -1; - p.address = entry->addr; + p.address = *addr; p.flags = NETSENDFLAG_CONNLESS; /*p.data_size = sizeof(buffer); p.data = buffer; @@ -529,7 +529,8 @@ static void client_serverbrowse_request(SERVERENTRY *entry) p.data = SERVERBROWSE_OLD_GETINFO; netclient_send(net, &p); - entry->request_time = time_get(); + if(entry) + entry->request_time = time_get(); } void client_serverbrowse_update() @@ -600,7 +601,7 @@ void client_serverbrowse_update() break; if(entry->request_time == 0) - client_serverbrowse_request(entry); + client_serverbrowse_request(&entry->addr, entry); count++; entry = entry->next_req; diff --git a/src/game/client/components/maplist.cpp b/src/game/client/components/maplist.cpp new file mode 100644 index 000000000..027ec4490 --- /dev/null +++ b/src/game/client/components/maplist.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include "maplist.hpp" + +MAPLIST::MAPLIST() +{ + on_reset(); +} + +void MAPLIST::on_reset() +{ + buffer[0] = 0; + num_maps = 0; +} + +static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; } + +void MAPLIST::on_message(int msgtype, void *rawmsg) +{ + if(msgtype == NETMSGTYPE_SV_MAPLIST) + { + NETMSG_SV_MAPLIST *msg = (NETMSG_SV_MAPLIST*)rawmsg; + str_copy(buffer, msg->names, sizeof(buffer)); + + // parse list + num_maps = 0; + char *ptr = buffer; + while(*ptr) + { + while(*ptr && is_separator(*ptr)) + { + *ptr = 0; + ptr++; + } + + if(*ptr) + { + maps[num_maps++] = ptr; + while(*ptr && !is_separator(*ptr)) + ptr++; + } + } + } +} diff --git a/src/game/client/components/maplist.hpp b/src/game/client/components/maplist.hpp new file mode 100644 index 000000000..9b7ee1fdc --- /dev/null +++ b/src/game/client/components/maplist.hpp @@ -0,0 +1,15 @@ +#include + +class MAPLIST : public COMPONENT +{ + char buffer[2048]; + const char *maps[128]; + int num_maps; +public: + MAPLIST(); + virtual void on_reset(); + virtual void on_message(int msgtype, void *rawmsg); + + int num() const { return num_maps; } + const char *name(int index) const { return maps[index]; } +}; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index d2759642b..f28a3197b 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -21,13 +21,7 @@ extern "C" { #include #include -#include -#include -#include #include -#include -#include -#include #include vec4 MENUS::gui_color; @@ -38,7 +32,6 @@ vec4 MENUS::color_tabbar_active; vec4 MENUS::color_tabbar_inactive_ingame; vec4 MENUS::color_tabbar_active_ingame; - INPUT_EVENT MENUS::inputevents[MAX_INPUTEVENTS]; int MENUS::num_inputevents; @@ -92,6 +85,8 @@ MENUS::MENUS() num_inputevents = 0; last_input = time_get(); + + button_height = 25.0f; } vec4 MENUS::button_color_mul(const void *id) @@ -533,6 +528,12 @@ int MENUS::render_menubar(RECT r) static int server_info_button=0; if (ui_do_button(&server_info_button, "Server Info", active_page==PAGE_SERVER_INFO, &button, ui_draw_menu_tab_button, 0)) new_page = PAGE_SERVER_INFO; + + ui_vsplit_l(&box, 4.0f, 0, &box); + ui_vsplit_l(&box, 140.0f, &button, &box); + static int callvote_button=0; + if (ui_do_button(&callvote_button, "Call Vote", active_page==PAGE_CALLVOTE, &button, ui_draw_menu_tab_button, 0)) + new_page = PAGE_CALLVOTE; ui_vsplit_l(&box, 30.0f, 0, &box); } @@ -619,245 +620,6 @@ void MENUS::render_news(RECT main_view) ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); } -void MENUS::render_game(RECT main_view) -{ - RECT button; - //RECT votearea; - ui_hsplit_t(&main_view, 45.0f, &main_view, 0); - ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); - - ui_hsplit_t(&main_view, 10.0f, 0, &main_view); - ui_hsplit_t(&main_view, 25.0f, &main_view, 0); - ui_vmargin(&main_view, 10.0f, &main_view); - - ui_vsplit_r(&main_view, 120.0f, &main_view, &button); - static int disconnect_button = 0; - if(ui_do_button(&disconnect_button, "Disconnect", 0, &button, ui_draw_menu_button, 0)) - client_disconnect(); - - if(gameclient.snap.local_info && gameclient.snap.gameobj) - { - if(gameclient.snap.local_info->team != -1) - { - ui_vsplit_l(&main_view, 10.0f, &button, &main_view); - ui_vsplit_l(&main_view, 120.0f, &button, &main_view); - static int spectate_button = 0; - if(ui_do_button(&spectate_button, "Spectate", 0, &button, ui_draw_menu_button, 0)) - { - gameclient.send_switch_team(-1); - menu_active = false; - } - } - - if(gameclient.snap.gameobj->flags & GAMEFLAG_TEAMS) - { - if(gameclient.snap.local_info->team != 0) - { - ui_vsplit_l(&main_view, 10.0f, &button, &main_view); - ui_vsplit_l(&main_view, 120.0f, &button, &main_view); - static int spectate_button = 0; - if(ui_do_button(&spectate_button, "Join Red", 0, &button, ui_draw_menu_button, 0)) - { - gameclient.send_switch_team(0); - menu_active = false; - } - } - - if(gameclient.snap.local_info->team != 1) - { - ui_vsplit_l(&main_view, 10.0f, &button, &main_view); - ui_vsplit_l(&main_view, 120.0f, &button, &main_view); - static int spectate_button = 0; - if(ui_do_button(&spectate_button, "Join Blue", 0, &button, ui_draw_menu_button, 0)) - { - gameclient.send_switch_team(1); - menu_active = false; - } - } - } - else - { - if(gameclient.snap.local_info->team != 0) - { - ui_vsplit_l(&main_view, 10.0f, &button, &main_view); - ui_vsplit_l(&main_view, 120.0f, &button, &main_view); - static int spectate_button = 0; - if(ui_do_button(&spectate_button, "Join Game", 0, &button, ui_draw_menu_button, 0)) - { - gameclient.send_switch_team(0); - menu_active = false; - } - } - } - } - - /* - RECT bars; - ui_hsplit_t(&votearea, 10.0f, 0, &votearea); - ui_hsplit_t(&votearea, 25.0f + 10.0f*3 + 25.0f, &votearea, &bars); - - ui_draw_rect(&votearea, color_tabbar_active, CORNER_ALL, 10.0f); - - ui_vmargin(&votearea, 20.0f, &votearea); - ui_hmargin(&votearea, 10.0f, &votearea); - - ui_hsplit_b(&votearea, 35.0f, &votearea, &bars); - - if(gameclient.voting->is_voting()) - { - // do yes button - ui_vsplit_l(&votearea, 50.0f, &button, &votearea); - static int yes_button = 0; - if(ui_do_button(&yes_button, "Yes", 0, &button, ui_draw_menu_button, 0)) - gameclient.voting->vote(1); - - // do no button - ui_vsplit_l(&votearea, 5.0f, 0, &votearea); - ui_vsplit_l(&votearea, 50.0f, &button, &votearea); - static int no_button = 0; - if(ui_do_button(&no_button, "No", 0, &button, ui_draw_menu_button, 0)) - gameclient.voting->vote(-1); - - // do time left - ui_vsplit_r(&votearea, 50.0f, &votearea, &button); - char buf[256]; - str_format(buf, sizeof(buf), "%d", gameclient.voting->seconds_left()); - ui_do_label(&button, buf, 24.0f, 0); - - // do description and command - ui_vsplit_l(&votearea, 5.0f, 0, &votearea); - ui_do_label(&votearea, gameclient.voting->vote_description(), 14.0f, -1); - ui_hsplit_t(&votearea, 16.0f, 0, &votearea); - ui_do_label(&votearea, gameclient.voting->vote_command(), 10.0f, -1); - - // do bars - ui_hsplit_t(&bars, 10.0f, 0, &bars); - ui_hmargin(&bars, 5.0f, &bars); - - gameclient.voting->render_bars(bars, true); - - } - else - { - ui_do_label(&votearea, "No vote in progress", 18.0f, -1); - }*/ -} - -void MENUS::render_serverinfo(RECT main_view) -{ - // count players for server info-box - int num_players = 0; - for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) - { - SNAP_ITEM item; - snap_get_item(SNAP_CURRENT, i, &item); - - if(item.type == NETOBJTYPE_PLAYER_INFO) - { - num_players++; - } - } - - // render background - ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); - - RECT view, serverinfo, gameinfo, motd; - - float x = 0.0f; - float y = 0.0f; - - char buf[1024]; - - // set view to use for all sub-modules - ui_margin(&main_view, 10.0f, &view); - - /* serverinfo */ - ui_hsplit_t(&view, view.h/2-5.0f, &serverinfo, &motd); - ui_vsplit_l(&serverinfo, view.w/2-5.0f, &serverinfo, &gameinfo); - ui_draw_rect(&serverinfo, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); - - ui_margin(&serverinfo, 5.0f, &serverinfo); - - x = 5.0f; - y = 0.0f; - - gfx_text(0, serverinfo.x+x, serverinfo.y+y, 32, "Server info", 250.0f); - y += 32.0f+5.0f; - - mem_zero(buf, sizeof(buf)); - str_format( - buf, - sizeof(buf), - "%s\n\n" - "Address: %s\n" - "Ping: %d\n" - "Version: %s\n" - "Password: %s\n", - current_server_info.name, - config.ui_server_address, - gameclient.snap.local_info->latency, - current_server_info.version, - current_server_info.flags&1 ? "Yes" : "No" - ); - gfx_text(0, serverinfo.x+x, serverinfo.y+y, 20, buf, 250.0f); - - { - RECT button; - ui_hsplit_b(&serverinfo, 20.0f, &serverinfo, &button); - static int add_fav_button = 0; - if (ui_do_button(&add_fav_button, "Favorite", current_server_info.favorite, &button, ui_draw_checkbox, 0)) - { - if(current_server_info.favorite) - client_serverbrowse_removefavorite(current_server_info.netaddr); - else - client_serverbrowse_addfavorite(current_server_info.netaddr); - current_server_info.favorite = !current_server_info.favorite; - } - } - - /* gameinfo */ - ui_vsplit_l(&gameinfo, 10.0f, 0x0, &gameinfo); - ui_draw_rect(&gameinfo, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); - - ui_margin(&gameinfo, 5.0f, &gameinfo); - - x = 5.0f; - y = 0.0f; - - gfx_text(0, gameinfo.x+x, gameinfo.y+y, 32, "Game info", 250.0f); - y += 32.0f+5.0f; - - mem_zero(buf, sizeof(buf)); - str_format( - buf, - sizeof(buf), - "\n\n" - "Gametype: %s\n" - "Map: %s\n" - "Score limit: %d\n" - "Time limit: %d\n" - "\n" - "Players: %d/%d\n", - current_server_info.gametype, - current_server_info.map, - gameclient.snap.gameobj->score_limit, - gameclient.snap.gameobj->time_limit, - gameclient.snap.team_size[0]+gameclient.snap.team_size[1], - current_server_info.max_players - ); - gfx_text(0, gameinfo.x+x, gameinfo.y+y, 20, buf, 250.0f); - - /* motd */ - ui_hsplit_t(&motd, 10.0f, 0, &motd); - ui_draw_rect(&motd, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); - ui_margin(&motd, 5.0f, &motd); - y = 0.0f; - x = 5.0f; - gfx_text(0, motd.x+x, motd.y+y, 32, "MOTD", -1); - y += 32.0f+5.0f; - gfx_text(0, motd.x+x, motd.y+y, 16, gameclient.motd->server_motd, motd.w); -} - void MENUS::init() { if(config.cl_show_welcome) @@ -912,6 +674,8 @@ int MENUS::render() render_game(main_view); else if(game_page == PAGE_SERVER_INFO) render_serverinfo(main_view); + else if(game_page == PAGE_CALLVOTE) + render_servercontrol(main_view); else if(game_page == PAGE_SETTINGS) render_settings(main_view); } @@ -1167,6 +931,11 @@ void MENUS::on_render() if(!menu_active) return; + + + if(inp_key_down('M')) button_height += 1.0f; + if(inp_key_down('N')) button_height -= 1.0f; + // update colors vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f)); gui_color = vec4(rgb.r, rgb.g, rgb.b, config.ui_color_alpha/255.0f); @@ -1201,7 +970,7 @@ void MENUS::on_render() ui_update(mx,my,mx*3.0f,my*3.0f,buttons); // render - if(time_get()-last_input > time_freq()*30) + if(time_get()-last_input > time_freq()*30 && client_state() == CLIENTSTATE_OFFLINE) { // screen saver :) render_background(); @@ -1308,253 +1077,3 @@ void MENUS::render_background() {RECT screen = *ui_screen(); gfx_mapscreen(screen.x, screen.y, screen.w, screen.h);} } - - -#if 0 -static int texture_mountains = -1; -static int texture_sun = -1; -static int texture_grass = -1; - -static const int tiles_width = 50; -static const int tiles_height = 10; -static TILE tiles[tiles_width*tiles_height] = {{0}}; - -class TEE -{ -public: - float speed; - int skin; - float time; - vec2 pos; - //float vy; - - float jumptime; - float jumpstr; - - void new_jump() - { - jumptime = time + (rand()/(float)RAND_MAX)*2; - jumpstr = 12.6f*20 * ((rand()/(float)RAND_MAX)*0.5f+0.5f); - } - - void init() - { - skin = rand(); - speed = 150.0f + (rand()/(float)RAND_MAX) * 50.0f; - time = (rand()/(float)RAND_MAX) * 5.0f; - jumptime = 0; - update(0); - new_jump(); - } - - void reset() - { - time = 0; - pos.x = -100.0f; - - jumptime = 0; - new_jump(); - skin = rand(); - } - - void update(float frametime) - { - time += frametime; - pos.x = -100 + time*speed; - pos.y = 0; - if(time > jumptime) - { - float t = time - jumptime; - float j = -jumpstr*t + 25.0f*15*(t*t); - if(j < 0) - pos.y = j; - else - new_jump(); - } - - if(pos.x > 300*2) - reset(); - } -}; - -static const int NUM_TEES = 35; -static TEE tees[NUM_TEES]; - -static void render_sunrays(float x, float y) -{ - vec2 pos(x, y); - - gfx_texture_set(-1); - gfx_blend_additive(); - gfx_quads_begin(); - const int rays = 10; - gfx_setcolor(1.0f,1.0f,1.0f,0.025f); - for(int r = 0; r < rays; r++) - { - float a = r/(float)rays + client_localtime()*0.015f; - float size = (1.0f/(float)rays)*0.25f; - vec2 dir0(sinf((a-size)*pi*2.0f), cosf((a-size)*pi*2.0f)); - vec2 dir1(sinf((a+size)*pi*2.0f), cosf((a+size)*pi*2.0f)); - - gfx_setcolorvertex(0, 1.0f,1.0f,1.0f,0.025f); - gfx_setcolorvertex(1, 1.0f,1.0f,1.0f,0.025f); - gfx_setcolorvertex(2, 1.0f,1.0f,1.0f,0.0f); - gfx_setcolorvertex(3, 1.0f,1.0f,1.0f,0.0f); - const float range = 1000.0f; - gfx_quads_draw_freeform( - pos.x+dir0.x, pos.y+dir0.y, - pos.x+dir1.x, pos.y+dir1.y, - pos.x+dir0.x*range, pos.y+dir0.y*range, - pos.x+dir1.x*range, pos.y+dir1.y*range); - } - gfx_quads_end(); - gfx_blend_normal(); -} - -void MENUS::render_background() -{ - gfx_clear(1,1,1); - - static int load = 1; - if(load) - { - load = 0; - texture_mountains = gfx_load_texture("data/mapres/mountains.png", IMG_AUTO, 0); - texture_sun = gfx_load_texture("data/mapres/sun.png", IMG_AUTO, 0); - texture_grass = gfx_load_texture("data/mapres/grass_main.png", IMG_AUTO, 0); - - for(int i = 0; i < NUM_TEES; i++) - tees[i].init(); - - int c = 0; - for(int y = 0; y < tiles_height; y++) - for(int x = 0; x < tiles_width; x++, c++) - { - if(y == 0) - tiles[c].index = 16; - else - { - int r = rand()&0x3f; - if(r == 1) - tiles[c].index = 2; - else if(r == 2) - tiles[c].index = 3; - else - tiles[c].index = 1; - } - } - } - - float sw = 300*gfx_screenaspect(); - float sh = 300; - gfx_mapscreen(0, 0, sw, sh); - - // render backdrop color - gfx_texture_set(-1); - gfx_quads_begin(); - vec4 top(0.7f, 0.8f, 1.0f, 1.0f); - vec4 bottom = top*0.5f;//(0.6f, 0.6f, 0.6f, 1.0f); - gfx_setcolorvertex(0, top.r, top.g, top.b, top.a); - gfx_setcolorvertex(1, top.r, top.g, top.b, top.a); - gfx_setcolorvertex(2, bottom.r, bottom.g, bottom.b, bottom.a); - gfx_setcolorvertex(3, bottom.r, bottom.g, bottom.b, bottom.a); - gfx_quads_drawTL(0, 0, sw, sh); - gfx_quads_end(); - - // render sunrays - render_sunrays(75, 50); - - // render sun - gfx_texture_set(texture_sun); - gfx_quads_begin(); - gfx_quads_draw(75, 50, 128, 128); - gfx_quads_end(); - - - gfx_mapscreen(0, 0, sw, sh); - - int num_skins = gameclient.skins->num(); - - for(int layer = 0; layer < 2; layer++) - { - vec4 color = layer == 0 ? vec4(0.9f, 0.95f, 1.0f, 1.0f) : vec4(1,1,1,1); - float scale = layer == 0 ? 0.5f : 1.0f; - float mountainoffset = layer == 0 ? 220 : 190; - float mountainstreach = layer == 0 ? 2 : 1; - float groundoffset = layer == 0 ? 95 : 30; - - // draw mountains - float w = 192*2*scale; - float start = fmod(client_localtime()*20.0f*scale, w); - gfx_mapscreen(start, 0, sw+start, sh); - gfx_texture_set(texture_mountains); - gfx_quads_begin(); - gfx_setcolor(color.r, color.g, color.b, color.a); - gfx_quads_drawTL(0, sh-mountainoffset, w, 192*scale*mountainstreach); - gfx_quads_drawTL(w, sh-mountainoffset, w, 192*scale*mountainstreach); - gfx_quads_drawTL(w*2, sh-mountainoffset, w, 192*scale*mountainstreach); - gfx_quads_drawTL(w*3, sh-mountainoffset, w, 192*scale*mountainstreach); - gfx_quads_end(); - - // draw ground - { - float w = 16.0f*scale*(tiles_width); - float start = fmod(client_localtime()*20.0f*(scale+0.25f), w); - float offset = -300.0f + groundoffset; - for(int i = 0; i < 4; i++) - { - gfx_mapscreen(start-i*w, offset, sw+start-i*w, offset+sh); - gfx_texture_set(texture_grass); - render_tilemap(tiles, tiles_width, tiles_height, 16.0f*scale, color, LAYERRENDERFLAG_OPAQUE); - render_tilemap(tiles, tiles_width, tiles_height, 16.0f*scale, color, LAYERRENDERFLAG_TRANSPARENT); - } - } - - if(num_skins) - { - gfx_mapscreen(0, 0, sw, sh); - - for(int i = layer; i < NUM_TEES; i+=2) - { - TEE *tee = &tees[i]; - tee->update(client_frametime()); - - ANIMSTATE state; - mem_zero(&state, sizeof(state)); - state.set(&data->animations[ANIM_BASE], 0); - - if(tee->pos.y < -0.0001f) - state.add(&data->animations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here - else - state.add(&data->animations[ANIM_WALK], fmod(tee->pos.x*0.025f, 1.0f), 1.0f); - - TEE_RENDER_INFO render_info; - render_info.size = 24.0f*scale; - render_info.color_body = color; - render_info.color_feet = color; - render_info.texture = gameclient.skins->get(tee->skin%num_skins)->org_texture; - - if(layer == 0) - render_tee(&state, &render_info, 0, vec2(-1,0), vec2(sw+20-tee->pos.x, tee->pos.y*scale+(sh-groundoffset)-6*scale)); - else - render_tee(&state, &render_info, 0, vec2(1,0), vec2(tee->pos.x, tee->pos.y*scale+(sh-groundoffset)-6*scale)); - } - } - } - - {RECT screen = *ui_screen(); - gfx_mapscreen(screen.x, screen.y, screen.w, screen.h);} - - /* - if(data->images[IMAGE_BANNER].id != 0) - { - gfx_texture_set(data->images[IMAGE_BANNER].id); - gfx_quads_begin(); - gfx_setcolor(0,0,0,0.05f); - gfx_quads_setrotation(-pi/4+0.15f); - gfx_quads_draw(400, 300, 1000, 250); - gfx_quads_end(); - }*/ -} - -#endif diff --git a/src/game/client/components/menus.hpp b/src/game/client/components/menus.hpp index 0349ec803..abe26135e 100644 --- a/src/game/client/components/menus.hpp +++ b/src/game/client/components/menus.hpp @@ -48,6 +48,7 @@ class MENUS : public COMPONENT PAGE_NEWS=0, PAGE_GAME, PAGE_SERVER_INFO, + PAGE_CALLVOTE, PAGE_INTERNET, PAGE_LAN, PAGE_FAVORITES, @@ -68,8 +69,15 @@ class MENUS : public COMPONENT static INPUT_EVENT inputevents[MAX_INPUTEVENTS]; static int num_inputevents; + // some settings + float button_height; + // for graphic settings bool need_restart; + + // for call vote + int callvote_selectedplayer; + int callvote_selectedmap; // found in menus.cpp int render(); @@ -77,8 +85,13 @@ class MENUS : public COMPONENT //void render_loading(float percent); int render_menubar(RECT r); void render_news(RECT main_view); + + // found in menus_ingame.cpp void render_game(RECT main_view); void render_serverinfo(RECT main_view); + void render_servercontrol(RECT main_view); + void render_servercontrol_kick(RECT main_view); + void render_servercontrol_map(RECT main_view); // found in menus_browser.cpp SERVER_INFO current_server_info; // should this be here? diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index a462b4213..376f87bba 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -373,7 +373,7 @@ void MENUS::render_serverbrowser_filters(RECT view) } //ui_vsplit_r(&buttons, 30.0f, &buttons, &button); - ui_hsplit_b(&view, 25.0f, &view, &button); + ui_hsplit_b(&view, button_height, &view, &button); static int clear_button = 0; if(ui_do_button(&clear_button, "Reset Filter", 0, &button, ui_draw_menu_button, 0)) { @@ -544,7 +544,7 @@ void MENUS::render_serverbrowser(RECT main_view) // split off a piece for filters, details and scoreboard ui_vsplit_r(&view, 200.0f, &view, &toolbox); ui_hsplit_b(&toolbox, 120.0f, &toolbox, &button_box); - ui_hsplit_b(&view, 30.0f, &view, &status_toolbar); + ui_hsplit_b(&view, button_height+5.0f, &view, &status_toolbar); render_serverbrowser_serverlist(view); @@ -562,7 +562,6 @@ void MENUS::render_serverbrowser(RECT main_view) ui_vsplit_r(&tabbutton0, 5.0f, &tabbutton0, 0); ui_vsplit_l(&tabbutton1, 5.0f, 0, &tabbutton1); - static int filters_tab = 0; if (ui_do_button(&filters_tab, "Filter", toolbox_page==0, &tabbutton0, ui_draw_menu_tab_button, 0)) toolbox_page = 0; @@ -612,7 +611,7 @@ void MENUS::render_serverbrowser(RECT main_view) ui_vsplit_r(&button_box, 5.0f, &button_box, 0); RECT button; - ui_hsplit_b(&button_box, 25.0f, &button_box, &button); + ui_hsplit_b(&button_box, button_height, &button_box, &button); ui_vsplit_r(&button, 120.0f, 0, &button); ui_vmargin(&button, 2.0f, &button); //ui_vmargin(&button, 2.0f, &button); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp new file mode 100644 index 000000000..80b5f0fda --- /dev/null +++ b/src/game/client/components/menus_ingame.cpp @@ -0,0 +1,391 @@ + +#include + +#include // strcmp, strlen, strncpy +#include // atoi + +#include + +#include +#include + +#include +#include +#include + +#include "menus.hpp" +#include "motd.hpp" +#include "voting.hpp" +#include "maplist.hpp" + +void MENUS::render_game(RECT main_view) +{ + RECT button; + //RECT votearea; + ui_hsplit_t(&main_view, 45.0f, &main_view, 0); + ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); + + ui_hsplit_t(&main_view, 10.0f, 0, &main_view); + ui_hsplit_t(&main_view, 25.0f, &main_view, 0); + ui_vmargin(&main_view, 10.0f, &main_view); + + ui_vsplit_r(&main_view, 120.0f, &main_view, &button); + static int disconnect_button = 0; + if(ui_do_button(&disconnect_button, "Disconnect", 0, &button, ui_draw_menu_button, 0)) + client_disconnect(); + + if(gameclient.snap.local_info && gameclient.snap.gameobj) + { + if(gameclient.snap.local_info->team != -1) + { + ui_vsplit_l(&main_view, 10.0f, &button, &main_view); + ui_vsplit_l(&main_view, 120.0f, &button, &main_view); + static int spectate_button = 0; + if(ui_do_button(&spectate_button, "Spectate", 0, &button, ui_draw_menu_button, 0)) + { + gameclient.send_switch_team(-1); + menu_active = false; + } + } + + if(gameclient.snap.gameobj->flags & GAMEFLAG_TEAMS) + { + if(gameclient.snap.local_info->team != 0) + { + ui_vsplit_l(&main_view, 10.0f, &button, &main_view); + ui_vsplit_l(&main_view, 120.0f, &button, &main_view); + static int spectate_button = 0; + if(ui_do_button(&spectate_button, "Join Red", 0, &button, ui_draw_menu_button, 0)) + { + gameclient.send_switch_team(0); + menu_active = false; + } + } + + if(gameclient.snap.local_info->team != 1) + { + ui_vsplit_l(&main_view, 10.0f, &button, &main_view); + ui_vsplit_l(&main_view, 120.0f, &button, &main_view); + static int spectate_button = 0; + if(ui_do_button(&spectate_button, "Join Blue", 0, &button, ui_draw_menu_button, 0)) + { + gameclient.send_switch_team(1); + menu_active = false; + } + } + } + else + { + if(gameclient.snap.local_info->team != 0) + { + ui_vsplit_l(&main_view, 10.0f, &button, &main_view); + ui_vsplit_l(&main_view, 120.0f, &button, &main_view); + static int spectate_button = 0; + if(ui_do_button(&spectate_button, "Join Game", 0, &button, ui_draw_menu_button, 0)) + { + gameclient.send_switch_team(0); + menu_active = false; + } + } + } + } + + /* + RECT bars; + ui_hsplit_t(&votearea, 10.0f, 0, &votearea); + ui_hsplit_t(&votearea, 25.0f + 10.0f*3 + 25.0f, &votearea, &bars); + + ui_draw_rect(&votearea, color_tabbar_active, CORNER_ALL, 10.0f); + + ui_vmargin(&votearea, 20.0f, &votearea); + ui_hmargin(&votearea, 10.0f, &votearea); + + ui_hsplit_b(&votearea, 35.0f, &votearea, &bars); + + if(gameclient.voting->is_voting()) + { + // do yes button + ui_vsplit_l(&votearea, 50.0f, &button, &votearea); + static int yes_button = 0; + if(ui_do_button(&yes_button, "Yes", 0, &button, ui_draw_menu_button, 0)) + gameclient.voting->vote(1); + + // do no button + ui_vsplit_l(&votearea, 5.0f, 0, &votearea); + ui_vsplit_l(&votearea, 50.0f, &button, &votearea); + static int no_button = 0; + if(ui_do_button(&no_button, "No", 0, &button, ui_draw_menu_button, 0)) + gameclient.voting->vote(-1); + + // do time left + ui_vsplit_r(&votearea, 50.0f, &votearea, &button); + char buf[256]; + str_format(buf, sizeof(buf), "%d", gameclient.voting->seconds_left()); + ui_do_label(&button, buf, 24.0f, 0); + + // do description and command + ui_vsplit_l(&votearea, 5.0f, 0, &votearea); + ui_do_label(&votearea, gameclient.voting->vote_description(), 14.0f, -1); + ui_hsplit_t(&votearea, 16.0f, 0, &votearea); + ui_do_label(&votearea, gameclient.voting->vote_command(), 10.0f, -1); + + // do bars + ui_hsplit_t(&bars, 10.0f, 0, &bars); + ui_hmargin(&bars, 5.0f, &bars); + + gameclient.voting->render_bars(bars, true); + + } + else + { + ui_do_label(&votearea, "No vote in progress", 18.0f, -1); + }*/ +} + +void MENUS::render_serverinfo(RECT main_view) +{ + // count players for server info-box + int num_players = 0; + for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) + { + SNAP_ITEM item; + snap_get_item(SNAP_CURRENT, i, &item); + + if(item.type == NETOBJTYPE_PLAYER_INFO) + { + num_players++; + } + } + + // render background + ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); + + RECT view, serverinfo, gameinfo, motd; + + float x = 0.0f; + float y = 0.0f; + + char buf[1024]; + + // set view to use for all sub-modules + ui_margin(&main_view, 10.0f, &view); + + /* serverinfo */ + ui_hsplit_t(&view, view.h/2-5.0f, &serverinfo, &motd); + ui_vsplit_l(&serverinfo, view.w/2-5.0f, &serverinfo, &gameinfo); + ui_draw_rect(&serverinfo, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); + + ui_margin(&serverinfo, 5.0f, &serverinfo); + + x = 5.0f; + y = 0.0f; + + gfx_text(0, serverinfo.x+x, serverinfo.y+y, 32, "Server info", 250.0f); + y += 32.0f+5.0f; + + mem_zero(buf, sizeof(buf)); + str_format( + buf, + sizeof(buf), + "%s\n\n" + "Address: %s\n" + "Ping: %d\n" + "Version: %s\n" + "Password: %s\n", + current_server_info.name, + config.ui_server_address, + gameclient.snap.local_info->latency, + current_server_info.version, + current_server_info.flags&1 ? "Yes" : "No" + ); + gfx_text(0, serverinfo.x+x, serverinfo.y+y, 20, buf, 250.0f); + + { + RECT button; + ui_hsplit_b(&serverinfo, 20.0f, &serverinfo, &button); + static int add_fav_button = 0; + if (ui_do_button(&add_fav_button, "Favorite", current_server_info.favorite, &button, ui_draw_checkbox, 0)) + { + if(current_server_info.favorite) + client_serverbrowse_removefavorite(current_server_info.netaddr); + else + client_serverbrowse_addfavorite(current_server_info.netaddr); + current_server_info.favorite = !current_server_info.favorite; + } + } + + /* gameinfo */ + ui_vsplit_l(&gameinfo, 10.0f, 0x0, &gameinfo); + ui_draw_rect(&gameinfo, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); + + ui_margin(&gameinfo, 5.0f, &gameinfo); + + x = 5.0f; + y = 0.0f; + + gfx_text(0, gameinfo.x+x, gameinfo.y+y, 32, "Game info", 250.0f); + y += 32.0f+5.0f; + + mem_zero(buf, sizeof(buf)); + str_format( + buf, + sizeof(buf), + "\n\n" + "Gametype: %s\n" + "Map: %s\n" + "Score limit: %d\n" + "Time limit: %d\n" + "\n" + "Players: %d/%d\n", + current_server_info.gametype, + current_server_info.map, + gameclient.snap.gameobj->score_limit, + gameclient.snap.gameobj->time_limit, + gameclient.snap.team_size[0]+gameclient.snap.team_size[1], + current_server_info.max_players + ); + gfx_text(0, gameinfo.x+x, gameinfo.y+y, 20, buf, 250.0f); + + /* motd */ + ui_hsplit_t(&motd, 10.0f, 0, &motd); + ui_draw_rect(&motd, vec4(1,1,1,0.25f), CORNER_ALL, 10.0f); + ui_margin(&motd, 5.0f, &motd); + y = 0.0f; + x = 5.0f; + gfx_text(0, motd.x+x, motd.y+y, 32, "MOTD", -1); + y += 32.0f+5.0f; + gfx_text(0, motd.x+x, motd.y+y, 16, gameclient.motd->server_motd, motd.w); +} + +void MENUS::render_servercontrol_map(RECT main_view) +{ + // draw header + RECT header, footer; + ui_hsplit_t(&main_view, 20, &header, &main_view); + ui_draw_rect(&header, vec4(1,1,1,0.25f), CORNER_T, 5.0f); + ui_do_label(&header, "Maps", 18.0f, 0); + + // draw footers + ui_hsplit_b(&main_view, 20, &main_view, &footer); + ui_draw_rect(&footer, vec4(1,1,1,0.25f), CORNER_B, 5.0f); + ui_vsplit_l(&footer, 10.0f, 0, &footer); + + // maps + ui_draw_rect(&main_view, vec4(0,0,0,0.15f), 0, 0); + RECT list = main_view; + for(int i = 0; i < gameclient.maplist->num(); i++) + { + RECT button; + ui_hsplit_t(&list, button_height, &button, &list); + + if(ui_do_button((char *)&gameclient.snap+i, "", callvote_selectedmap == i, &button, ui_draw_list_row, 0)) + callvote_selectedmap = i; + + ui_vmargin(&button, 5.0f, &button); + ui_do_label(&button, gameclient.maplist->name(i), 18.0f, -1); + } +} + +void MENUS::render_servercontrol_kick(RECT main_view) +{ + // draw header + RECT header, footer; + ui_hsplit_t(&main_view, 20, &header, &main_view); + ui_draw_rect(&header, vec4(1,1,1,0.25f), CORNER_T, 5.0f); + ui_do_label(&header, "Players", 18.0f, 0); + + // draw footers + ui_hsplit_b(&main_view, 20, &main_view, &footer); + ui_draw_rect(&footer, vec4(1,1,1,0.25f), CORNER_B, 5.0f); + ui_vsplit_l(&footer, 10.0f, 0, &footer); + + // players + ui_draw_rect(&main_view, vec4(0,0,0,0.15f), 0, 0); + RECT list = main_view; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!gameclient.snap.player_infos[i]) + continue; + + RECT button; + ui_hsplit_t(&list, button_height, &button, &list); + + if(ui_do_button((char *)&gameclient.snap+i, "", callvote_selectedplayer == i, &button, ui_draw_list_row, 0)) + callvote_selectedplayer = i; + + TEE_RENDER_INFO info = gameclient.clients[i].render_info; + info.size = button.h; + render_tee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0), vec2(button.x+button.h/2, button.y+button.h/2)); + + button.x += button.h; + ui_do_label(&button, gameclient.clients[i].name, 18.0f, -1); + } +} + +void MENUS::render_servercontrol(RECT main_view) +{ + static int control_page = 0; + + // render background + RECT temp, tabbar; + ui_vsplit_r(&main_view, 120.0f, &main_view, &tabbar); + ui_draw_rect(&main_view, color_tabbar_active, CORNER_B|CORNER_TL, 10.0f); + ui_hsplit_t(&tabbar, 50.0f, &temp, &tabbar); + ui_draw_rect(&temp, color_tabbar_active, CORNER_R, 10.0f); + + ui_hsplit_t(&main_view, 10.0f, 0, &main_view); + + RECT button; + + const char *tabs[] = {"Map", "Kick"}; + int num_tabs = (int)(sizeof(tabs)/sizeof(*tabs)); + + for(int i = 0; i < num_tabs; i++) + { + ui_hsplit_t(&tabbar, 10, &button, &tabbar); + ui_hsplit_t(&tabbar, 26, &button, &tabbar); + if(ui_do_button(tabs[i], tabs[i], control_page == i, &button, ui_draw_settings_tab_button, 0)) + { + control_page = i; + callvote_selectedplayer = -1; + callvote_selectedmap = -1; + } + } + + ui_margin(&main_view, 10.0f, &main_view); + RECT bottom; + ui_hsplit_b(&main_view, button_height + 5*2, &main_view, &bottom); + ui_hmargin(&bottom, 5.0f, &bottom); + + // render page + if(control_page == 0) + render_servercontrol_map(main_view); + else if(control_page == 1) + render_servercontrol_kick(main_view); + + + { + RECT button; + ui_vsplit_r(&bottom, 120.0f, &bottom, &button); + + static int callvote_button = 0; + if(ui_do_button(&callvote_button, "Call vote", 0, &button, ui_draw_menu_button, 0)) + { + if(control_page == 0) + { + if(callvote_selectedmap >= 0 && callvote_selectedmap < gameclient.maplist->num()) + gameclient.voting->callvote_map(gameclient.maplist->name(callvote_selectedmap)); + } + else if(control_page == 1) + { + if(callvote_selectedplayer >= 0 && callvote_selectedplayer < MAX_CLIENTS && + gameclient.snap.player_infos[callvote_selectedplayer]) + { + gameclient.voting->callvote_kick(callvote_selectedplayer); + menu_active = false; + } + } + } + } +} + diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index e835aa8f6..1386071d1 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -7,11 +7,8 @@ void VOTING::con_callvote(void *result, void *user_data) { - NETMSG_CL_CALLVOTE msg = {0}; - msg.type = console_arg_string(result, 0); - msg.value = console_arg_string(result, 1); - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + VOTING *self = (VOTING*)user_data; + self->callvote(console_arg_string(result, 0), console_arg_string(result, 1)); } void VOTING::con_vote(void *result, void *user_data) @@ -23,6 +20,27 @@ void VOTING::con_vote(void *result, void *user_data) self->vote(-1); } +void VOTING::callvote(const char *type, const char *value) +{ + NETMSG_CL_CALLVOTE msg = {0}; + msg.type = type; + msg.value = value; + msg.pack(MSGFLAG_VITAL); + client_send_msg(); +} + +void VOTING::callvote_kick(int client_id) +{ + char buf[32]; + str_format(buf, sizeof(buf), "%d", client_id); + callvote("kick", buf); +} + +void VOTING::callvote_map(const char *map) +{ + callvote("map", map); +} + void VOTING::vote(int v) { NETMSG_CL_VOTE msg = {v}; diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp index 03de629d9..78e561c7e 100644 --- a/src/game/client/components/voting.hpp +++ b/src/game/client/components/voting.hpp @@ -21,6 +21,8 @@ class VOTING : public COMPONENT char command[512]; int voted; + void callvote(const char *type, const char *value); + public: VOTING(); virtual void on_reset(); @@ -30,6 +32,9 @@ public: void render_bars(RECT bars, bool text); + void callvote_kick(int client_id); + void callvote_map(const char *map); + void vote(int v); // -1 = no, 1 = yes int seconds_left() { return (closetime - time_get())/time_freq(); } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index e16347062..2696e1854 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -24,6 +24,7 @@ #include "components/killmessages.hpp" #include "components/mapimages.hpp" #include "components/maplayers.hpp" +#include "components/maplist.hpp" #include "components/menus.hpp" #include "components/motd.hpp" #include "components/particles.hpp" @@ -62,6 +63,7 @@ static PLAYERS players; static NAMEPLATES nameplates; static ITEMS items; static MAPIMAGES mapimages; +static MAPLIST maplist; static MAPLAYERS maplayers_background(MAPLAYERS::TYPE_BACKGROUND); static MAPLAYERS maplayers_foreground(MAPLAYERS::TYPE_FOREGROUND); @@ -108,6 +110,7 @@ void GAMECLIENT::on_console_init() damageind = &::damageind; mapimages = &::mapimages; voting = &::voting; + maplist = &::maplist; // make a list of all the systems, make sure to add them in the corrent render order all.add(skins); @@ -119,6 +122,7 @@ void GAMECLIENT::on_console_init() all.add(camera); all.add(sounds); all.add(voting); + all.add(maplist); all.add(particles); // doesn't render anything, just updates all the particles all.add(&maplayers_background); // first to render @@ -489,6 +493,8 @@ static void evolve(NETOBJ_CHARACTER *character, int tick) tempcore.world = &tempworld; tempcore.read(character); //tempcore.input.direction = character->wanted_direction; + if(tick-character->tick > 50*3) + dbg_msg("", "%d -> %d = %d", character->tick, tick, tick-character->tick); while(character->tick < tick) { character->tick++; diff --git a/src/game/client/gameclient.hpp b/src/game/client/gameclient.hpp index c1e60c2c6..3ced19ce7 100644 --- a/src/game/client/gameclient.hpp +++ b/src/game/client/gameclient.hpp @@ -138,6 +138,7 @@ public: class MOTD *motd; class MAPIMAGES *mapimages; class VOTING *voting; + class MAPLIST *maplist; }; extern GAMECLIENT gameclient; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 258b29947..fb426ad6b 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -268,7 +268,6 @@ void GAMECONTEXT::send_vote_status(int cid) { if(players[i]) { - dbg_msg("", "%d %d", i, players[i]->vote); msg.total++; if(players[i]->vote > 0) msg.yes++; @@ -279,7 +278,6 @@ void GAMECONTEXT::send_vote_status(int cid) } } - dbg_msg("", "%d %d %d %d", msg.yes, msg.no, msg.pass, msg.total); msg.pack(MSGFLAG_VITAL); server_send_msg(cid); diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp index f7fad64ae..200e2c86b 100644 --- a/src/game/server/hooks.cpp +++ b/src/game/server/hooks.cpp @@ -97,6 +97,7 @@ void mods_client_drop(int client_id) game.players[client_id]->on_disconnect(); (void) game.controller->check_team_balance(); delete game.players[client_id]; + game.players[client_id] = 0; } void mods_message(int msgtype, int client_id) @@ -150,11 +151,36 @@ void mods_message(int msgtype, int client_id) NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg; if(str_comp_nocase(msg->type, "map") == 0) { + if(!config.sv_vote_map) + { + game.send_chat(-1, client_id, "Server does not allow voting on map"); + return; + } + str_format(chatmsg, sizeof(chatmsg), "Vote called to change map to '%s'", msg->value); str_format(desc, sizeof(desc), "Change map to '%s'", msg->value); str_format(cmd, sizeof(cmd), "sv_map %s", msg->value); } - + else if(str_comp_nocase(msg->type, "kick") == 0) + { + if(!config.sv_vote_kick) + { + game.send_chat(-1, client_id, "Server does not allow voting to kick players"); + return; + } + + int kick_id = atoi(msg->value); + if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id]) + { + game.send_chat(-1, client_id, "Invalid client id to kick"); + return; + } + + str_format(chatmsg, sizeof(chatmsg), "Vote called to kick '%s'", server_clientname(kick_id)); + str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id)); + str_format(cmd, sizeof(cmd), "kick %d", kick_id); + } + if(cmd[0]) { game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg); @@ -257,10 +283,18 @@ void mods_message(int msgtype, int client_id) // send tuning parameters to client send_tuning_params(client_id); + // send maps to the client + { + NETMSG_SV_MAPLIST m; + m.names = config.sv_maplist; + m.pack(MSGFLAG_VITAL); + server_send_msg(client_id); + } + // NETMSG_SV_READYTOENTER m; m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH); - server_send_msg(client_id); + server_send_msg(client_id); } game.send_info(client_id, -1); diff --git a/src/game/variables.hpp b/src/game/variables.hpp index 5154e8ac9..edc01635c 100644 --- a/src/game/variables.hpp +++ b/src/game/variables.hpp @@ -51,7 +51,8 @@ MACRO_CONFIG_INT(ui_color_alpha, 228, 0, 255) MACRO_CONFIG_INT(sv_warmup, 0, 0, 0) MACRO_CONFIG_STR(sv_motd, 900, "") MACRO_CONFIG_INT(sv_teamdamage, 0, 0, 1) -MACRO_CONFIG_STR(sv_maprotation, 512, "") +MACRO_CONFIG_STR(sv_maprotation, 768, "") +MACRO_CONFIG_STR(sv_maplist, 768, "") MACRO_CONFIG_INT(sv_rounds_per_map, 1, 1, 100) MACRO_CONFIG_INT(sv_powerups, 1, 0, 1) MACRO_CONFIG_INT(sv_scorelimit, 20, 0, 1000) @@ -62,3 +63,8 @@ MACRO_CONFIG_INT(sv_spamprotection, 1, 0, 1) MACRO_CONFIG_INT(sv_spectator_slots, 0, 0, 12) MACRO_CONFIG_INT(sv_teambalance_time, 1, 0, 1000) + +MACRO_CONFIG_INT(sv_vote_map, 1, 0, 1) +MACRO_CONFIG_INT(sv_vote_kick, 1, 0, 1) +MACRO_CONFIG_INT(sv_vote_scorelimit, 0, 0, 1) +MACRO_CONFIG_INT(sv_vote_timelimit, 0, 0, 1)