1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-26 00:04:43 +01:00

Merge pull request #3777 from IntelOrca/feature/mpinfo

Add information tab to multiplayer window
This commit is contained in:
Ted John
2016-05-31 17:16:23 +01:00
5 changed files with 269 additions and 24 deletions

View File

@@ -4175,6 +4175,10 @@ STR_5863 :{SMALLFONT}{BLACK}Only allow players with known keys to join.
STR_5864 :This server only allows whitelisted players to connect.
STR_5865 :Log chat history
STR_5866 :{SMALLFONT}{BLACK}Logs all chat history to files in your user directory.
STR_5867 :{WINDOW_COLOUR_2}Provider Name: {BLACK}{STRING}
STR_5868 :{WINDOW_COLOUR_2}Provider E-mail: {BLACK}{STRING}
STR_5869 :{WINDOW_COLOUR_2}Provider Website: {BLACK}{STRING}
STR_5870 :{SMALLFONT}{BLACK}Show server information
#############
# Scenarios #

View File

@@ -2639,6 +2639,10 @@ enum {
STR_MULTIPLAYER_UNKNOWN_KEY_DISALLOWED = 5864,
STR_LOG_CHAT = 5865,
STR_LOG_CHAT_TIP = 5866,
STR_PROVIDER_NAME = 5867,
STR_PROVIDER_EMAIL = 5868,
STR_PROVIDER_WEBSITE = 5869,
STR_SHOW_SERVER_INFO_TIP = 5870,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768

View File

@@ -111,6 +111,7 @@ Network::Network()
client_command_handlers[NETWORK_COMMAND_SHOWERROR] = &Network::Client_Handle_SHOWERROR;
client_command_handlers[NETWORK_COMMAND_GROUPLIST] = &Network::Client_Handle_GROUPLIST;
client_command_handlers[NETWORK_COMMAND_EVENT] = &Network::Client_Handle_EVENT;
client_command_handlers[NETWORK_COMMAND_GAMEINFO] = &Network::Client_Handle_GAMEINFO;
client_command_handlers[NETWORK_COMMAND_TOKEN] = &Network::Client_Handle_TOKEN;
server_command_handlers.resize(NETWORK_COMMAND_MAX, 0);
server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH;
@@ -142,6 +143,12 @@ bool Network::Init()
#endif
status = NETWORK_STATUS_READY;
ServerName = std::string();
ServerDescription = std::string();
ServerProviderName = std::string();
ServerProviderEmail = std::string();
ServerProviderWebsite = std::string();
return true;
}
@@ -303,6 +310,12 @@ bool Network::BeginServer(unsigned short port, const char* address)
return false;
}
ServerName = gConfigNetwork.server_name;
ServerDescription = gConfigNetwork.server_description;
ServerProviderName = gConfigNetwork.provider_name;
ServerProviderEmail = gConfigNetwork.provider_email;
ServerProviderWebsite = gConfigNetwork.provider_website;
cheats_reset();
LoadGroups();
BeginChatLog();
@@ -1487,6 +1500,9 @@ void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& p
{
packet >> (uint32&)connection.AuthStatus >> (uint8&)player_id;
switch(connection.AuthStatus) {
case NETWORK_AUTH_OK:
Client_Send_GAMEINFO();
break;
case NETWORK_AUTH_BADNAME:
connection.SetLastDisconnectReason(STR_MULTIPLAYER_BAD_PLAYER_NAME);
shutdown(connection.Socket, SHUT_RDWR);
@@ -1518,6 +1534,8 @@ void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& p
shutdown(connection.Socket, SHUT_RDWR);
break;
default:
connection.SetLastDisconnectReason(STR_MULTIPLAYER_INCORRECT_SOFTWARE_VERSION);
shutdown(connection.Socket, SHUT_RDWR);
break;
}
}
@@ -1913,6 +1931,39 @@ void Network::Client_Handle_EVENT(NetworkConnection& connection, NetworkPacket&
}
}
void Network::Client_Send_GAMEINFO()
{
log_verbose("requesting gameinfo");
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_GAMEINFO;
server_connection.QueuePacket(std::move(packet));
}
std::string json_stdstring_value(const json_t * string)
{
const char * cstr = json_string_value(string);
return cstr == nullptr ? std::string() : std::string(cstr);
}
void Network::Client_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet)
{
const char * jsonString = packet.ReadString();
json_error_t error;
json_t *root = json_loads(jsonString, 0, &error);
ServerName = json_stdstring_value(json_object_get(root, "name"));
ServerDescription = json_stdstring_value(json_object_get(root, "description"));
json_t *jsonProvider = json_object_get(root, "provider");
if (jsonProvider != nullptr) {
ServerProviderName = json_stdstring_value(json_object_get(root, "name"));
ServerProviderEmail = json_stdstring_value(json_object_get(root, "email"));
ServerProviderWebsite = json_stdstring_value(json_object_get(root, "website"));
}
json_decref(root);
}
int network_init()
{
return gNetwork.Init();
@@ -2394,6 +2445,12 @@ static void network_get_keymap_path(utf8 *buffer, size_t bufferSize)
Path::Append(buffer, bufferSize, "keymappings.json");
}
const utf8 * network_get_server_name() { return gNetwork.ServerName.c_str(); }
const utf8 * network_get_server_description() { return gNetwork.ServerDescription.c_str(); }
const utf8 * network_get_server_provider_name() { return gNetwork.ServerProviderName.c_str(); }
const utf8 * network_get_server_provider_email() { return gNetwork.ServerProviderEmail.c_str(); }
const utf8 * network_get_server_provider_website() { return gNetwork.ServerProviderWebsite.c_str(); }
#else
int network_get_mode() { return NETWORK_MODE_NONE; }
int network_get_status() { return NETWORK_STATUS_NONE; }
@@ -2441,4 +2498,9 @@ void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }
int network_get_current_player_group_index() { return 0; }
void network_append_chat_log(const utf8 *text) { }
const utf8 * network_get_server_name() { return nullptr; }
const utf8 * network_get_server_description() { return nullptr; }
const utf8 * network_get_server_provider_name() { return nullptr; }
const utf8 * network_get_server_provider_email() { return nullptr; }
const utf8 * network_get_server_provider_website() { return nullptr; }
#endif /* DISABLE_NETWORK */

