|
@@ -53,7 +53,6 @@
|
|
|
#include "../safeguards.h"
|
|
|
|
|
|
static void ShowNetworkStartServerWindow();
|
|
|
static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
|
|
|
|
|
|
static const int NETWORK_LIST_REFRESH_DELAY = 30; ///< Time, in seconds, between updates of the network list.
|
|
|
|
|
@@ -770,7 +769,7 @@ public:
|
|
|
|
|
|
case WID_NG_JOIN: // Join Game
|
|
|
if (this->server != nullptr) {
|
|
|
ShowNetworkLobbyWindow(this->server);
|
|
|
NetworkClientConnectGame(this->server->connection_string, COMPANY_SPECTATOR);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -990,7 +989,6 @@ static WindowDesc _network_game_window_d
|
|
|
void ShowNetworkGameWindow()
|
|
|
{
|
|
|
static bool first = true;
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
|
|
|
|
|
|
/* Only show once */
|
|
@@ -1266,328 +1264,10 @@ static void ShowNetworkStartServerWindow
|
|
|
if (!NetworkValidateOurClientName()) return;
|
|
|
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
|
|
|
|
|
new NetworkStartServerWindow(&_network_start_server_window_desc);
|
|
|
}
|
|
|
|
|
|
struct NetworkLobbyWindow : public Window {
|
|
|
CompanyID company; ///< Selected company
|
|
|
NetworkGameList *server; ///< Selected server
|
|
|
NetworkCompanyInfo company_info[MAX_COMPANIES];
|
|
|
Scrollbar *vscroll;
|
|
|
|
|
|
NetworkLobbyWindow(WindowDesc *desc, NetworkGameList *ngl) :
|
|
|
Window(desc), company(INVALID_COMPANY), server(ngl)
|
|
|
{
|
|
|
this->CreateNestedTree();
|
|
|
this->vscroll = this->GetScrollbar(WID_NL_SCROLLBAR);
|
|
|
this->FinishInitNested(WN_NETWORK_WINDOW_LOBBY);
|
|
|
}
|
|
|
|
|
|
CompanyID NetworkLobbyFindCompanyIndex(byte pos) const
|
|
|
{
|
|
|
/* Scroll through all this->company_info and get the 'pos' item that is not empty. */
|
|
|
for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
|
|
|
if (!this->company_info[i].company_name.empty()) {
|
|
|
if (pos-- == 0) return i;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return COMPANY_FIRST;
|
|
|
}
|
|
|
|
|
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_NL_HEADER:
|
|
|
size->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
|
|
|
break;
|
|
|
|
|
|
case WID_NL_MATRIX:
|
|
|
resize->height = WD_MATRIX_TOP + std::max<uint>(std::max(GetSpriteSize(SPR_LOCK).height, GetSpriteSize(SPR_PROFIT_LOT).height), FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
|
|
|
size->height = 10 * resize->height;
|
|
|
break;
|
|
|
|
|
|
case WID_NL_DETAILS:
|
|
|
size->height = 30 + 11 * FONT_HEIGHT_NORMAL;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void SetStringParameters(int widget) const override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_NL_TEXT:
|
|
|
SetDParamStr(0, this->server->info.server_name);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void DrawWidget(const Rect &r, int widget) const override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_NL_DETAILS:
|
|
|
this->DrawDetails(r);
|
|
|
break;
|
|
|
|
|
|
case WID_NL_MATRIX:
|
|
|
this->DrawMatrix(r);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void OnPaint() override
|
|
|
{
|
|
|
const NetworkGameInfo *gi = &this->server->info;
|
|
|
|
|
|
/* Join button is disabled when no company is selected and for AI companies. */
|
|
|
this->SetWidgetDisabledState(WID_NL_JOIN, this->company == INVALID_COMPANY || GetLobbyCompanyInfo(this->company)->ai);
|
|
|
/* Cannot start new company if there are too many. */
|
|
|
this->SetWidgetDisabledState(WID_NL_NEW, gi->companies_on >= gi->companies_max);
|
|
|
|
|
|
this->vscroll->SetCount(gi->companies_on);
|
|
|
|
|
|
/* Draw window widgets */
|
|
|
this->DrawWidgets();
|
|
|
}
|
|
|
|
|
|
void DrawMatrix(const Rect &r) const
|
|
|
{
|
|
|
bool rtl = _current_text_dir == TD_RTL;
|
|
|
uint left = r.left + WD_FRAMERECT_LEFT;
|
|
|
uint right = r.right - WD_FRAMERECT_RIGHT;
|
|
|
uint text_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - FONT_HEIGHT_NORMAL) / 2 + WD_MATRIX_TOP;
|
|
|
|
|
|
Dimension lock_size = GetSpriteSize(SPR_LOCK);
|
|
|
int lock_width = lock_size.width;
|
|
|
int lock_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - lock_size.height) / 2 + WD_MATRIX_TOP;
|
|
|
|
|
|
Dimension profit_size = GetSpriteSize(SPR_PROFIT_LOT);
|
|
|
int profit_width = lock_size.width;
|
|
|
int profit_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - profit_size.height) / 2 + WD_MATRIX_TOP;
|
|
|
|
|
|
uint text_left = left + (rtl ? lock_width + profit_width + 4 : 0);
|
|
|
uint text_right = right - (rtl ? 0 : lock_width + profit_width + 4);
|
|
|
uint profit_left = rtl ? left : right - profit_width;
|
|
|
uint lock_left = rtl ? left + profit_width + 2 : right - profit_width - lock_width - 2;
|
|
|
|
|
|
int y = r.top;
|
|
|
/* Draw company list */
|
|
|
int pos = this->vscroll->GetPosition();
|
|
|
while (pos < this->server->info.companies_on) {
|
|
|
byte company = NetworkLobbyFindCompanyIndex(pos);
|
|
|
bool income = false;
|
|
|
if (this->company == company) {
|
|
|
GfxFillRect(r.left + WD_BEVEL_LEFT, y + 1, r.right - WD_BEVEL_RIGHT, y + this->resize.step_height - 2, PC_GREY); // show highlighted item with a different colour
|
|
|
}
|
|
|
|
|
|
DrawString(text_left, text_right, y + text_offset, this->company_info[company].company_name, TC_BLACK);
|
|
|
if (this->company_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, lock_left, y + lock_y_offset);
|
|
|
|
|
|
/* If the company's income was positive puts a green dot else a red dot */
|
|
|
if (this->company_info[company].income >= 0) income = true;
|
|
|
DrawSprite(income ? SPR_PROFIT_LOT : SPR_PROFIT_NEGATIVE, PAL_NONE, profit_left, y + profit_y_offset);
|
|
|
|
|
|
pos++;
|
|
|
y += this->resize.step_height;
|
|
|
if (pos >= this->vscroll->GetPosition() + this->vscroll->GetCapacity()) break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void DrawDetails(const Rect &r) const
|
|
|
{
|
|
|
const int detail_height = 12 + FONT_HEIGHT_NORMAL + 12;
|
|
|
/* Draw info about selected company when it is selected in the left window. */
|
|
|
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 12, STR_NETWORK_GAME_LOBBY_COMPANY_INFO, TC_FROMSTRING, SA_HOR_CENTER);
|
|
|
|
|
|
if (this->company == INVALID_COMPANY || this->company_info[this->company].company_name.empty()) return;
|
|
|
|
|
|
int y = r.top + detail_height + 4;
|
|
|
const NetworkGameInfo *gi = &this->server->info;
|
|
|
|
|
|
SetDParam(0, gi->clients_on);
|
|
|
SetDParam(1, gi->clients_max);
|
|
|
SetDParam(2, gi->companies_on);
|
|
|
SetDParam(3, gi->companies_max);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS);
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParamStr(0, this->company_info[this->company].company_name);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_COMPANY_NAME);
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].inaugurated_year);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR); // inauguration year
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].company_value);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VALUE); // company value
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].money);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE); // current balance
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].income);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_LAST_YEARS_INCOME); // last year's income
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].performance);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PERFORMANCE); // performance
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].num_vehicle[NETWORK_VEH_TRAIN]);
|
|
|
SetDParam(1, this->company_info[this->company].num_vehicle[NETWORK_VEH_LORRY]);
|
|
|
SetDParam(2, this->company_info[this->company].num_vehicle[NETWORK_VEH_BUS]);
|
|
|
SetDParam(3, this->company_info[this->company].num_vehicle[NETWORK_VEH_SHIP]);
|
|
|
SetDParam(4, this->company_info[this->company].num_vehicle[NETWORK_VEH_PLANE]);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VEHICLES); // vehicles
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParam(0, this->company_info[this->company].num_station[NETWORK_VEH_TRAIN]);
|
|
|
SetDParam(1, this->company_info[this->company].num_station[NETWORK_VEH_LORRY]);
|
|
|
SetDParam(2, this->company_info[this->company].num_station[NETWORK_VEH_BUS]);
|
|
|
SetDParam(3, this->company_info[this->company].num_station[NETWORK_VEH_SHIP]);
|
|
|
SetDParam(4, this->company_info[this->company].num_station[NETWORK_VEH_PLANE]);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_STATIONS); // stations
|
|
|
y += FONT_HEIGHT_NORMAL;
|
|
|
|
|
|
SetDParamStr(0, this->company_info[this->company].clients);
|
|
|
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PLAYERS); // players
|
|
|
}
|
|
|
|
|
|
void OnClick(Point pt, int widget, int click_count) override
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case WID_NL_CANCEL: // Cancel button
|
|
|
ShowNetworkGameWindow();
|
|
|
break;
|
|
|
|
|
|
case WID_NL_MATRIX: { // Company list
|
|
|
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NL_MATRIX);
|
|
|
this->company = (id_v >= this->server->info.companies_on) ? INVALID_COMPANY : NetworkLobbyFindCompanyIndex(id_v);
|
|
|
this->SetDirty();
|
|
|
|
|
|
/* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
|
|
|
if (click_count > 1 && !this->IsWidgetDisabled(WID_NL_JOIN)) this->OnClick(pt, WID_NL_JOIN, 1);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case WID_NL_JOIN: // Join company
|
|
|
/* Button can be clicked only when it is enabled. */
|
|
|
NetworkClientConnectGame(this->server->connection_string, this->company);
|
|
|
break;
|
|
|
|
|
|
case WID_NL_NEW: // New company
|
|
|
NetworkClientConnectGame(this->server->connection_string, COMPANY_NEW_COMPANY);
|
|
|
break;
|
|
|
|
|
|
case WID_NL_SPECTATE: // Spectate game
|
|
|
NetworkClientConnectGame(this->server->connection_string, COMPANY_SPECTATOR);
|
|
|
break;
|
|
|
|
|
|
case WID_NL_REFRESH: // Refresh
|
|
|
/* Clear the information so removed companies don't remain */
|
|
|
for (auto &company : this->company_info) company = {};
|
|
|
|
|
|
NetworkQueryLobbyServer(this->server->connection_string);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void OnResize() override
|
|
|
{
|
|
|
this->vscroll->SetCapacityFromWidget(this, WID_NL_MATRIX);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
static const NWidgetPart _nested_network_lobby_window_widgets[] = {
|
|
|
NWidget(NWID_HORIZONTAL),
|
|
|
NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
|
|
|
NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_GAME_LOBBY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
|
|
EndContainer(),
|
|
|
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_BACKGROUND),
|
|
|
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NL_TEXT), SetDataTip(STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN, STR_NULL), SetResize(1, 0), SetPadding(10, 10, 0, 10),
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
|
|
|
NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10),
|
|
|
/* Company list. */
|
|
|
NWidget(NWID_VERTICAL),
|
|
|
NWidget(WWT_PANEL, COLOUR_WHITE, WID_NL_HEADER), SetMinimalSize(146, 0), SetResize(1, 0), SetFill(1, 0), EndContainer(),
|
|
|
NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NL_MATRIX), SetMinimalSize(146, 0), SetResize(1, 1), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP), SetScrollbar(WID_NL_SCROLLBAR),
|
|
|
EndContainer(),
|
|
|
NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NL_SCROLLBAR),
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetResize(0, 1),
|
|
|
/* Company info. */
|
|
|
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_DETAILS), SetMinimalSize(232, 0), SetResize(1, 1), SetFill(1, 1), EndContainer(),
|
|
|
EndContainer(),
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(0, 9),
|
|
|
/* Buttons. */
|
|
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 3, 10),
|
|
|
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 3, 0),
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_JOIN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_JOIN_COMPANY, STR_NETWORK_GAME_LOBBY_JOIN_COMPANY_TOOLTIP),
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_NEW), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_NEW_COMPANY, STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP),
|
|
|
EndContainer(),
|
|
|
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 3, 0),
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_SPECTATE), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_SPECTATE_GAME, STR_NETWORK_GAME_LOBBY_SPECTATE_GAME_TOOLTIP),
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_REFRESH), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
|
|
|
EndContainer(),
|
|
|
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 3, 0),
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
|
|
|
NWidget(NWID_SPACER), SetFill(1, 1),
|
|
|
EndContainer(),
|
|
|
EndContainer(),
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(0, 8),
|
|
|
EndContainer(),
|
|
|
};
|
|
|
|
|
|
static WindowDesc _network_lobby_window_desc(
|
|
|
WDP_CENTER, nullptr, 0, 0,
|
|
|
WC_NETWORK_WINDOW, WC_NONE,
|
|
|
0,
|
|
|
_nested_network_lobby_window_widgets, lengthof(_nested_network_lobby_window_widgets)
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
* Show the networklobbywindow with the selected server.
|
|
|
* @param ngl Selected game pointer which is passed to the new window.
|
|
|
*/
|
|
|
static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
|
|
|
{
|
|
|
if (!NetworkValidateOurClientName()) return;
|
|
|
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
|
|
|
CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
|
|
|
|
|
_settings_client.network.last_joined = ngl->connection_string;
|
|
|
|
|
|
NetworkQueryLobbyServer(ngl->connection_string);
|
|
|
|
|
|
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Get the company information of a given company to fill for the lobby.
|
|
|
* @param company the company to get the company info struct from.
|
|
|
* @return the company info struct to write the (downloaded) data to.
|
|
|
*/
|
|
|
NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company)
|
|
|
{
|
|
|
NetworkLobbyWindow *lobby = dynamic_cast<NetworkLobbyWindow*>(FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY));
|
|
|
return (lobby != nullptr && company < MAX_COMPANIES) ? &lobby->company_info[company] : nullptr;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Get the game information for the lobby.
|
|
|
* @return the game info struct to write the (downloaded) data to.
|
|
|
*/
|
|
|
NetworkGameList *GetLobbyGameInfo()
|
|
|
{
|
|
|
NetworkLobbyWindow *lobby = dynamic_cast<NetworkLobbyWindow *>(FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY));
|
|
|
return lobby != nullptr ? lobby->server : nullptr;
|
|
|
}
|
|
|
|
|
|
/* The window below gives information about the connected clients
|
|
|
* and also makes able to kick them (if server) and stuff like that. */
|
|
|
|