mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-09-01 19:09:09 +00:00
Codechange: Un-bitstuff commands taking a ClientID (i.e. CMD_CLIENT_ID).
This commit is contained in:
@@ -840,7 +840,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
|
||||
* the server will give us a client-id and let us in */
|
||||
_network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
|
||||
ShowJoinStatusWindow();
|
||||
Command<CMD_COMPANY_CTRL>::SendNet(STR_NULL, nullptr, _local_company, 0, CCA_NEW, 0, {});
|
||||
Command<CMD_COMPANY_CTRL>::SendNet(STR_NULL, nullptr, _local_company, CCA_NEW, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
|
||||
}
|
||||
} else {
|
||||
/* take control over an existing company */
|
||||
|
@@ -89,15 +89,17 @@ static CommandCallback * const _callback_table[] = {
|
||||
|
||||
template <Commands Tcmd> static CommandDataBuffer SanitizeCmdStrings(const CommandDataBuffer &data);
|
||||
template <Commands Tcmd> static void UnpackNetworkCommand(const CommandPacket *cp);
|
||||
template <Commands Tcmd> static void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id);
|
||||
struct CommandDispatch {
|
||||
CommandDataBuffer(*Sanitize)(const CommandDataBuffer &);
|
||||
void (*ReplaceClientId)(CommandPacket &, ClientID);
|
||||
void (*Unpack)(const CommandPacket *);
|
||||
};
|
||||
|
||||
template<typename T, T... i>
|
||||
inline constexpr auto MakeDispatchTable(std::integer_sequence<T, i...>) noexcept
|
||||
{
|
||||
return std::array<CommandDispatch, sizeof...(i)>{{ { &SanitizeCmdStrings<static_cast<Commands>(i)>, &UnpackNetworkCommand<static_cast<Commands>(i)> }... }};
|
||||
return std::array<CommandDispatch, sizeof...(i)>{{ { &SanitizeCmdStrings<static_cast<Commands>(i)>, &NetworkReplaceCommandClientId<static_cast<Commands>(i)>, &UnpackNetworkCommand<static_cast<Commands>(i)> }... }};
|
||||
}
|
||||
static constexpr auto _cmd_dispatch = MakeDispatchTable(std::make_integer_sequence<std::underlying_type_t<Commands>, CMD_END>{});
|
||||
|
||||
@@ -383,6 +385,35 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp)
|
||||
p->Send_uint8 (callback);
|
||||
}
|
||||
|
||||
/** Helper to process a single ClientID argument. */
|
||||
template <class T>
|
||||
static inline void SetClientIdHelper(T &data, [[maybe_unused]] ClientID client_id)
|
||||
{
|
||||
if constexpr (std::is_same_v<ClientID, T>) {
|
||||
data = client_id;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set all invalid ClientID's to the proper value. */
|
||||
template<class Ttuple, size_t... Tindices>
|
||||
static inline void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence<Tindices...>)
|
||||
{
|
||||
((SetClientIdHelper(std::get<Tindices>(values), client_id)), ...);
|
||||
}
|
||||
|
||||
template <Commands Tcmd>
|
||||
static void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id)
|
||||
{
|
||||
/* Unpack command parameters. */
|
||||
auto params = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.data);
|
||||
|
||||
/* Insert client id. */
|
||||
SetClientIds(params, client_id, std::make_index_sequence<std::tuple_size_v<decltype(params)>>{});
|
||||
|
||||
/* Repack command parameters. */
|
||||
cp.data = EndianBufferWriter<CommandDataBuffer>::FromValue(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a client ID into the command data in a command packet.
|
||||
* @param cp Command packet to modify.
|
||||
@@ -390,14 +421,7 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp)
|
||||
*/
|
||||
void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id)
|
||||
{
|
||||
/* Unpack command parameters. */
|
||||
auto params = EndianBufferReader::ToValue<std::tuple<TileIndex, uint32, uint32, std::string>>(cp.data);
|
||||
|
||||
/* Insert client id. */
|
||||
std::get<2>(params) = client_id;
|
||||
|
||||
/* Repack command parameters. */
|
||||
cp.data = EndianBufferWriter<CommandDataBuffer>::FromValue(params);
|
||||
_cmd_dispatch[cp.cmd].ReplaceClientId(cp, client_id);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1396,7 +1396,7 @@ static void AdminCompanyResetCallback(Window *w, bool confirmed)
|
||||
{
|
||||
if (confirmed) {
|
||||
if (NetworkCompanyHasClients(_admin_company_id)) return;
|
||||
Command<CMD_COMPANY_CTRL>::Post(0, CCA_DELETE | _admin_company_id << 16 | CRR_MANUAL << 24, 0, {});
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_DELETE, _admin_company_id, CRR_MANUAL, INVALID_CLIENT_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,9 +1536,9 @@ private:
|
||||
static void OnClickCompanyNew(NetworkClientListWindow *w, Point pt, CompanyID company_id)
|
||||
{
|
||||
if (_network_server) {
|
||||
Command<CMD_COMPANY_CTRL>::Post(0, CCA_NEW, _network_own_client_id, {});
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW, INVALID_COMPANY, CRR_NONE, _network_own_client_id);
|
||||
} else {
|
||||
Command<CMD_COMPANY_CTRL>::SendNet(STR_NULL, nullptr, _local_company, 0, CCA_NEW, 0, {});
|
||||
Command<CMD_COMPANY_CTRL>::SendNet(STR_NULL, nullptr, _local_company, CCA_NEW, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1050,15 +1050,15 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet
|
||||
* to match the company in the packet. If it doesn't, the client has done
|
||||
* something pretty naughty (or a bug), and will be kicked
|
||||
*/
|
||||
uint32 company_p1 = cp.cmd == CMD_COMPANY_CTRL ? std::get<1>(EndianBufferReader::ToValue<CommandTraits<CMD_COMPANY_CTRL>::Args>(cp.data)) : 0;
|
||||
if (!(cp.cmd == CMD_COMPANY_CTRL && company_p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
|
||||
CompanyCtrlAction cca = cp.cmd == CMD_COMPANY_CTRL ? std::get<0>(EndianBufferReader::ToValue<CommandTraits<CMD_COMPANY_CTRL>::Args>(cp.data)) : CCA_NEW;
|
||||
if (!(cp.cmd == CMD_COMPANY_CTRL && cca == CCA_NEW && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
|
||||
IConsolePrint(CC_WARNING, "Kicking client #{} (IP: {}) due to calling a command as another company {}.",
|
||||
ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
|
||||
return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
|
||||
}
|
||||
|
||||
if (cp.cmd == CMD_COMPANY_CTRL) {
|
||||
if (company_p1 != 0 || cp.company != COMPANY_SPECTATOR) {
|
||||
if (cca != CCA_NEW || cp.company != COMPANY_SPECTATOR) {
|
||||
return this->SendError(NETWORK_ERROR_CHEATER);
|
||||
}
|
||||
|
||||
@@ -1556,7 +1556,7 @@ static void NetworkAutoCleanCompanies()
|
||||
/* Is the company empty for autoclean_unprotected-months, and is there no protection? */
|
||||
if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && _network_company_states[c->index].password.empty()) {
|
||||
/* Shut the company down */
|
||||
Command<CMD_COMPANY_CTRL>::Post(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, {});
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_DELETE, c->index, CRR_AUTOCLEAN, INVALID_CLIENT_ID);
|
||||
IConsolePrint(CC_INFO, "Auto-cleaned company #{} with no password.", c->index + 1);
|
||||
}
|
||||
/* Is the company empty for autoclean_protected-months, and there is a protection? */
|
||||
@@ -1570,7 +1570,7 @@ static void NetworkAutoCleanCompanies()
|
||||
/* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
|
||||
if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && vehicles_in_company[c->index] == 0) {
|
||||
/* Shut the company down */
|
||||
Command<CMD_COMPANY_CTRL>::Post(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, {});
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_DELETE, c->index, CRR_AUTOCLEAN, INVALID_CLIENT_ID);
|
||||
IConsolePrint(CC_INFO, "Auto-cleaned company #{} with no vehicles.", c->index + 1);
|
||||
}
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user