diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 144bf8a857..361b08dea1 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3836,3 +3836,9 @@ STR_5494 :Type the message you would like to send. STR_5495 :Player List STR_5496 :Player: STR_5497 :Ping: +STR_5498 :Server List +STR_5499 :Player Name: +STR_5500 :Add Server +STR_5501 :Start Server +STR_5502 :Multiplayer +STR_5503 :Enter hostname or IP address: diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 84ea401ec4..956fd8efe2 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -100,6 +100,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 49d011038e..8321dae4a5 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -519,6 +519,9 @@ Source\Interface + + Source\Windows + diff --git a/src/interface/window.h b/src/interface/window.h index 080c6c201a..a60cace19f 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -449,6 +449,7 @@ enum { WC_CHAT_HOST = 124, WC_PLAYER_LIST = 125, WC_NETWORK_STATUS = 126, + WC_SERVER_LIST = 127, // Only used for colour schemes WC_STAFF = 220, @@ -615,6 +616,7 @@ void window_sign_small_open(rct_windownumber number); void window_cheats_open(); void window_player_list_open(); void window_network_status_open(const char* text); +void window_server_list_open(); void window_research_open(); void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dpi, int baseWidgetIndex); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 8fbbc0d93e..f9cc1abcfb 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2035,6 +2035,12 @@ enum { STR_PLAYER_LIST = 5495, STR_PLAYER = 5496, STR_PING = 5497, + STR_SERVER_LIST = 5498, + STR_PLAYER_NAME = 5499, + STR_ADD_SERVER = 5500, + STR_START_SERVER = 5501, + STR_MULTIPLAYER = 5502, + STR_ENTER_HOSTNAME_OR_IP_ADDRESS = 5503, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 diff --git a/src/windows/clear_scenery.c b/src/windows/clear_scenery.c index 819340bc07..fcbb6a50c5 100644 --- a/src/windows/clear_scenery.c +++ b/src/windows/clear_scenery.c @@ -139,8 +139,6 @@ static void window_clear_scenery_close(rct_window *w) */ static void window_clear_scenery_mouseup(rct_window *w, int widgetIndex) { - int limit; - switch (widgetIndex) { case WIDX_CLOSE: window_close(w); diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 26e05f526e..054b3918a2 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -1,3 +1,4 @@ + /***************************************************************************** * Copyright (c) 2014 Dániel Tar * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. diff --git a/src/windows/server_list.c b/src/windows/server_list.c new file mode 100644 index 0000000000..c9716da512 --- /dev/null +++ b/src/windows/server_list.c @@ -0,0 +1,338 @@ +/***************************************************************************** +* Copyright (c) 2014 Ted John +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#include "../interface/themes.h" +#include "../interface/widget.h" +#include "../interface/window.h" +#include "../localisation/localisation.h" +#include "../network/network.h" +#include "../sprites.h" + +#define WWIDTH_MIN 500 +#define WHEIGHT_MIN 300 +#define WWIDTH_MAX 1200 +#define WHEIGHT_MAX 800 +#define ITEM_HEIGHT (3 + 11 + 1 + 11 + 3) + +typedef struct { + char *address; + utf8 *name; + utf8 *description; +} saved_server; + +char _playerName[64] = "Player"; +saved_server *_savedServers = NULL; +int _numSavedServers = 0; + +enum { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_PLAYER_NAME_INPUT, + WIDX_LIST, + WIDX_ADD_SERVER, + WIDX_START_SERVER +}; + +enum { + WIDX_LIST_REMOVE, + WIDX_LIST_SPECTATE +}; + +static rct_widget window_server_list_widgets[] = { + { WWT_FRAME, 0, 0, 340, 0, 90, 0xFFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 338, 1, 14, STR_SERVER_LIST, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_TEXT_BOX, 1, 100, 344, 20, 31, (uint32)_playerName, STR_NONE }, // player name text box + { WWT_SCROLL, 1, 6, 337, 37, 50, STR_NONE, STR_NONE }, // server list + { WWT_DROPDOWN_BUTTON, 1, 6, 106, 53, 64, STR_ADD_SERVER, STR_NONE }, // add server button + { WWT_DROPDOWN_BUTTON, 1, 112, 212, 53, 64, STR_START_SERVER, STR_NONE }, // start server button + { WIDGETS_END }, +}; + +static void window_server_list_mouseup(rct_window *w, int widgetIndex); +static void window_server_list_resize(rct_window *w); +static void window_server_list_update(rct_window *w); +static void window_server_list_scroll_getsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_server_list_scroll_mousedown(rct_window *w, int scrollIndex, int x, int y); +static void window_server_list_scroll_mouseover(rct_window *w, int scrollIndex, int x, int y); +static void window_server_list_textinput(rct_window *w, int widgetIndex, char *text); +static void window_server_list_invalidate(rct_window *w); +static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi); +static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); + +static void server_list_get_item_button(int buttonIndex, int x, int y, int width, int *outX, int *outY); + +static rct_window_event_list window_server_list_events = { + NULL, + window_server_list_mouseup, + window_server_list_resize, + NULL, + NULL, + NULL, + window_server_list_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_server_list_scroll_getsize, + window_server_list_scroll_mousedown, + NULL, + window_server_list_scroll_mouseover, + window_server_list_textinput, + NULL, + NULL, + NULL, + NULL, + NULL, + window_server_list_invalidate, + window_server_list_paint, + window_server_list_scrollpaint +}; + +static int _hoverButtonIndex = -1; + +void window_server_list_open() +{ + rct_window* window; + + // Check if window is already open + window = window_bring_to_front_by_class(WC_SERVER_LIST); + if (window != NULL) + return; + + window = window_create_centred(WWIDTH_MIN, WHEIGHT_MIN, &window_server_list_events, WC_SERVER_LIST, WF_10 | WF_RESIZABLE); + + window->widgets = window_server_list_widgets; + window->enabled_widgets = ( + (1 << WIDX_CLOSE) | + (1 << WIDX_PLAYER_NAME_INPUT) | + (1 << WIDX_ADD_SERVER) | + (1 << WIDX_START_SERVER) + ); + window_init_scroll_widgets(window); + window->no_list_items = 0; + window->selected_list_item = -1; + window->frame_no = 0; + window->min_width = 320; + window->min_height = 90; + window->max_width = window->min_width; + window->max_height = window->min_height; + + window->page = 0; + window->list_information_type = 0; + window->colours[0] = 1; + window->colours[1] = 26; + window->colours[2] = 26; + + window_set_resize(window, WWIDTH_MIN, WHEIGHT_MIN, WWIDTH_MAX, WHEIGHT_MAX); + + _numSavedServers = 2; + _savedServers = malloc(_numSavedServers * sizeof(saved_server)); + _savedServers[0].address = "127.0.0.1"; + _savedServers[0].name = "localhost"; + _savedServers[0].description = "Home sweet home."; + _savedServers[1].address = "81.124.111.146:12428"; + _savedServers[1].name = "Another server, #1"; + _savedServers[1].description = "Another server..."; + window->no_list_items = _numSavedServers; +} + +static void window_server_list_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_PLAYER_NAME_INPUT: + window_start_textbox(w, widgetIndex, 1170, (uint32)_playerName, 63); + break; + case WIDX_ADD_SERVER: + window_text_input_open(w, widgetIndex, STR_ADD_SERVER, STR_ENTER_HOSTNAME_OR_IP_ADDRESS, STR_NONE, 0, 128); + break; + } +} + +static void window_server_list_resize(rct_window *w) +{ + window_set_resize(w, WWIDTH_MIN, WHEIGHT_MIN, WWIDTH_MAX, WHEIGHT_MAX); +} + +static void window_server_list_update(rct_window *w) +{ + if (gCurrentTextBox.window.classification == w->classification && gCurrentTextBox.window.number == w->number) { + window_update_textbox_caret(); + widget_invalidate(w, WIDX_PLAYER_NAME_INPUT); + } +} + +static void window_server_list_scroll_getsize(rct_window *w, int scrollIndex, int *width, int *height) +{ + *width = 0; + *height = w->no_list_items * ITEM_HEIGHT; +} + +static void window_server_list_scroll_mousedown(rct_window *w, int scrollIndex, int x, int y) +{ + if (w->selected_list_item == -1) return; + + switch (_hoverButtonIndex) { + case WIDX_LIST_REMOVE: + break; + case WIDX_LIST_SPECTATE: + break; + default: + // Join + break; + } +} + +static void window_server_list_scroll_mouseover(rct_window *w, int scrollIndex, int x, int y) +{ + // Item + int index = y / ITEM_HEIGHT; + if (index < 0 || index >= w->no_list_items) { + index = -1; + } + + int hoverButtonIndex = -1; + if (index != -1) { + int width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left; + int sy = index * ITEM_HEIGHT; + for (int i = 0; i < 2; i++) { + int bx, by; + + server_list_get_item_button(i, 0, sy, width, &bx, &by); + if (x >= bx && y >= by && x < bx + 24 && y < by + 24) { + hoverButtonIndex = i; + break; + } + } + } + + if (w->selected_list_item != index || _hoverButtonIndex != hoverButtonIndex) { + w->selected_list_item = index; + _hoverButtonIndex = hoverButtonIndex; + window_invalidate(w); + } +} + +static void window_server_list_textinput(rct_window *w, int widgetIndex, char *text) +{ + if (widgetIndex != WIDX_PLAYER_NAME_INPUT || text == NULL) + return; + + if (strcmp(_playerName, text) == 0) + return; + + if (strlen(text) == 0) { + memset(_playerName, 0, sizeof(_playerName)); + } else { + memset(_playerName, 0, sizeof(_playerName)); + strcpy(_playerName, text); + } + + widget_invalidate(w, WIDX_PLAYER_NAME_INPUT); +} + +static void window_server_list_invalidate(rct_window *w) +{ + window_server_list_widgets[WIDX_BACKGROUND].right = w->width - 1; + window_server_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1; + window_server_list_widgets[WIDX_TITLE].right = w->width - 2; + window_server_list_widgets[WIDX_CLOSE].left = w->width - 2 - 11; + window_server_list_widgets[WIDX_CLOSE].right = w->width - 2 - 11 + 10; + + window_server_list_widgets[WIDX_PLAYER_NAME_INPUT].right = w->width - 6; + window_server_list_widgets[WIDX_LIST].left = 6; + window_server_list_widgets[WIDX_LIST].right = w->width - 6; + window_server_list_widgets[WIDX_LIST].bottom = w->height - 6 - 11 - 6; + window_server_list_widgets[WIDX_ADD_SERVER].top = w->height - 6 - 11; + window_server_list_widgets[WIDX_ADD_SERVER].bottom = w->height - 6; + window_server_list_widgets[WIDX_START_SERVER].top = w->height - 6 - 11; + window_server_list_widgets[WIDX_START_SERVER].bottom = w->height - 6; +} + +static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + + gfx_draw_string_left(dpi, STR_PLAYER_NAME, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_PLAYER_NAME_INPUT].top); +} + +static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) +{ + uint32 colour; + int bx, by; + + colour = ((char*)0x0141FC48)[w->colours[1] * 8]; + colour = (colour << 24) | (colour << 16) | (colour << 8) | colour; + gfx_clear(dpi, colour); + + int width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left; + + int y = 0; + for (int i = 0; i < w->no_list_items; i++) { + if (y >= dpi->y + dpi->height) continue; + // if (y + ITEM_HEIGHT < dpi->y) continue; + + saved_server *serverDetails = &_savedServers[i]; + bool highlighted = i == w->selected_list_item; + + // Draw hover highlight + if (highlighted) { + gfx_fill_rect(dpi, 0, y, width, y + ITEM_HEIGHT, 0x02000031); + } + + // Draw server information + if (highlighted) { + gfx_draw_string(dpi, serverDetails->address, w->colours[1], 3, y + 3); + } else { + gfx_draw_string(dpi, serverDetails->name, w->colours[1], 3, y + 3); + } + gfx_draw_string(dpi, serverDetails->description, w->colours[1], 3, y + 14); + + // Draw delete server button + server_list_get_item_button(0, 0, y, width, &bx, &by); + if (highlighted && _hoverButtonIndex == WIDX_LIST_REMOVE) { + gfx_fill_rect_inset(dpi, bx, by, bx + 24, by + 24, w->colours[1], 0); + } + gfx_draw_sprite(dpi, SPR_DEMOLISH, bx, by, 0); + + // Draw spectate server button + server_list_get_item_button(1, 0, y, width, &bx, &by); + if (highlighted && _hoverButtonIndex == WIDX_LIST_SPECTATE) { + gfx_fill_rect_inset(dpi, bx, by, bx + 24, by + 24, w->colours[1], 0); + } + gfx_draw_sprite(dpi, SPR_LOCATE, bx, by, 0); + + y += ITEM_HEIGHT; + } +} + +static void server_list_get_item_button(int buttonIndex, int x, int y, int width, int *outX, int *outY) +{ + *outX = width - 3 - 36 - (30 * buttonIndex); + *outY = y + 2; +} diff --git a/src/windows/title_menu.c b/src/windows/title_menu.c index 9ef748705d..2bb2c004f1 100644 --- a/src/windows/title_menu.c +++ b/src/windows/title_menu.c @@ -35,6 +35,7 @@ enum { WIDX_CONTINUE_SAVED_GAME, WIDX_SHOW_TUTORIAL, WIDX_GAME_TOOLS, + WIDX_MULTIPLAYER }; static rct_widget window_title_menu_widgets[] = { @@ -42,6 +43,7 @@ static rct_widget window_title_menu_widgets[] = { { WWT_IMGBTN, 2, 82, 163, 0, 81, SPR_MENU_LOAD_GAME, STR_CONTINUE_SAVED_GAME_TIP }, { WWT_IMGBTN, 2, 164, 245, 0, 81, SPR_MENU_TUTORIAL, STR_SHOW_TUTORIAL_TIP }, { WWT_IMGBTN, 2, 246, 327, 0, 81, SPR_MENU_TOOLBOX, STR_GAME_TOOLS }, + { WWT_DROPDOWN_BUTTON, 2, 82, 245, 88, 99, STR_MULTIPLAYER, STR_NONE }, { WIDGETS_END }, }; @@ -93,14 +95,23 @@ void window_title_menu_open() window = window_create( (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 328) / 2, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 142, - 328, 82, + 328, 100, &window_title_menu_events, WC_TITLE_MENU, - WF_STICK_TO_BACK | WF_TRANSPARENT + WF_STICK_TO_BACK | WF_TRANSPARENT | WF_5 ); window->widgets = window_title_menu_widgets; - window->enabled_widgets |= (8 | 2 | 1); - window->disabled_widgets |= (4); // Disable tutorial button + window->enabled_widgets = ( + (1 << WIDX_START_NEW_GAME) | + (1 << WIDX_CONTINUE_SAVED_GAME) | + (1 << WIDX_SHOW_TUTORIAL) | + (1 << WIDX_GAME_TOOLS) | + (1 << WIDX_MULTIPLAYER) + ); + + // Disable tutorial button + window->disabled_widgets = (1 << WIDX_SHOW_TUTORIAL); + window_init_scroll_widgets(window); } @@ -113,6 +124,9 @@ static void window_title_menu_mouseup(rct_window *w, int widgetIndex) case WIDX_CONTINUE_SAVED_GAME: game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0); break; + case WIDX_MULTIPLAYER: + window_server_list_open(); + break; } } @@ -175,6 +189,15 @@ static void window_title_menu_cursor(rct_window *w, int widgetIndex, int x, int static void window_title_menu_paint(rct_window *w, rct_drawpixelinfo *dpi) { + gfx_fill_rect(dpi, w->x, w->y, w->x + w->width - 1, w->y + 82 - 1, 0x2000000 | 51); + gfx_fill_rect( + dpi, + w->x + window_title_menu_widgets[WIDX_MULTIPLAYER].left, + w->y + window_title_menu_widgets[WIDX_MULTIPLAYER].top, + w->x + window_title_menu_widgets[WIDX_MULTIPLAYER].right, + w->y + window_title_menu_widgets[WIDX_MULTIPLAYER].bottom, + 0x2000000 | 51 + ); window_draw_widgets(w, dpi); }