Changeset - r25255:d399237bfabe
[Not reviewed]
master
0 6 0
Patric Stout - 3 years ago 2021-04-22 23:52:57
truebrain@openttd.org
Add: admin menu for companies in multiplayer games

You can now easily do:
- a password reset (unlock)
- remove an empty company (reset company)
6 files changed with 97 insertions and 166 deletions:
0 comments (0 inline, 0 general)
src/company_cmd.cpp
Show inline comments
 
@@ -568,13 +568,12 @@ Company *DoStartupNewCompany(bool is_ai,
 
	SetDefaultCompanySettings(c->index);
 
	ClearEnginesHiddenFlagOfCompany(c->index);
 

	
 
	GeneratePresidentName(c);
 

	
 
	SetWindowDirty(WC_GRAPH_LEGEND, 0);
 
	InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP);
 
	InvalidateWindowData(WC_CLIENT_LIST, 0);
 
	InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0);
 
	BuildOwnerLegend();
 
	InvalidateWindowData(WC_SMALLMAP, 0, 1);
 

	
 
	if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
 
@@ -906,12 +905,14 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
			delete c;
 
			AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index));
 
			Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
 
			CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
 

	
 
			if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
 
			InvalidateWindowData(WC_CLIENT_LIST, 0);
 

	
 
			break;
 
		}
 

	
 
		default: return CMD_ERROR;
 
	}
 

	
src/lang/english.txt
Show inline comments
 
@@ -2121,16 +2121,12 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION  
 
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION                       :{WHITE}Company is protected. Enter password
 

	
 
# Network company list added strings
 
STR_NETWORK_COMPANY_LIST_CLIENT_LIST                            :Online players
 
STR_NETWORK_COMPANY_LIST_NEW_COMPANY                            :New company
 

	
 
# Network client list popup for clients
 
STR_NETWORK_CLIENTLIST_KICK                                     :Kick
 
STR_NETWORK_CLIENTLIST_BAN                                      :Ban
 

	
 
# Network client list
 
STR_NETWORK_CLIENT_LIST_CAPTION                                 :{WHITE}Multiplayer
 
STR_NETWORK_CLIENT_LIST_SERVER                                  :{BLACK}Server
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME                             :{BLACK}Name
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP                     :{BLACK}Name of the server you are playing on
 
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP                :{BLACK}Edit the name of your server
 
@@ -2141,19 +2137,25 @@ STR_NETWORK_CLIENT_LIST_PLAYER          
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME                             :{BLACK}Name
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP                     :{BLACK}Your player name
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP                :{BLACK}Edit your player name
 
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION               :Your player name
 
STR_NETWORK_CLIENT_LIST_PLAYER_HOST                             :{WHITE}(host) {BLACK}{RAW_STRING}
 
STR_NETWORK_CLIENT_LIST_PLAYER_SELF                             :{WHITE}(you) {BLACK}{RAW_STRING}
 
STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP                           :{BLACK}Administrative actions to perform for this client
 
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP                    :{BLACK}Administrative actions to perform for this client
 
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP                   :{BLACK}Administrative actions to perform for this company
 
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP                            :{BLACK}Join this company
 
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP                     :{BLACK}Send a message to this player
 
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP                    :{BLACK}Send a message to all players of this company
 
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP                  :{BLACK}Send a message to all spectators
 
STR_NETWORK_CLIENT_LIST_SPECTATORS                              :Spectators
 

	
 
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK                       :Kick
 
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN                        :Ban
 
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET                     :Delete
 
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK                    :Password unlock
 

	
 
STR_NETWORK_SERVER                                              :Server
 
STR_NETWORK_CLIENT                                              :Client
 
STR_NETWORK_SPECTATORS                                          :Spectators
 

	
 
# Network set password
 
STR_COMPANY_PASSWORD_CANCEL                                     :{BLACK}Do not save the entered password
src/network/network_gui.cpp
Show inline comments
 
@@ -14,21 +14,23 @@
 
#include "network_client.h"
 
#include "network_gui.h"
 
#include "network_gamelist.h"
 
#include "network.h"
 
#include "network_base.h"
 
#include "network_content.h"
 
#include "network_server.h"
 
#include "../gui.h"
 
#include "network_udp.h"
 
#include "../window_func.h"
 
#include "../gfx_func.h"
 
