Merge branch 'master' into jgrpp
# Conflicts: # CMakeLists.txt # COMPILING.md # src/console.cpp # src/console_cmds.cpp # src/console_internal.h # src/rev.cpp.in
This commit is contained in:
@@ -340,6 +340,7 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err)
|
||||
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER,
|
||||
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP,
|
||||
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN,
|
||||
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME,
|
||||
};
|
||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||
|
||||
@@ -722,6 +723,8 @@ void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const c
|
||||
|
||||
if (address.GetPort() == 0) return;
|
||||
|
||||
if (!NetworkValidateClientName()) return;
|
||||
|
||||
strecpy(_settings_client.network.last_host, address.GetHostname(), lastof(_settings_client.network.last_host));
|
||||
_settings_client.network.last_port = address.GetPort();
|
||||
_network_join_as = join_as;
|
||||
|
@@ -282,7 +282,6 @@ static void SendChat(const char *buf, DestType type, int dest)
|
||||
/** Window to enter the chat message in. */
|
||||
struct NetworkChatWindow : public Window {
|
||||
DestType dtype; ///< The type of destination.
|
||||
StringID dest_string; ///< String representation of the destination.
|
||||
int dest; ///< The identifier of the destination.
|
||||
QueryString message_editbox; ///< Message editbox.
|
||||
|
||||
@@ -307,9 +306,10 @@ struct NetworkChatWindow : public Window {
|
||||
STR_NULL,
|
||||
};
|
||||
assert((uint)this->dtype < lengthof(chat_captions));
|
||||
this->dest_string = chat_captions[this->dtype];
|
||||
|
||||
this->InitNested(type);
|
||||
this->CreateNestedTree();
|
||||
this->GetWidget<NWidgetCore>(WID_NC_DESTINATION)->widget_data = chat_captions[this->dtype];
|
||||
this->FinishInitNested(type);
|
||||
|
||||
this->SetFocusedWidget(WID_NC_TEXTBOX);
|
||||
InvalidateWindowData(WC_NEWS_WINDOW, 0, this->height);
|
||||
@@ -464,27 +464,13 @@ struct NetworkChatWindow : public Window {
|
||||
return pt;
|
||||
}
|
||||
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
if (widget != WID_NC_DESTINATION) return;
|
||||
|
||||
if (this->dtype == DESTTYPE_CLIENT) {
|
||||
SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
|
||||
}
|
||||
Dimension d = GetStringBoundingBox(this->dest_string);
|
||||
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||
*size = maxdim(*size, d);
|
||||
}
|
||||
|
||||
void DrawWidget(const Rect &r, int widget) const override
|
||||
{
|
||||
if (widget != WID_NC_DESTINATION) return;
|
||||
|
||||
if (this->dtype == DESTTYPE_CLIENT) {
|
||||
SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
|
||||
}
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT);
|
||||
}
|
||||
|
||||
void OnClick(Point pt, int widget, int click_count) override
|
||||
@@ -532,7 +518,7 @@ static const NWidgetPart _nested_chat_window_widgets[] = {
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY, WID_NC_CLOSE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_NC_BACKGROUND),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_NC_DESTINATION), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NULL, STR_NULL),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_NC_DESTINATION), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetTextColour(TC_BLACK), SetAlignment(SA_TOP | SA_RIGHT), SetDataTip(STR_NULL, STR_NULL),
|
||||
NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NC_TEXTBOX), SetMinimalSize(100, 12), SetPadding(1, 0, 1, 0), SetResize(1, 0),
|
||||
SetDataTip(STR_NETWORK_CHAT_OSKTITLE, STR_NULL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NC_SENDBUTTON), SetMinimalSize(62, 12), SetPadding(1, 0, 1, 0), SetDataTip(STR_NETWORK_CHAT_SEND, STR_NULL),
|
||||
|
@@ -736,6 +736,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac
|
||||
|
||||
if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
|
||||
/* The server validates the name when receiving it from clients, so when it is wrong
|
||||
* here something went really wrong. In the best case the packet got malformed on its
|
||||
* way too us, in the worst case the server is broken or compromised. */
|
||||
if (!NetworkIsValidClientName(name)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
|
||||
ci = NetworkClientInfo::GetByClientID(client_id);
|
||||
if (ci != nullptr) {
|
||||
@@ -781,26 +785,27 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p)
|
||||
{
|
||||
static const StringID network_error_strings[] = {
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_GENERAL
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_DESYNC
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_SAVEGAME_FAILED
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_CONNECTION_LOST
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_ILLEGAL_PACKET
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NEWGRF_MISMATCH
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_AUTHORIZED
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_EXPECTED
|
||||
STR_NETWORK_ERROR_WRONG_REVISION, // NETWORK_ERROR_WRONG_REVISION
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NAME_IN_USE
|
||||
STR_NETWORK_ERROR_WRONG_PASSWORD, // NETWORK_ERROR_WRONG_PASSWORD
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_COMPANY_MISMATCH
|
||||
STR_NETWORK_ERROR_KICKED, // NETWORK_ERROR_KICKED
|
||||
STR_NETWORK_ERROR_CHEATER, // NETWORK_ERROR_CHEATER
|
||||
STR_NETWORK_ERROR_SERVER_FULL, // NETWORK_ERROR_FULL
|
||||
STR_NETWORK_ERROR_TOO_MANY_COMMANDS, // NETWORK_ERROR_TOO_MANY_COMMANDS
|
||||
STR_NETWORK_ERROR_TIMEOUT_PASSWORD, // NETWORK_ERROR_TIMEOUT_PASSWORD
|
||||
STR_NETWORK_ERROR_TIMEOUT_COMPUTER, // NETWORK_ERROR_TIMEOUT_COMPUTER
|
||||
STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
|
||||
STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_GENERAL
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_DESYNC
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_SAVEGAME_FAILED
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_CONNECTION_LOST
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_ILLEGAL_PACKET
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NEWGRF_MISMATCH
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_AUTHORIZED
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_EXPECTED
|
||||
STR_NETWORK_ERROR_WRONG_REVISION, // NETWORK_ERROR_WRONG_REVISION
|
||||
STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NAME_IN_USE
|
||||
STR_NETWORK_ERROR_WRONG_PASSWORD, // NETWORK_ERROR_WRONG_PASSWORD
|
||||
STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_COMPANY_MISMATCH
|
||||
STR_NETWORK_ERROR_KICKED, // NETWORK_ERROR_KICKED
|
||||
STR_NETWORK_ERROR_CHEATER, // NETWORK_ERROR_CHEATER
|
||||
STR_NETWORK_ERROR_SERVER_FULL, // NETWORK_ERROR_FULL
|
||||
STR_NETWORK_ERROR_TOO_MANY_COMMANDS, // NETWORK_ERROR_TOO_MANY_COMMANDS
|
||||
STR_NETWORK_ERROR_TIMEOUT_PASSWORD, // NETWORK_ERROR_TIMEOUT_PASSWORD
|
||||
STR_NETWORK_ERROR_TIMEOUT_COMPUTER, // NETWORK_ERROR_TIMEOUT_COMPUTER
|
||||
STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
|
||||
STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
|
||||
STR_NETWORK_ERROR_INVALID_CLIENT_NAME, // NETWORK_ERROR_INVALID_CLIENT_NAME
|
||||
};
|
||||
static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
|
||||
|
||||
@@ -1414,6 +1419,56 @@ void NetworkClientsToSpectators(CompanyID cid)
|
||||
cur_company.Restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given client name is deemed valid for use in network games.
|
||||
* An empty name (null or '') is not valid as that is essentially no name at all.
|
||||
* A name starting with white space is not valid for tab completion purposes.
|
||||
* @param client_name The client name to check for validity.
|
||||
* @return True iff the name is valid.
|
||||
*/
|
||||
bool NetworkIsValidClientName(const char *client_name)
|
||||
{
|
||||
if (StrEmpty(client_name)) return false;
|
||||
if (*client_name == ' ') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the given client name in place, i.e. remove leading and trailing spaces.
|
||||
* After the trim check whether the client name is valid. A client name is valid
|
||||
* whenever the name is not empty and does not start with spaces. This check is
|
||||
* done via \c NetworkIsValidClientName.
|
||||
* When the client name is valid, this function returns true.
|
||||
* When the client name is not valid a GUI error message is shown telling the
|
||||
* user to set the client name and this function returns false.
|
||||
*
|
||||
* This function is not suitable for ensuring a valid client name at the server
|
||||
* as the error message will then be shown to the host instead of the client.
|
||||
* @param client_name The client name to validate. It will be trimmed of leading
|
||||
* and trailing spaces.
|
||||
* @return True iff the client name is valid.
|
||||
*/
|
||||
bool NetworkValidateClientName(char *client_name)
|
||||
{
|
||||
StrTrimInPlace(client_name);
|
||||
if (NetworkIsValidClientName(client_name)) return true;
|
||||
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_BAD_PLAYER_NAME, INVALID_STRING_ID, WL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for NetworkValidateClientName on _settings_client.network.client_name.
|
||||
* It trims the client name and checks whether it is empty. When it is empty
|
||||
* an error message is shown to the GUI user.
|
||||
* See \c NetworkValidateClientName(char*) for details about the functionality.
|
||||
* @return True iff the client name is valid.
|
||||
*/
|
||||
bool NetworkValidateClientName()
|
||||
{
|
||||
return NetworkValidateClientName(_settings_client.network.client_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the server our name.
|
||||
*/
|
||||
@@ -1422,6 +1477,11 @@ void NetworkUpdateClientName()
|
||||
NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
|
||||
|
||||
if (ci == nullptr) return;
|
||||
/* There is no validation on string settings, it is actually a post change callback.
|
||||
* This method is called from that post change callback. So, when the client name is
|
||||
* changed via the console there is no easy way to prevent an invalid name. Though,
|
||||
* we can prevent it getting sent here. */
|
||||
if (!NetworkValidateClientName()) return;
|
||||
|
||||
/* Don't change the name if it is the same as the old name */
|
||||
if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) {
|
||||
|
@@ -863,55 +863,31 @@ public:
|
||||
|
||||
EventState OnKeyPress(WChar key, uint16 keycode) override
|
||||
{
|
||||
switch (keycode) {
|
||||
case WKC_UP:
|
||||
/* scroll up by one */
|
||||
if (this->list_pos > 0) this->list_pos--;
|
||||
break;
|
||||
case WKC_DOWN:
|
||||
/* scroll down by one */
|
||||
if (this->list_pos < (int)this->content.size() - 1) this->list_pos++;
|
||||
break;
|
||||
case WKC_PAGEUP:
|
||||
/* scroll up a page */
|
||||
this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
|
||||
break;
|
||||
case WKC_PAGEDOWN:
|
||||
/* scroll down a page */
|
||||
this->list_pos = std::min(this->list_pos + this->vscroll->GetCapacity(), (int)this->content.size() - 1);
|
||||
break;
|
||||
case WKC_HOME:
|
||||
/* jump to beginning */
|
||||
this->list_pos = 0;
|
||||
break;
|
||||
case WKC_END:
|
||||
/* jump to end */
|
||||
this->list_pos = (int)this->content.size() - 1;
|
||||
break;
|
||||
|
||||
case WKC_SPACE:
|
||||
case WKC_RETURN:
|
||||
if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
|
||||
if (this->selected != nullptr) {
|
||||
_network_content_client.ToggleSelectedState(this->selected);
|
||||
this->content.ForceResort();
|
||||
this->InvalidateData();
|
||||
if (this->vscroll->UpdateListPositionOnKeyPress(this->list_pos, keycode) == ES_NOT_HANDLED) {
|
||||
switch (keycode) {
|
||||
case WKC_SPACE:
|
||||
case WKC_RETURN:
|
||||
if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
|
||||
if (this->selected != nullptr) {
|
||||
_network_content_client.ToggleSelectedState(this->selected);
|
||||
this->content.ForceResort();
|
||||
this->InvalidateData();
|
||||
}
|
||||
if (this->filter_data.types.any()) {
|
||||
this->content.ForceRebuild();
|
||||
this->InvalidateData();
|
||||
}
|
||||
return ES_HANDLED;
|
||||
}
|
||||
if (this->filter_data.types.any()) {
|
||||
this->content.ForceRebuild();
|
||||
this->InvalidateData();
|
||||
}
|
||||
return ES_HANDLED;
|
||||
}
|
||||
/* space is pressed and filter is focused. */
|
||||
FALLTHROUGH;
|
||||
/* space is pressed and filter is focused. */
|
||||
FALLTHROUGH;
|
||||
|
||||
default:
|
||||
return ES_NOT_HANDLED;
|
||||
default:
|
||||
return ES_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->content.size() == 0) {
|
||||
this->list_pos = 0; // above stuff may result in "-1".
|
||||
if (this->UpdateFilterState()) {
|
||||
this->content.ForceRebuild();
|
||||
this->InvalidateData();
|
||||
|
@@ -36,6 +36,9 @@ extern StringList _network_host_list;
|
||||
extern StringList _network_ban_list;
|
||||
|
||||
byte NetworkSpectatorCount();
|
||||
bool NetworkIsValidClientName(const char *client_name);
|
||||
bool NetworkValidateClientName();
|
||||
bool NetworkValidateClientName(char *client_name);
|
||||
void NetworkUpdateClientName();
|
||||
bool NetworkCompanyHasClients(CompanyID company);
|
||||
const char *NetworkChangeCompanyPassword(CompanyID company_id, const char *password);
|
||||
|
@@ -68,8 +68,8 @@ void UpdateNetworkGameWindow()
|
||||
}
|
||||
|
||||
typedef GUIList<NetworkGameList*, StringFilter&> GUIGameServerList;
|
||||
typedef uint16 ServerListPosition;
|
||||
static const ServerListPosition SLP_INVALID = 0xFFFF;
|
||||
typedef int ServerListPosition;
|
||||
static const ServerListPosition SLP_INVALID = -1;
|
||||
|
||||
/** Full blown container to make it behave exactly as we want :) */
|
||||
class NWidgetServerListHeader : public NWidgetContainer {
|
||||
@@ -786,39 +786,8 @@ public:
|
||||
EventState state = ES_NOT_HANDLED;
|
||||
|
||||
/* handle up, down, pageup, pagedown, home and end */
|
||||
if (keycode == WKC_UP || keycode == WKC_DOWN || keycode == WKC_PAGEUP || keycode == WKC_PAGEDOWN || keycode == WKC_HOME || keycode == WKC_END) {
|
||||
if (this->servers.size() == 0) return ES_HANDLED;
|
||||
switch (keycode) {
|
||||
case WKC_UP:
|
||||
/* scroll up by one */
|
||||
if (this->list_pos == SLP_INVALID) return ES_HANDLED;
|
||||
if (this->list_pos > 0) this->list_pos--;
|
||||
break;
|
||||
case WKC_DOWN:
|
||||
/* scroll down by one */
|
||||
if (this->list_pos == SLP_INVALID) return ES_HANDLED;
|
||||
if (this->list_pos < this->servers.size() - 1) this->list_pos++;
|
||||
break;
|
||||
case WKC_PAGEUP:
|
||||
/* scroll up a page */
|
||||
if (this->list_pos == SLP_INVALID) return ES_HANDLED;
|
||||
this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
|
||||
break;
|
||||
case WKC_PAGEDOWN:
|
||||
/* scroll down a page */
|
||||
if (this->list_pos == SLP_INVALID) return ES_HANDLED;
|
||||
this->list_pos = std::min(this->list_pos + this->vscroll->GetCapacity(), (int)this->servers.size() - 1);
|
||||
break;
|
||||
case WKC_HOME:
|
||||
/* jump to beginning */
|
||||
this->list_pos = 0;
|
||||
break;
|
||||
case WKC_END:
|
||||
/* jump to end */
|
||||
this->list_pos = (ServerListPosition)this->servers.size() - 1;
|
||||
break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
if (this->vscroll->UpdateListPositionOnKeyPress(this->list_pos, keycode) == ES_HANDLED) {
|
||||
if (this->list_pos == SLP_INVALID) return ES_HANDLED;
|
||||
|
||||
this->server = this->servers[this->list_pos];
|
||||
|
||||
@@ -854,12 +823,9 @@ public:
|
||||
}
|
||||
|
||||
case WID_NG_CLIENT:
|
||||
/* Make sure the name does not start with a space, so TAB completion works */
|
||||
if (!StrEmpty(this->name_editbox.text.buf) && this->name_editbox.text.buf[0] != ' ') {
|
||||
strecpy(_settings_client.network.client_name, this->name_editbox.text.buf, lastof(_settings_client.network.client_name));
|
||||
} else {
|
||||
strecpy(_settings_client.network.client_name, "Player", lastof(_settings_client.network.client_name));
|
||||
}
|
||||
/* Validation of the name will happen once the user tries to join or start a game, as getting
|
||||
* error messages while typing (e.g. when you clear the name) defeats the purpose of the check. */
|
||||
strecpy(_settings_client.network.client_name, this->name_editbox.text.buf, lastof(_settings_client.network.client_name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1292,6 +1258,8 @@ static WindowDesc _network_start_server_window_desc(
|
||||
|
||||
static void ShowNetworkStartServerWindow()
|
||||
{
|
||||
if (!NetworkValidateClientName()) return;
|
||||
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
||||
|
||||
@@ -1584,6 +1552,8 @@ static WindowDesc _network_lobby_window_desc(
|
||||
*/
|
||||
static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
|
||||
{
|
||||
if (!NetworkValidateClientName()) return;
|
||||
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
||||
|
||||
|
@@ -987,8 +987,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need a valid name.. make it Player */
|
||||
if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
|
||||
if (!NetworkIsValidClientName(name)) {
|
||||
/* An invalid client name was given. However, the client ensures the name
|
||||
* is valid before it is sent over the network, so something went horribly
|
||||
* wrong. This is probably someone trying to troll us. */
|
||||
return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
|
||||
}
|
||||
|
||||
if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate
|
||||
/* We could not create a name for this client */
|
||||
@@ -1558,6 +1562,13 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet
|
||||
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
|
||||
|
||||
if (ci != nullptr) {
|
||||
if (!NetworkIsValidClientName(client_name)) {
|
||||
/* An invalid client name was given. However, the client ensures the name
|
||||
* is valid before it is sent over the network, so something went horribly
|
||||
* wrong. This is probably someone trying to troll us. */
|
||||
return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
|
||||
}
|
||||
|
||||
/* Display change */
|
||||
if (NetworkFindName(client_name, lastof(client_name))) {
|
||||
NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
|
||||
|
@@ -133,6 +133,7 @@ enum NetworkErrorCode {
|
||||
NETWORK_ERROR_TIMEOUT_COMPUTER,
|
||||
NETWORK_ERROR_TIMEOUT_MAP,
|
||||
NETWORK_ERROR_TIMEOUT_JOIN,
|
||||
NETWORK_ERROR_INVALID_CLIENT_NAME,
|
||||
|
||||
NETWORK_ERROR_END,
|
||||
};
|
||||
|
Reference in New Issue
Block a user