View File

@@ -144,6 +144,7 @@ public:
void Server_Send_GROUPLIST(NetworkConnection& connection);
void Server_Send_EVENT_PLAYER_JOINED(const char *playerName);
void Server_Send_EVENT_PLAYER_DISCONNECTED(const char *playerName, const char *reason);
void Client_Send_GAMEINFO();
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
std::vector<std::unique_ptr<NetworkGroup>> group_list;
@@ -151,6 +152,12 @@ public:
std::vector<uint8> challenge;
NetworkUserManager _userManager;
std::string ServerName;
std::string ServerDescription;
std::string ServerProviderName;
std::string ServerProviderEmail;
std::string ServerProviderWebsite;
private:
bool ProcessConnection(NetworkConnection& connection);
void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet);
@@ -226,6 +233,7 @@ private:
void Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet);
void Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPacket& packet);
@@ -292,6 +300,11 @@ void network_set_password(const char* password);
void network_print_error();
void network_append_chat_log(const utf8 *text);
const utf8 * network_get_server_name();
const utf8 * network_get_server_description();
const utf8 * network_get_server_provider_name();
const utf8 * network_get_server_provider_email();
const utf8 * network_get_server_provider_website();
#ifdef __cplusplus
}

View File

@@ -25,6 +25,7 @@
#include "dropdown.h"
enum {
WINDOW_MULTIPLAYER_PAGE_INFORMATION,
WINDOW_MULTIPLAYER_PAGE_PLAYERS,
WINDOW_MULTIPLAYER_PAGE_GROUPS,
WINDOW_MULTIPLAYER_PAGE_OPTIONS
@@ -38,10 +39,11 @@ enum WINDOW_MULTIPLAYER_WIDGET_IDX {
WIDX_TAB1,
WIDX_TAB2,
WIDX_TAB3,
WIDX_TAB4,
WIDX_LIST = 7,
WIDX_LIST = 8,
WIDX_DEFAULT_GROUP = 7,
WIDX_DEFAULT_GROUP = 8,
WIDX_DEFAULT_GROUP_DROPDOWN,
WIDX_ADD_GROUP,
WIDX_REMOVE_GROUP,
@@ -50,7 +52,7 @@ enum WINDOW_MULTIPLAYER_WIDGET_IDX {
WIDX_SELECTED_GROUP_DROPDOWN,
WIDX_PERMISSIONS_LIST,
WIDX_LOG_CHAT_CHECKBOX = 7,
WIDX_LOG_CHAT_CHECKBOX = 8,
WIDX_KNOWN_KEYS_ONLY_CHECKBOX,
};
@@ -59,10 +61,16 @@ enum WINDOW_MULTIPLAYER_WIDGET_IDX {
{ WWT_CAPTION, 0, 1, 338, 1, 14, STR_MULTIPLAYER, STR_WINDOW_TITLE_TIP }, /* title bar */ \
{ WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, /* close x button */ \
{ WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, /* content panel */ \
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_SHOW_SERVER_INFO_TIP }, /* tab */ \
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_PLAYERS_TIP }, /* tab */ \
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_GROUPS_TIP }, /* tab */ \
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_OPTIONS_TIP } /* tab */ \
static rct_widget window_multiplayer_information_widgets[] = {
MAIN_MULTIPLAYER_WIDGETS,
{ WIDGETS_END }
};
static rct_widget window_multiplayer_players_widgets[] = {
MAIN_MULTIPLAYER_WIDGETS,
{ WWT_SCROLL, 1, 3, 336, 60, 236, 2, STR_NONE }, // list
@@ -90,19 +98,27 @@ static rct_widget window_multiplayer_options_widgets[] = {
};
static rct_widget *window_multiplayer_page_widgets[] = {
window_multiplayer_information_widgets,
window_multiplayer_players_widgets,
window_multiplayer_groups_widgets,
window_multiplayer_options_widgets
};
const uint64 window_multiplayer_page_enabled_widgets[] = {
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_DEFAULT_GROUP) | (1 << WIDX_DEFAULT_GROUP_DROPDOWN) | (1 << WIDX_ADD_GROUP) | (1 << WIDX_REMOVE_GROUP) | (1 << WIDX_RENAME_GROUP) | (1 << WIDX_SELECTED_GROUP) | (1 << WIDX_SELECTED_GROUP_DROPDOWN),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_LOG_CHAT_CHECKBOX) | (1 << WIDX_KNOWN_KEYS_ONLY_CHECKBOX),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_DEFAULT_GROUP) | (1 << WIDX_DEFAULT_GROUP_DROPDOWN) | (1 << WIDX_ADD_GROUP) | (1 << WIDX_REMOVE_GROUP) | (1 << WIDX_RENAME_GROUP) | (1 << WIDX_SELECTED_GROUP) | (1 << WIDX_SELECTED_GROUP_DROPDOWN),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_LOG_CHAT_CHECKBOX) | (1 << WIDX_KNOWN_KEYS_ONLY_CHECKBOX),
};
static uint8 _selectedGroup = 0;
static void window_multiplayer_information_mouseup(rct_window *w, int widgetIndex);
static void window_multiplayer_information_resize(rct_window *w);
static void window_multiplayer_information_update(rct_window *w);
static void window_multiplayer_information_invalidate(rct_window *w);
static void window_multiplayer_information_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex);
static void window_multiplayer_players_resize(rct_window *w);
static void window_multiplayer_players_update(rct_window *w);
@@ -132,6 +148,37 @@ static void window_multiplayer_options_update(rct_window *w);
static void window_multiplayer_options_invalidate(rct_window *w);
static void window_multiplayer_options_paint(rct_window *w, rct_drawpixelinfo *dpi);
static rct_window_event_list window_multiplayer_information_events = {
NULL,
window_multiplayer_information_mouseup,
window_multiplayer_information_resize,
NULL,
NULL,
NULL,
window_multiplayer_information_update,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
window_multiplayer_information_invalidate,
window_multiplayer_information_paint,
NULL
};
static rct_window_event_list window_multiplayer_players_events = {
NULL,
window_multiplayer_players_mouseup,
@@ -226,35 +273,35 @@ static rct_window_event_list window_multiplayer_options_events = {
};
static rct_window_event_list *window_multiplayer_page_events[] = {
&window_multiplayer_information_events,
&window_multiplayer_players_events,
&window_multiplayer_groups_events,
&window_multiplayer_options_events
};
static const int window_multiplayer_animation_divisor[] = { 4, 2, 2 };
static const int window_multiplayer_animation_frames[] = { 8, 7, 4 };
static const int window_multiplayer_animation_divisor[] = { 4, 4, 2, 2 };
static const int window_multiplayer_animation_frames[] = { 8, 8, 7, 4 };
static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi);
static void window_multiplayer_set_page(rct_window* w, int page);
static bool _windowInformationSizeDirty;
static rct_xy16 _windowInformationSize;
void window_multiplayer_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_class(WC_MULTIPLAYER);
if (window != NULL)
return;
window = window_create_auto_pos(320, 144, &window_multiplayer_players_events, WC_MULTIPLAYER, WF_10 | WF_RESIZABLE);
window_multiplayer_set_page(window, WINDOW_MULTIPLAYER_PAGE_PLAYERS);
window->page = WINDOW_MULTIPLAYER_PAGE_PLAYERS;
window->list_information_type = 0;
rct_window *window = window_bring_to_front_by_class(WC_MULTIPLAYER);
if (window == NULL) {
window = window_create_auto_pos(320, 144, &window_multiplayer_players_events, WC_MULTIPLAYER, WF_10 | WF_RESIZABLE);
window_multiplayer_set_page(window, WINDOW_MULTIPLAYER_PAGE_INFORMATION);
}
}
static void window_multiplayer_set_page(rct_window* w, int page){
static void window_multiplayer_set_page(rct_window* w, int page)
{
_windowInformationSizeDirty = true;
w->page = page;
w->frame_no = 0;
w->no_list_items = 0;
@@ -322,6 +369,115 @@ static void window_multiplayer_groups_show_group_dropdown(rct_window *w, rct_wid
}
}
#pragma region Information page
static void window_multiplayer_information_mouseup(rct_window *w, int widgetIndex)
{
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_TAB1:
case WIDX_TAB2:
case WIDX_TAB3:
case WIDX_TAB4:
if (w->page != widgetIndex - WIDX_TAB1) {
window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1);
}
break;
}
}
static rct_xy16 window_multiplayer_information_get_size()
{
if (!_windowInformationSizeDirty) {
return _windowInformationSize;
}
int width = 300;
int height = 110;
char * buffer = gConfigNetwork.server_description;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
int numLines, fontSpriteBase;
gfx_wrap_string(buffer, width, &numLines, &fontSpriteBase);
int lineHeight = font_get_line_height(fontSpriteBase);
height += (numLines + 1) * lineHeight;
_windowInformationSizeDirty = false;
_windowInformationSize = (rct_xy16){ width, height };
return _windowInformationSize;
}
static void window_multiplayer_information_resize(rct_window *w)
{
rct_xy16 size = window_multiplayer_information_get_size();
window_set_resize(w, size.x, size.y, size.x, size.y);
}
static void window_multiplayer_information_update(rct_window *w)
{
w->frame_no++;
widget_invalidate(w, WIDX_TAB1 + w->page);
}
static void window_multiplayer_information_invalidate(rct_window *w)
{
colour_scheme_update(w);
window_multiplayer_set_pressed_tab(w);
window_multiplayer_anchor_border_widgets(w);
window_align_tabs(w, WIDX_TAB1, WIDX_TAB4);
}
static void window_multiplayer_information_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
window_multiplayer_draw_tab_images(w, dpi);
rct_drawpixelinfo clippedDPI;
if (clip_drawpixelinfo(&clippedDPI, dpi, w->x, w->y, w->width, w->height)) {
dpi = &clippedDPI;
int x = 3;
int y = 50;
int width = w->width - 6;
const utf8 * name = network_get_server_name();
{
gfx_draw_string_left_wrapped(dpi, (void*)&name, x, y, width, STR_STRING, w->colours[1]);
y += 11;
}
y += 3;
const utf8 * description = network_get_server_description();
if (!str_is_null_or_empty(description)) {
gfx_draw_string_left_wrapped(dpi, (void*)&description, x, y, width, STR_STRING, w->colours[1]);
y += 11;
}
y += 8;
const utf8 * providerName = network_get_server_provider_name();
if (!str_is_null_or_empty(providerName)) {
gfx_draw_string_left(dpi, STR_PROVIDER_NAME, (void*)&providerName, 0, x, y);
y += 11;
}
const utf8 * providerEmail = network_get_server_provider_email();
if (!str_is_null_or_empty(providerEmail)) {
gfx_draw_string_left(dpi, STR_PROVIDER_EMAIL, (void*)&providerEmail, 0, x, y);
y += 11;
}
const utf8 * providerWebsite = network_get_server_provider_website();
if (!str_is_null_or_empty(providerWebsite)) {
gfx_draw_string_left(dpi, STR_PROVIDER_WEBSITE, (void*)&providerWebsite, 0, x, y);
}
}
}
#pragma endregion
#pragma region Players page
static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex)
@@ -333,6 +489,7 @@ static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex)
case WIDX_TAB1:
case WIDX_TAB2:
case WIDX_TAB3:
case WIDX_TAB4:
if (w->page != widgetIndex - WIDX_TAB1) {
window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1);
}
@@ -410,7 +567,7 @@ static void window_multiplayer_players_invalidate(rct_window *w)
window_multiplayer_anchor_border_widgets(w);
window_multiplayer_players_widgets[WIDX_LIST].right = w->width - 4;
window_multiplayer_players_widgets[WIDX_LIST].bottom = w->height - 0x0F;
window_align_tabs(w, WIDX_TAB1, WIDX_TAB3);
window_align_tabs(w, WIDX_TAB1, WIDX_TAB4);
}
static void window_multiplayer_players_paint(rct_window *w, rct_drawpixelinfo *dpi)
@@ -514,6 +671,7 @@ static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex)
case WIDX_TAB1:
case WIDX_TAB2:
case WIDX_TAB3:
case WIDX_TAB4:
if (w->page != widgetIndex - WIDX_TAB1) {
window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1);
}
@@ -639,11 +797,12 @@ static void window_multiplayer_groups_text_input(rct_window *w, int widgetIndex,
static void window_multiplayer_groups_invalidate(rct_window *w)
{
colour_scheme_update(w);
window_multiplayer_set_pressed_tab(w);
window_multiplayer_anchor_border_widgets(w);
window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].right = w->width - 4;
window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].bottom = w->height - 0x0F;
window_align_tabs(w, WIDX_TAB1, WIDX_TAB3);
window_align_tabs(w, WIDX_TAB1, WIDX_TAB4);
// select other group if one is removed
while (network_get_group_index(_selectedGroup) == -1 && _selectedGroup > 0) {
@@ -754,6 +913,7 @@ static void window_multiplayer_options_mouseup(rct_window *w, int widgetIndex)
case WIDX_TAB1:
case WIDX_TAB2:
case WIDX_TAB3:
case WIDX_TAB4:
if (w->page != widgetIndex - WIDX_TAB1) {
window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1);
}
@@ -782,9 +942,10 @@ static void window_multiplayer_options_update(rct_window *w)
static void window_multiplayer_options_invalidate(rct_window *w)
{
colour_scheme_update(w);
window_multiplayer_set_pressed_tab(w);
window_multiplayer_anchor_border_widgets(w);
window_align_tabs(w, WIDX_TAB1, WIDX_TAB3);
window_align_tabs(w, WIDX_TAB1, WIDX_TAB4);
if (network_get_mode() == NETWORK_MODE_CLIENT) {
w->widgets[WIDX_KNOWN_KEYS_ONLY_CHECKBOX].type = WWT_EMPTY;
@@ -821,6 +982,7 @@ static void window_multiplayer_draw_tab_image(rct_window *w, rct_drawpixelinfo *
static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi)
{
window_multiplayer_draw_tab_image(w, dpi, WINDOW_MULTIPLAYER_PAGE_INFORMATION, SPR_TAB_KIOSKS_AND_FACILITIES_0);
window_multiplayer_draw_tab_image(w, dpi, WINDOW_MULTIPLAYER_PAGE_PLAYERS, SPR_TAB_GUESTS_0);
window_multiplayer_draw_tab_image(w, dpi, WINDOW_MULTIPLAYER_PAGE_GROUPS, SPR_TAB_STAFF_OPTIONS_0);
window_multiplayer_draw_tab_image(w, dpi, WINDOW_MULTIPLAYER_PAGE_OPTIONS, SPR_TAB_GEARS_0);