#include "../widgets/dropdown_type.h"
 
#include "../widgets/dropdown_func.h"
 
#include "../querystring_gui.h"
 
#include "../sortlist_type.h"
 
#include "../company_func.h"
 
#include "../command_func.h"
 
#include "../core/geometry_func.hpp"
 
#include "../genworld.h"
 
#include "../map_type.h"
 
#include "../guitimer_func.h"
 
#include "../zoom_func.h"
 
#include "../sprite.h"
 
@@ -1567,152 +1569,12 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(
 

	
 
/* The window below gives information about the connected clients
 
 * and also makes able to kick them (if server) and stuff like that. */
 

	
 
extern void DrawCompanyIcon(CompanyID cid, int x, int y);
 

	
 
/**
 
 * Prototype for ClientList actions.
 
 * @param ci The information about the current client.
 
 */
 
typedef void ClientList_Action_Proc(const NetworkClientInfo *ci);
 

	
 
static const NWidgetPart _nested_client_list_popup_widgets[] = {
 
	NWidget(WWT_PANEL, COLOUR_GREY, WID_CLP_PANEL), EndContainer(),
 
};
 

	
 
static WindowDesc _client_list_popup_desc(
 
	WDP_AUTO, nullptr, 0, 0,
 
	WC_CLIENT_LIST_POPUP, WC_CLIENT_LIST,
 
	0,
 
	_nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets)
 
);
 

	
 
/* Here we start to define the options out of the menu */
 
static void ClientList_Kick(const NetworkClientInfo *ci)
 
{
 
	NetworkServerKickClient(ci->client_id, nullptr);
 
}
 

	
 
static void ClientList_Ban(const NetworkClientInfo *ci)
 
{
 
	NetworkServerKickOrBanIP(ci->client_id, true, nullptr);
 
}
 

	
 
/** Popup selection window to chose an action to perform */
 
struct NetworkClientListPopupWindow : Window {
 
	/** Container for actions that can be executed. */
 
	struct ClientListAction {
 
		StringID name;                ///< Name of the action to execute
 
		ClientList_Action_Proc *proc; ///< Action to execute
 
	};
 

	
 
	uint sel_index;
 
	ClientID client_id;
 
	Point desired_location;
 
	std::vector<ClientListAction> actions; ///< Actions to execute
 

	
 
	/**
 
	 * Add an action to the list of actions to execute.
 
	 * @param name the name of the action
 
	 * @param proc the procedure to execute for the action
 
	 */
 
	inline void AddAction(StringID name, ClientList_Action_Proc *proc)
 
	{
 
		this->actions.push_back({name, proc});
 
	}
 

	
 
	NetworkClientListPopupWindow(WindowDesc *desc, int x, int y, ClientID client_id) :
 
			Window(desc),
 
			sel_index(0), client_id(client_id)
 
	{
 
		this->desired_location.x = x;
 
		this->desired_location.y = y;
 

	
 
		const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
 

	
 
		/* A server can kick clients (but not himself). */
 
		if (_network_server && _network_own_client_id != ci->client_id) {
 
			this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick);
 
			this->AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban);
 
		}
 

	
 
		this->InitNested(client_id);
 
		CLRBITS(this->flags, WF_WHITE_BORDER);
 
	}
 

	
 
	Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
 
	{
 
		return this->desired_location;
 
	}
 

	
 
	void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
 
	{
 
		Dimension d = *size;
 
		for (const ClientListAction &action : this->actions) {
 
			d = maxdim(GetStringBoundingBox(action.name), d);
 
		}
 

	
 
		d.height *= (uint)this->actions.size();
 
		d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + 4 + 4; // Give the list a bit of padding on both sides.
 
		d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
 
		*size = d;
 
	}
 

	
 
	void DrawWidget(const Rect &r, int widget) const override
 
	{
 
		/* Draw the actions */
 
		int sel = this->sel_index;
 
		int y = r.top + WD_FRAMERECT_TOP;
 
		for (const ClientListAction &action : this->actions) {
 
			TextColour colour;
 
			if (sel-- == 0) { // Selected item, highlight it
 
				GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, PC_BLACK);
 
				colour = TC_WHITE;
 
			} else {
 
				colour = TC_BLACK;
 
			}
 

	
 
			DrawString(r.left + WD_FRAMERECT_LEFT + 4, r.right - WD_FRAMERECT_RIGHT - 4, y, action.name, colour);
 
			y += FONT_HEIGHT_NORMAL;
 
		}
 
	}
 

	
 
	void OnMouseLoop() override
 
	{
 
		/* We selected an action */
 
		uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL;
 

	
 
		if (_left_button_down) {
 
			if (index == this->sel_index || index >= this->actions.size()) return;
 

	
 
			this->sel_index = index;
 
			this->SetDirty();
 
		} else {
 
			if (index < this->actions.size() && _cursor.pos.y >= this->top) {
 
				const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id);
 
				if (ci != nullptr) this->actions[index].proc(ci);
 
			}
 

	
 
			DeleteWindowByClass(WC_CLIENT_LIST_POPUP);
 
		}
 
	}
 
};
 

	
 
/**
 
 * Show the popup (action list)
 
 */
 
static void PopupClientList(ClientID client_id, int x, int y)
 
{
 
	DeleteWindowByClass(WC_CLIENT_LIST_POPUP);
 

	
 
	if (NetworkClientInfo::GetByClientID(client_id) == nullptr) return;
 

	
 
	new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_id);
 
}
 

	
 
static const NWidgetPart _nested_client_list_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
 
		NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
		NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
 
		NWidget(WWT_STICKYBOX, COLOUR_GREY),
 
@@ -1756,12 +1618,23 @@ static WindowDesc _client_list_desc(
 
	WC_CLIENT_LIST, WC_NONE,
 
	0,
 
	_nested_client_list_widgets, lengthof(_nested_client_list_widgets)
 
);
 

	
 
/**
 
 * The possibly entries in a DropDown for an admin.
 
 * Client and companies are mixed; they just have to be unique.
 
 */
 
enum DropDownAdmin {
 
	DD_CLIENT_ADMIN_KICK,
 
	DD_CLIENT_ADMIN_BAN,
 
	DD_COMPANY_ADMIN_RESET,
 
	DD_COMPANY_ADMIN_UNLOCK,
 
};
 

	
 
/**
 
 * Button shown for either a company or client in the client-list.
 
 *
 
 * These buttons are dynamic and strongly depends on which company/client
 
 * what buttons are available. This class allows dynamically creating them
 
 * as the current Widget system does not.
 
 */
 
@@ -1771,17 +1644,17 @@ public:
 
	StringID tooltip;  ///< The tooltip of the button.
 
	Colours colour;    ///< The colour of the button.
 
	bool disabled;     ///< Is the button disabled?
 
	uint height;       ///< Calculated height of the button.
 
	uint width;        ///< Calculated width of the button.
 

	
 
	ButtonCommon(SpriteID sprite, StringID tooltip, Colours colour) :
 
	ButtonCommon(SpriteID sprite, StringID tooltip, Colours colour, bool disabled = false) :
 
		sprite(sprite),
 
		tooltip(tooltip),
 
		colour(colour),
 
		disabled(false)
 
		disabled(disabled)
 
	{
 
		Dimension d = GetSpriteSize(sprite);
 
		this->height = d.height + ScaleGUITrad(WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM);
 
		this->width = d.width + ScaleGUITrad(WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT);
 
	}
 
	virtual ~ButtonCommon() {}
 
@@ -1800,14 +1673,14 @@ class Button : public ButtonCommon {
 
private:
 
	typedef void (*ButtonCallback)(struct NetworkClientListWindow *w, Point pt, T id); ///< Callback function to call on click.
 
	T id;                 ///< ID this button belongs to.
 
	ButtonCallback proc;  ///< Callback proc to call when button is pressed.
 

	
 
public:
 
	Button(SpriteID sprite, StringID tooltip, Colours colour, T id, ButtonCallback proc) :
 
		ButtonCommon(sprite, tooltip, colour),
 
	Button(SpriteID sprite, StringID tooltip, Colours colour, T id, ButtonCallback proc, bool disabled = false) :
 
		ButtonCommon(sprite, tooltip, colour, disabled),
 
		id(id),
 
		proc(proc)
 
	{
 
		assert(proc != nullptr);
 
	}
 

	
 
@@ -1827,12 +1700,15 @@ using ClientButton = Button<ClientID>;
 
 */
 
struct NetworkClientListWindow : Window {
 
private:
 
	ClientListWidgets query_widget; ///< During a query this tracks what widget caused the query.
 
	CompanyID join_company; ///< During query for company password, this stores what company we wanted to join.
 

	
 
	ClientID dd_client_id; ///< During admin dropdown, track which client this was for.
 
	CompanyID dd_company_id; ///< During admin dropdown, track which company this was for.
 

	
 
	Scrollbar *vscroll; ///< Vertical scrollbar of this window.
 
	uint line_height; ///< Current lineheight of each entry in the matrix.
 
	uint line_count; ///< Amount of lines in the matrix.
 

	
 
	std::map<uint, std::vector<std::unique_ptr<ButtonCommon>>> buttons; ///< Per line which buttons are available.
 

	
 
@@ -1874,16 +1750,48 @@ private:
 
	 * @param w The instance of this window.
 
	 * @param pt The point where this button was clicked.
 
	 * @param client_id The client this button was assigned to.
 
	 */
 
	static void OnClickClientAdmin(NetworkClientListWindow *w, Point pt, ClientID client_id)
 
	{
 
		PopupClientList(client_id, pt.x + w->left, pt.y + w->top);
 
		DropDownList list;
 
		list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK, DD_CLIENT_ADMIN_KICK, false));
 
		list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN, DD_CLIENT_ADMIN_BAN, false));
 

	
 
		Rect wi_rect;
 
		wi_rect.left   = pt.x;
 
		wi_rect.right  = pt.x;
 
		wi_rect.top    = pt.y;
 
		wi_rect.bottom = pt.y;
 

	
 
		w->dd_client_id = client_id;
 
		ShowDropDownListAt(w, std::move(list), -1, WID_CL_MATRIX, wi_rect, COLOUR_GREY, true, true);
 
	}
 

	
 
	/**
 
	 * Admin button on a Company is clicked.
 
	 * @param w The instance of this window.
 
	 * @param pt The point where this button was clicked.
 
	 * @param company_id The company this button was assigned to.
 
	 */
 
	static void OnClickCompanyAdmin(NetworkClientListWindow *w, Point pt, CompanyID company_id)
 
	{
 
		DropDownList list;
 
		list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET, DD_COMPANY_ADMIN_RESET, NetworkCompanyHasClients(company_id)));
 
		list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK, DD_COMPANY_ADMIN_UNLOCK, !NetworkCompanyIsPassworded(company_id)));
 

	
 
		Rect wi_rect;
 
		wi_rect.left   = pt.x;
 
		wi_rect.right  = pt.x;
 
		wi_rect.top    = pt.y;
 
		wi_rect.bottom = pt.y;
 

	
 
		w->dd_company_id = company_id;
 
		ShowDropDownListAt(w, std::move(list), -1, WID_CL_MATRIX, wi_rect, COLOUR_GREY, true, true);
 
	}
 
	/**
 
	 * Chat button on a Client is clicked.
 
	 * @param w The instance of this window.
 
	 * @param pt The point where this button was clicked.
 
	 * @param client_id The client this button was assigned to.
 
	 */
 
	static void OnClickClientChat(NetworkClientListWindow *w, Point pt, ClientID client_id)
 
@@ -1897,28 +1805,30 @@ private:
 
	 * @param own_ci The NetworkClientInfo of the client itself.
 
	 */
 
	void RebuildListCompany(CompanyID company_id, const NetworkClientInfo *own_ci)
 
	{
 
		ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat);
 

	
 
		if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin));
 
		this->buttons[line_count].emplace_back(chat_button);
 
		if (own_ci->client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin));
 

	
 
		this->line_count += 1;
 

	
 
		bool has_players = false;
 
		for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
 
			if (ci->client_playas != company_id) continue;
 
			has_players = true;
 

	
 
			if (_network_server) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id));
 
			if (_network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat));
 
			if (_network_server && _network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin));
 

	
 
			this->line_count += 1;
 
		}
 

	
 
		/* Disable the chat button when there are players in this company. */
 
		chat_button->disabled = !has_players;
 
	}
 

	
 
	/**
 
	 * Rebuild the list, meaning: calculate the lines needed and what buttons go on which line.
 
	 */
 
@@ -2081,21 +1991,53 @@ public:
 
			};
 
		}
 

	
 
		return false;
 
	}
 

	
 
	void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
 
	{
 
		/* If you close the dropdown outside the list, don't take any action. */
 
		if (widget == WID_CL_MATRIX) return;
 

	
 
		Window::OnDropdownClose(pt, widget, index, instant_close);
 
	}
 

	
 
	void OnDropdownSelect(int widget, int index) override
 
	{
 
		switch (widget) {
 
			case WID_CL_SERVER_VISIBILITY:
 
				if (!_network_server) break;
 

	
 
				_settings_client.network.server_advertise = (index != 0);
 
				break;
 

	
 
			case WID_CL_MATRIX:
 
				switch (index) {
 
					case DD_CLIENT_ADMIN_KICK:
 
						NetworkServerKickClient(this->dd_client_id, nullptr);
 
						break;
 

	
 
					case DD_CLIENT_ADMIN_BAN:
 
						NetworkServerKickOrBanIP(this->dd_client_id, true, nullptr);
 
						break;
 

	
 
					case DD_COMPANY_ADMIN_RESET:
 
						if (NetworkCompanyHasClients(this->dd_company_id)) break;
 
						DoCommandP(0, CCA_DELETE | this->dd_company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
 
						break;
 

	
 
					case DD_COMPANY_ADMIN_UNLOCK:
 
						NetworkServerSetCompanyPassword(this->dd_company_id, "", false);
 
						break;
 

	
 
					default:
 
						NOT_REACHED();
 
				}
 
				break;
 

	
 
			default:
 
				NOT_REACHED();
 
		}
 

	
 
		this->SetDirty();
 
	}
src/network/network_server.cpp
Show inline comments
 
@@ -284,14 +284,12 @@ NetworkRecvStatus ServerNetworkGameSocke
 

	
 
	/* We just lost one client :( */
 
	if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
 
	extern byte _network_clients_connected;
 
	_network_clients_connected--;
 

	
 
	DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id);
 

	
 
	this->SendPackets(true);
 

	
 
	delete this->GetInfo();
 
	delete this;
 

	
 
	InvalidateWindowData(WC_CLIENT_LIST, 0);
 
@@ -2061,13 +2059,12 @@ void NetworkServerDoMove(ClientID client
 
	/* announce the client's move */
 
	NetworkUpdateClientInfo(client_id);
 

	
 
	NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
 
	NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
 

	
 
	InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP);
 
	InvalidateWindowData(WC_CLIENT_LIST, 0);
 
}
 

	
 
/**
 
 * Send an rcon reply to the client.
 
 * @param client_id The identifier of the client.
src/widgets/network_widget.h
Show inline comments
 
@@ -105,17 +105,12 @@ enum ClientListWidgets {
 
	WID_CL_CLIENT_NAME_EDIT,           ///< Edit button for client name.
 
	WID_CL_MATRIX,                     ///< Company/client list.
 
	WID_CL_SCROLLBAR,                  ///< Scrollbar for company/client list.
 
	WID_CL_COMPANY_JOIN,               ///< Used for QueryWindow when a company has a password.
 
};
 

	
 
/** Widgets of the #NetworkClientListPopupWindow class. */
 
enum ClientListPopupWidgets {
 
	WID_CLP_PANEL, ///< Panel of the window.
 
};
 

	
 
/** Widgets of the #NetworkJoinStatusWindow class. */
 
enum NetworkJoinStatusWidgets {
 
	WID_NJS_BACKGROUND, ///< Background of the window.
 
	WID_NJS_CANCELOK,   ///< Cancel / OK button.
 
};
 

	
src/window_type.h
Show inline comments
 
@@ -469,18 +469,12 @@ enum WindowClass {
 
	 * Client list; %Window numbers:
 
	 *   - 0 = #ClientListWidgets
 
	 */
 
	WC_CLIENT_LIST,
 

	
 
	/**
 
	 * Popup for the client list; %Window numbers:
 
	 *   - #ClientID = #ClientListPopupWidgets
 
	 */
 
	WC_CLIENT_LIST_POPUP,
 

	
 
	/**
 
	 * Network status window; %Window numbers:
 
	 *   - #WN_NETWORK_STATUS_WINDOW_JOIN = #NetworkJoinStatusWidgets
 
	 *   - #WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD = #NetworkContentDownloadStatusWidgets
 
	 */
 
	WC_NETWORK_STATUS_WINDOW,
 

	
0 comments (0 inline, 0 general)