Feature #1509 ยป 0096-stdinhand.-ch-Improve-coding-style.patch
| server/stdinhand.c | ||
|---|---|---|
|
#define SPECHASH_IDATA_COPY time_duplicate
|
||
|
#define SPECHASH_IDATA_FREE (kick_hash_data_free_fn_t) free
|
||
|
#define SPECHASH_UDATA_TO_IDATA(t) (&(t))
|
||
|
#define SPECHASH_IDATA_TO_UDATA(p) (NULL != p ? *p : 0)
|
||
|
#define SPECHASH_IDATA_TO_UDATA(p) (p != nullptr ? *p : 0)
|
||
|
#include "spechash.h"
|
||
|
const char *script_extension = ".serv";
|
||
|
static struct kick_hash *kick_table_by_addr = NULL;
|
||
|
static struct kick_hash *kick_table_by_user = NULL;
|
||
|
static struct kick_hash *kick_table_by_addr = nullptr;
|
||
|
static struct kick_hash *kick_table_by_user = nullptr;
|
||
|
static bool cut_client_connection(struct connection *caller, char *name,
|
||
| ... | ... | |
|
"------------------------------------------------------------------------------";
|
||
|
/**********************************************************************//**
|
||
|
Are we operating under a restricted security regime? For now
|
||
|
Are we operating under a restricted security regime? For now
|
||
|
this does not do much.
|
||
|
**************************************************************************/
|
||
|
static bool is_restricted(struct connection *caller)
|
||
| ... | ... | |
|
int ind;
|
||
|
result = match_prefix(command_name_by_number, CMD_NUM, 0,
|
||
|
fc_strncasecmp, NULL, token, &ind);
|
||
|
fc_strncasecmp, nullptr, token, &ind);
|
||
|
if (result < M_PRE_AMBIGUOUS) {
|
||
|
return ind;
|
||
| ... | ... | |
|
**************************************************************************/
|
||
|
void stdinhand_init(void)
|
||
|
{
|
||
|
fc_assert(NULL == kick_table_by_addr);
|
||
|
fc_assert(kick_table_by_addr == nullptr);
|
||
|
kick_table_by_addr = kick_hash_new();
|
||
|
fc_assert(NULL == kick_table_by_user);
|
||
|
fc_assert(kick_table_by_user == nullptr);
|
||
|
kick_table_by_user = kick_hash_new();
|
||
|
}
|
||
| ... | ... | |
|
**************************************************************************/
|
||
|
void stdinhand_free(void)
|
||
|
{
|
||
|
fc_assert(NULL != kick_table_by_addr);
|
||
|
if (NULL != kick_table_by_addr) {
|
||
|
fc_assert(kick_table_by_addr != nullptr);
|
||
|
if (kick_table_by_addr != nullptr) {
|
||
|
kick_hash_destroy(kick_table_by_addr);
|
||
|
kick_table_by_addr = NULL;
|
||
|
kick_table_by_addr = nullptr;
|
||
|
}
|
||
|
fc_assert(NULL != kick_table_by_user);
|
||
|
if (NULL != kick_table_by_user) {
|
||
|
fc_assert(kick_table_by_user != nullptr);
|
||
|
if (kick_table_by_user != nullptr) {
|
||
|
kick_hash_destroy(kick_table_by_user);
|
||
|
kick_table_by_user = NULL;
|
||
|
kick_table_by_user = nullptr;
|
||
|
}
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Whether the caller can use the specified command. caller == NULL means
|
||
|
Whether the caller can use the specified command. caller == nullptr means
|
||
|
console.
|
||
|
**************************************************************************/
|
||
|
static bool may_use(struct connection *caller, enum command_id cmd)
|
||
|
{
|
||
|
if (!caller) {
|
||
|
return TRUE; /* on the console, everything is allowed */
|
||
|
if (caller == nullptr) {
|
||
|
return TRUE; /* On the console, everything is allowed */
|
||
|
}
|
||
|
return (caller->access_level >= command_level(command_by_number(cmd)));
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Whether the caller cannot use any commands at all.
|
||
|
caller == NULL means console.
|
||
|
caller == nullptr means console.
|
||
|
**************************************************************************/
|
||
|
static bool may_use_nothing(struct connection *caller)
|
||
|
{
|
||
|
if (!caller) {
|
||
|
return FALSE; /* on the console, everything is allowed */
|
||
|
if (caller == nullptr) {
|
||
|
return FALSE; /* On the console, everything is allowed */
|
||
|
}
|
||
|
return (ALLOW_NONE == conn_get_access(caller));
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Return the status of the setting (changeable, locked, fixed).
|
||
|
caller == NULL means console.
|
||
|
caller == nullptr means console.
|
||
|
**************************************************************************/
|
||
|
static char setting_status(struct connection *caller,
|
||
|
const struct setting *pset)
|
||
| ... | ... | |
|
return '!';
|
||
|
}
|
||
|
if (setting_is_changeable(pset, caller, NULL, 0)) {
|
||
|
/* setting can be changed */
|
||
|
if (setting_is_changeable(pset, caller, nullptr, 0)) {
|
||
|
/* Setting can be changed */
|
||
|
return '+';
|
||
|
}
|
||
|
/* setting is fixed */
|
||
|
/* Setting is fixed */
|
||
|
return ' ';
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
feedback related to server commands
|
||
|
caller == NULL means console.
|
||
|
Feedback related to server commands
|
||
|
caller == nullptr means console.
|
||
|
No longer duplicate all output to console.
|
||
|
This lowlevel function takes a single line; prefix is prepended to line.
|
||
|
**************************************************************************/
|
||
|
static void cmd_reply_line(enum command_id cmd, struct connection *caller,
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *line)
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *line)
|
||
|
{
|
||
|
const char *cmdname = cmd < CMD_NUM
|
||
|
? command_name_by_number(cmd)
|
||
| ... | ... | |
|
: "(?!?)"; /* this case is a bug! */
|
||
|
if (caller) {
|
||
|
notify_conn(caller->self, NULL, E_SETTING, ftc_command,
|
||
|
notify_conn(caller->self, nullptr, E_SETTING, ftc_command,
|
||
|
"/%s: %s%s", cmdname, prefix, line);
|
||
|
/* cc: to the console - testing has proved it's too verbose - rp
|
||
|
con_write(rfc_status, "%s/%s: %s%s", caller->name, cmdname, prefix, line);
|
||
| ... | ... | |
|
if (rfc_status == C_OK) {
|
||
|
struct packet_chat_msg packet;
|
||
|
package_event(&packet, NULL, E_SETTING, ftc_server, "%s", line);
|
||
|
package_event(&packet, nullptr, E_SETTING, ftc_server, "%s", line);
|
||
|
conn_list_iterate(game.est_connections, pconn) {
|
||
|
/* Do not tell caller, since they were told above! */
|
||
|
if (caller != pconn) {
|
||
| ... | ... | |
|
} conn_list_iterate_end;
|
||
|
event_cache_add_for_all(&packet);
|
||
|
if (NULL != caller) {
|
||
|
if (caller != nullptr) {
|
||
|
/* Echo to the console. */
|
||
|
log_normal("%s", line);
|
||
|
}
|
||
| ... | ... | |
|
duplicate declaration required for attribute to work...
|
||
|
**************************************************************************/
|
||
|
static void cmd_reply_prefix(enum command_id cmd, struct connection *caller,
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *format, ...)
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *format, ...)
|
||
|
fc__attribute((__format__ (__printf__, 5, 6)));
|
||
|
static void cmd_reply_prefix(enum command_id cmd, struct connection *caller,
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *format, ...)
|
||
|
enum rfc_status rfc_status, const char *prefix,
|
||
|
const char *format, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
va_start(ap, format);
|
||
|
vcmd_reply_prefix(cmd, caller, rfc_status, prefix, format, ap);
|
||
|
va_end(ap);
|
||
| ... | ... | |
|
enum rfc_status rfc_status, const char *format, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
va_start(ap, format);
|
||
|
vcmd_reply_prefix(cmd, caller, rfc_status, "", format, ap);
|
||
|
va_end(ap);
|
||
| ... | ... | |
|
is invalid. This function is common handling for that situation.
|
||
|
**************************************************************************/
|
||
|
static void cmd_reply_no_such_player(enum command_id cmd,
|
||
|
struct connection *caller,
|
||
|
const char *name,
|
||
|
enum m_pre_result match_result)
|
||
|
struct connection *caller,
|
||
|
const char *name,
|
||
|
enum m_pre_result match_result)
|
||
|
{
|
||
|
switch (match_result) {
|
||
|
case M_PRE_EMPTY:
|
||
|
cmd_reply(cmd, caller, C_SYNTAX,
|
||
|
_("Name is empty, so cannot be a player."));
|
||
|
_("Name is empty, so cannot be a player."));
|
||
|
break;
|
||
|
case M_PRE_LONG:
|
||
|
cmd_reply(cmd, caller, C_SYNTAX,
|
||
|
_("Name is too long, so cannot be a player."));
|
||
|
_("Name is too long, so cannot be a player."));
|
||
|
break;
|
||
|
case M_PRE_AMBIGUOUS:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("Player name prefix '%s' is ambiguous."), name);
|
||
|
_("Player name prefix '%s' is ambiguous."), name);
|
||
|
break;
|
||
|
case M_PRE_FAIL:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("No player by the name of '%s'."), name);
|
||
|
_("No player by the name of '%s'."), name);
|
||
|
break;
|
||
|
default:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("Unexpected match_result %d (%s) for '%s'."),
|
||
|
match_result, _(m_pre_description(match_result)), name);
|
||
|
_("Unexpected match_result %d (%s) for '%s'."),
|
||
|
match_result, _(m_pre_description(match_result)), name);
|
||
|
log_error("Unexpected match_result %d (%s) for '%s'.",
|
||
|
match_result, m_pre_description(match_result), name);
|
||
|
}
|
||
| ... | ... | |
|
is invalid. This function is common handling for that situation.
|
||
|
**************************************************************************/
|
||
|
static void cmd_reply_no_such_conn(enum command_id cmd,
|
||
|
struct connection *caller,
|
||
|
const char *name,
|
||
|
enum m_pre_result match_result)
|
||
|
struct connection *caller,
|
||
|
const char *name,
|
||
|
enum m_pre_result match_result)
|
||
|
{
|
||
|
switch (match_result) {
|
||
|
case M_PRE_EMPTY:
|
||
|
cmd_reply(cmd, caller, C_SYNTAX,
|
||
|
_("Name is empty, so cannot be a connection."));
|
||
|
_("Name is empty, so cannot be a connection."));
|
||
|
break;
|
||
|
case M_PRE_LONG:
|
||
|
cmd_reply(cmd, caller, C_SYNTAX,
|
||
|
_("Name is too long, so cannot be a connection."));
|
||
|
_("Name is too long, so cannot be a connection."));
|
||
|
break;
|
||
|
case M_PRE_AMBIGUOUS:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("Connection name prefix '%s' is ambiguous."), name);
|
||
|
_("Connection name prefix '%s' is ambiguous."), name);
|
||
|
break;
|
||
|
case M_PRE_FAIL:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("No connection by the name of '%s'."), name);
|
||
|
_("No connection by the name of '%s'."), name);
|
||
|
break;
|
||
|
default:
|
||
|
cmd_reply(cmd, caller, C_FAIL,
|
||
|
_("Unexpected match_result %d (%s) for '%s'."),
|
||
|
match_result, _(m_pre_description(match_result)), name);
|
||
|
_("Unexpected match_result %d (%s) for '%s'."),
|
||
|
match_result, _(m_pre_description(match_result)), name);
|
||
|
log_error("Unexpected match_result %d (%s) for '%s'.",
|
||
|
match_result, m_pre_description(match_result), name);
|
||
|
}
|
||
| ... | ... | |
|
/**********************************************************************//**
|
||
|
Handle metaconnection command.
|
||
|
**************************************************************************/
|
||
|
static bool metaconnection_command(struct connection *caller, char *arg,
|
||
|
static bool metaconnection_command(struct connection *caller, char *arg,
|
||
|
bool check)
|
||
|
{
|
||
|
bool persistent = FALSE;
|
||
| ... | ... | |
|
cmd_reply(CMD_METACONN, caller, C_COMMENT,
|
||
|
_("Metaserver connection is closed."));
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
_("Argument must be 'u', 'up', 'd', 'down', 'p', 'persistent', or '?'."));
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Handle metapatches command.
|
||
|
**************************************************************************/
|
||
|
static bool metapatches_command(struct connection *caller,
|
||
|
static bool metapatches_command(struct connection *caller,
|
||
|
char *arg, bool check)
|
||
|
{
|
||
|
if (check) {
|
||
| ... | ... | |
|
cmd_reply(CMD_METASERVER, caller, C_OK,
|
||
|
_("Metaserver is now [%s]."), meta_addr_port());
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
if (!check) {
|
||
|
save_game(arg, "User request", FALSE);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
if (!check) {
|
||
|
save_game(arg, "Scenario", TRUE);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
**************************************************************************/
|
||
|
void toggle_ai_player_direct(struct connection *caller, struct player *pplayer)
|
||
|
{
|
||
|
fc_assert_ret(pplayer != NULL);
|
||
|
fc_assert_ret(pplayer != nullptr);
|
||
|
if (is_human(pplayer)) {
|
||
|
cmd_reply(CMD_AITOGGLE, caller, C_OK,
|
||
|
_("%s is now under AI control."),
|
||
|
player_name(pplayer));
|
||
|
_("%s is now under AI control."),
|
||
|
player_name(pplayer));
|
||
|
player_set_to_ai_mode(pplayer,
|
||
|
!ai_level_is_valid(pplayer->ai_common.skill_level)
|
||
|
? game.info.skill_level
|
||
| ... | ... | |
|
fc_assert(is_ai(pplayer));
|
||
|
} else {
|
||
|
cmd_reply(CMD_AITOGGLE, caller, C_OK,
|
||
|
_("%s is now under human control."),
|
||
|
player_name(pplayer));
|
||
|
_("%s is now under human control."),
|
||
|
player_name(pplayer));
|
||
|
player_set_under_human_control(pplayer);
|
||
|
fc_assert(is_human(pplayer));
|
||
|
}
|
||
| ... | ... | |
|
toggle_ai_player_direct(caller, pplayer);
|
||
|
send_player_info_c(pplayer, game.est_connections);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
if (game_was_started()) {
|
||
|
status = create_command_newcomer(arg[0], ai_type_name, check,
|
||
|
NULL, NULL, buf, sizeof(buf));
|
||
|
nullptr, nullptr, buf, sizeof(buf));
|
||
|
} else {
|
||
|
status = create_command_pregame(arg[0], ai_type_name, check,
|
||
|
NULL, buf, sizeof(buf));
|
||
|
nullptr, buf, sizeof(buf));
|
||
|
}
|
||
|
free_tokens(arg, ntokens);
|
||
| ... | ... | |
|
struct player **newplayer,
|
||
|
char *buf, size_t buflen)
|
||
|
{
|
||
|
struct player *pplayer = NULL;
|
||
|
struct player *pplayer = nullptr;
|
||
|
struct research *presearch;
|
||
|
bool new_slot = FALSE;
|
||
| ... | ... | |
|
}
|
||
|
/* Check first if we can replace a player with
|
||
|
* [1a] - the same username. */
|
||
|
* [1a] - The same username. */
|
||
|
pplayer = player_by_user(name);
|
||
|
if (pplayer && pplayer->is_alive) {
|
||
|
fc_snprintf(buf, buflen,
|
||
| ... | ... | |
|
return C_BOUNCE;
|
||
|
}
|
||
|
/* [1b] - the same player name. */
|
||
|
/* [1b] - The same player name. */
|
||
|
pplayer = player_by_name(name);
|
||
|
if (pplayer && pplayer->is_alive) {
|
||
|
fc_snprintf(buf, buflen,
|
||
| ... | ... | |
|
} players_iterate_end;
|
||
|
} else {
|
||
|
/* Try to find a nation. */
|
||
|
pnation = pick_a_nation(NULL, FALSE, TRUE, NOT_A_BARBARIAN);
|
||
|
pnation = pick_a_nation(nullptr, FALSE, TRUE, NOT_A_BARBARIAN);
|
||
|
if (pnation == NO_NATION_SELECTED) {
|
||
|
fc_snprintf(buf, buflen,
|
||
|
_("Can't create players, no nations available."));
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
if (pplayer == NULL) {
|
||
|
if (pplayer == nullptr) {
|
||
|
if (player_count() == player_slot_count()) {
|
||
|
bool dead_found = FALSE;
|
||
| ... | ... | |
|
fc_snprintf(buf, buflen,
|
||
|
_("%s is replacing dead player %s as an AI-controlled "
|
||
|
"player."), name, player_name(pplayer));
|
||
|
/* remove player and thus free a player slot */
|
||
|
/* Remove player and thus free a player slot */
|
||
|
server_remove_player(pplayer);
|
||
|
pplayer = NULL;
|
||
|
pplayer = nullptr;
|
||
|
} else if (player_count() == player_slot_count()) {
|
||
|
/* [2] All player slots are used; try to remove a dead player. */
|
||
|
bool dead_found = FALSE;
|
||
| ... | ... | |
|
}
|
||
|
/* Create the new player. */
|
||
|
pplayer = server_create_player(-1, ai, NULL, FALSE);
|
||
|
pplayer = server_create_player(-1, ai, nullptr, FALSE);
|
||
|
if (!pplayer) {
|
||
|
fc_snprintf(buf, buflen, _("Failed to create new player %s."), name);
|
||
|
return C_FAIL;
|
||
| ... | ... | |
|
/* Find a color for the new player. */
|
||
|
assign_player_colors();
|
||
|
/* TRANS: keep one space at the beginning of the string. */
|
||
|
/* TRANS: Keep one space at the beginning of the string. */
|
||
|
cat_snprintf(buf, buflen, _(" Nation of the new player: %s."),
|
||
|
nation_rule_name(pnation));
|
||
| ... | ... | |
|
sz_strlcpy(pplayer->username, _(ANON_USER_NAME));
|
||
|
pplayer->unassigned_user = TRUE;
|
||
|
pplayer->was_created = TRUE; /* must use /remove explicitly to remove */
|
||
|
pplayer->was_created = TRUE; /* Must use /remove explicitly to remove */
|
||
|
set_as_ai(pplayer);
|
||
|
set_ai_level_directer(pplayer, game.info.skill_level);
|
||
|
CALL_PLR_AI_FUNC(gained_control, pplayer, pplayer);
|
||
|
send_player_info_c(pplayer, NULL);
|
||
|
send_player_info_c(pplayer, nullptr);
|
||
|
/* Send updated diplstate information to all players. */
|
||
|
send_player_diplstate_c(NULL, NULL);
|
||
|
send_player_diplstate_c(nullptr, nullptr);
|
||
|
/* Send research info after player info, else the client will complain
|
||
|
* about invalid team. */
|
||
|
send_research_info(presearch, NULL);
|
||
|
send_research_info(presearch, nullptr);
|
||
|
(void) send_server_info_to_metaserver(META_INFO);
|
||
|
if (newplayer != NULL) {
|
||
|
if (newplayer != nullptr) {
|
||
|
*newplayer = pplayer;
|
||
|
}
|
||
|
return C_OK;
|
||
|
}
|
||
| ... | ... | |
|
char *buf, size_t buflen)
|
||
|
{
|
||
|
char leader_name[MAX_LEN_NAME]; /* Must be in whole function scope */
|
||
|
struct player *pplayer = NULL;
|
||
|
struct player *pplayer = nullptr;
|
||
|
bool rand_name = FALSE;
|
||
|
if (name[0] == '\0') {
|
||
| ... | ... | |
|
return C_SYNTAX;
|
||
|
}
|
||
|
if (NULL != player_by_name(name)) {
|
||
|
if (player_by_name(name) != nullptr) {
|
||
|
fc_snprintf(buf, buflen,
|
||
|
_("A player already exists by that name."));
|
||
|
return C_BOUNCE;
|
||
|
}
|
||
|
if (NULL != player_by_user(name)) {
|
||
|
if (player_by_user(name) != nullptr) {
|
||
|
fc_snprintf(buf, buflen,
|
||
|
_("A user already exists by that name."));
|
||
|
return C_BOUNCE;
|
||
| ... | ... | |
|
/* Search for first uncontrolled player */
|
||
|
pplayer = find_uncontrolled_player();
|
||
|
if (NULL == pplayer) {
|
||
|
if (pplayer == nullptr) {
|
||
|
/* Check that we are not going over max players setting */
|
||
|
if (normal_player_count() >= game.server.max_players) {
|
||
|
fc_snprintf(buf, buflen,
|
||
| ... | ... | |
|
if (pplayer) {
|
||
|
struct ai_type *ait = ai_type_by_name(ai);
|
||
|
if (ait == NULL) {
|
||
|
if (ait == nullptr) {
|
||
|
fc_snprintf(buf, buflen,
|
||
|
_("There is no AI type %s."), ai);
|
||
|
return C_FAIL;
|
||
| ... | ... | |
|
team_remove_player(pplayer);
|
||
|
pplayer->ai = ai_type_by_name(ai);
|
||
|
} else {
|
||
|
/* add new player */
|
||
|
pplayer = server_create_player(-1, ai, NULL, FALSE);
|
||
|
/* pregame so no need to assign_player_colors() */
|
||
|
/* Add new player */
|
||
|
pplayer = server_create_player(-1, ai, nullptr, FALSE);
|
||
|
/* Pregame so no need to assign_player_colors() */
|
||
|
if (!pplayer) {
|
||
|
fc_snprintf(buf, buflen,
|
||
|
_("Failed to create new player %s."), name);
|
||
| ... | ... | |
|
sz_strlcpy(pplayer->username, _(ANON_USER_NAME));
|
||
|
pplayer->unassigned_user = TRUE;
|
||
|
pplayer->was_created = TRUE; /* must use /remove explicitly to remove */
|
||
|
pplayer->was_created = TRUE; /* Must use /remove explicitly to remove */
|
||
|
pplayer->random_name = rand_name;
|
||
|
set_as_ai(pplayer);
|
||
|
set_ai_level_directer(pplayer, game.info.skill_level);
|
||
| ... | ... | |
|
reset_all_start_commands(TRUE);
|
||
|
(void) send_server_info_to_metaserver(META_INFO);
|
||
|
if (newplayer != NULL) {
|
||
|
if (newplayer != nullptr) {
|
||
|
*newplayer = pplayer;
|
||
|
}
|
||
|
return C_OK;
|
||
|
}
|
||
| ... | ... | |
|
pplayer = player_by_name_prefix(arg, &match_result);
|
||
|
if (NULL == pplayer) {
|
||
|
if (pplayer == nullptr) {
|
||
|
cmd_reply_no_such_player(CMD_REMOVE, caller, arg, match_result);
|
||
|
return FALSE;
|
||
|
}
|
||
| ... | ... | |
|
sz_strlcpy(name, player_name(pplayer));
|
||
|
server_remove_player(pplayer);
|
||
|
if (!caller || caller->used) { /* may have removed self */
|
||
|
if (!caller || caller->used) { /* May have removed self */
|
||
|
cmd_reply(CMD_REMOVE, caller, C_OK,
|
||
|
_("Removed player %s from the game."), name);
|
||
|
_("Removed player %s from the game."), name);
|
||
|
}
|
||
|
(void) aifill(game.info.aifill);
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
Security: We will look for a file with mandatory extension '.serv',
|
||
|
and on public servers we will not look outside the data directories.
|
||
|
As long as the user cannot create files with arbitrary names in the
|
||
|
root of the data directories, this should ensure that we will not be
|
||
|
root of the data directories, this should ensure that we will not be
|
||
|
tricked into loading non-approved content. The script is read with the
|
||
|
permissions of the caller, so it will in any case not lead to elevated
|
||
|
permissions unless there are other bugs.
|
||
| ... | ... | |
|
const char *real_filename;
|
||
|
size_t fnlen;
|
||
|
/* check recursion depth */
|
||
|
/* Check recursion depth */
|
||
|
if (read_recursion > GAME_MAX_READ_RECURSION) {
|
||
|
log_error("Error: recursive calls to read!");
|
||
|
return FALSE;
|
||
|
}
|
||
|
/* abuse real_filename to find if we already have a .serv extension */
|
||
|
/* Abuse real_filename to find if we already have a .serv extension */
|
||
|
fnlen = strlen(script_filename);
|
||
|
real_filename = script_filename + fnlen
|
||
|
- MIN(strlen(script_extension), fnlen);
|
||
|
if (strcmp(real_filename, script_extension) != 0) {
|
||
|
fc_snprintf(serv_filename, sizeof(serv_filename), "%s%s",
|
||
|
fc_snprintf(serv_filename, sizeof(serv_filename), "%s%s",
|
||
|
script_filename, script_extension);
|
||
|
} else {
|
||
|
sz_strlcpy(serv_filename, script_filename);
|
||
| ... | ... | |
|
if (!real_filename) {
|
||
|
if (is_restricted(caller) && !from_cmdline) {
|
||
|
cmd_reply(CMD_READ_SCRIPT, caller, C_FAIL,
|
||
|
_("No command script found by the name \"%s\"."),
|
||
|
_("No command script found by the name \"%s\"."),
|
||
|
serv_filename);
|
||
|
return FALSE;
|
||
|
}
|
||
| ... | ... | |
|
} else {
|
||
|
cmd_reply(CMD_READ_SCRIPT, caller, C_FAIL,
|
||
|
_("Cannot read command line scriptfile '%s'."), real_filename);
|
||
|
if (NULL != caller) {
|
||
|
if (caller != nullptr) {
|
||
|
log_error(_("Could not read script file '%s'."), real_filename);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
const char *real_filename;
|
||
|
size_t arglen = strlen(arg);
|
||
|
/* abuse real_filename to find if we already have a .serv extension */
|
||
|
/* Abuse real_filename to find if we already have a .serv extension */
|
||
|
real_filename = arg + arglen - MIN(strlen(script_extension), arglen);
|
||
|
if (strcmp(real_filename, script_extension) != 0) {
|
||
|
fc_snprintf(serv_filename, sizeof(serv_filename), "%s%s",
|
||
| ... | ... | |
|
enum cmdlevel level)
|
||
|
{
|
||
|
/* Only ever call me for specific connection. */
|
||
|
fc_assert_ret_val(ptarget != NULL, FALSE);
|
||
|
fc_assert_ret_val(ptarget != nullptr, FALSE);
|
||
|
if (caller && ptarget->access_level > caller->access_level) {
|
||
|
/*
|
||
| ... | ... | |
|
* and thus this if clause is needed.
|
||
|
* (Imagine a ctrl level access player that wants to change
|
||
|
* access level of a hack level access player)
|
||
|
* At the moment it can be used only by hack access level
|
||
|
* At the moment it can be used only by hack access level
|
||
|
* and thus this clause is never used.
|
||
|
*/
|
||
|
cmd_reply(CMD_CMDLEVEL, caller, C_FAIL,
|
||
| ... | ... | |
|
enum cmdlevel access_level_for_next_connection(void)
|
||
|
{
|
||
|
if ((first_access_level > default_access_level)
|
||
|
&& !a_connection_exists()) {
|
||
|
&& !a_connection_exists()) {
|
||
|
return first_access_level;
|
||
|
} else {
|
||
|
return default_access_level;
|
||
| ... | ... | |
|
{
|
||
|
if (first_access_level > default_access_level
|
||
|
&& !is_first_access_level_taken()) {
|
||
|
notify_conn(NULL, NULL, E_SETTING, ftc_any,
|
||
|
notify_conn(nullptr, nullptr, E_SETTING, ftc_any,
|
||
|
_("Anyone can now become game organizer "
|
||
|
"'%s' by issuing the 'first' command."),
|
||
|
cmdlevel_name(first_access_level));
|
||
| ... | ... | |
|
conn_list_iterate(game.est_connections, pconn) {
|
||
|
const char *lvl_name = cmdlevel_name(conn_get_access(pconn));
|
||
|
if (lvl_name != NULL) {
|
||
|
if (lvl_name != nullptr) {
|
||
|
cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT, "cmdlevel %s %s",
|
||
|
lvl_name, pconn->username);
|
||
|
} else {
|
||
|
fc_assert(lvl_name != NULL); /* Always fails when reached. */
|
||
|
fc_assert(lvl_name != nullptr); /* Always fails when reached. */
|
||
|
}
|
||
|
} conn_list_iterate_end;
|
||
|
cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT,
|
||
| ... | ... | |
|
}
|
||
|
if (check) {
|
||
|
return TRUE; /* looks good */
|
||
|
return TRUE; /* Looks good */
|
||
|
}
|
||
|
if (ntokens == 1) {
|
||
| ... | ... | |
|
{
|
||
|
if (!caller) {
|
||
|
cmd_reply(CMD_FIRSTLEVEL, caller, C_FAIL,
|
||
|
_("The 'first' command makes no sense from the server command line."));
|
||
|
_("The 'first' command makes no sense from the server command line."));
|
||
|
return FALSE;
|
||
|
} else if (caller->access_level >= first_access_level) {
|
||
|
cmd_reply(CMD_FIRSTLEVEL, caller, C_FAIL,
|
||
|
_("You already have command access level '%s' or better."),
|
||
|
cmdlevel_name(first_access_level));
|
||
|
_("You already have command access level '%s' or better."),
|
||
|
cmdlevel_name(first_access_level));
|
||
|
return FALSE;
|
||
|
} else if (is_first_access_level_taken()) {
|
||
|
cmd_reply(CMD_FIRSTLEVEL, caller, C_FAIL,
|
||
|
_("Someone else is already game organizer."));
|
||
|
_("Someone else is already game organizer."));
|
||
|
return FALSE;
|
||
|
} else if (!check) {
|
||
|
conn_set_access(caller, first_access_level, FALSE);
|
||
| ... | ... | |
|
_("Connection %s has opted to become the game organizer."),
|
||
|
caller->username);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
void set_running_game_access_level(void)
|
||
|
{
|
||
|
if (default_access_level > ALLOW_BASIC) {
|
||
|
notify_conn(NULL, NULL, E_SETTING, ftc_server,
|
||
|
notify_conn(nullptr, nullptr, E_SETTING, ftc_server,
|
||
|
_("Default cmdlevel lowered to 'basic' on game start."));
|
||
|
default_access_level = ALLOW_BASIC;
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
if (i == 0) {
|
||
|
return "rulesetdir";
|
||
|
} else if (i < OLEVELS_NUM+1) {
|
||
|
return sset_level_name(i-1);
|
||
|
} else if (i < OLEVELS_NUM + 1) {
|
||
|
return sset_level_name(i - 1);
|
||
|
} else {
|
||
|
return optname_accessor(i-OLEVELS_NUM-1);
|
||
|
return optname_accessor(i - OLEVELS_NUM - 1);
|
||
|
}
|
||
|
}
|
||
|
#endif /* FREECIV_HAVE_LIBREADLINE */
|
||
| ... | ... | |
|
}
|
||
|
cmd_reply(CMD_TIMEOUT, caller, C_OK, _("Dynamic timeout set to "
|
||
|
"%d %d %d %d"),
|
||
|
game.server.timeoutint, game.server.timeoutintinc,
|
||
|
game.server.timeoutinc, game.server.timeoutincmult);
|
||
|
"%d %d %d %d"),
|
||
|
game.server.timeoutint, game.server.timeoutintinc,
|
||
|
game.server.timeoutinc, game.server.timeoutincmult);
|
||
|
/* if we set anything here, reset the counter */
|
||
|
/* If we set anything here, reset the counter */
|
||
|
game.server.timeoutcounter = 1;
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
result = match_prefix(optname_accessor, settings_number(),
|
||
|
0, fc_strncasecmp, NULL, name, &ind);
|
||
|
0, fc_strncasecmp, nullptr, name, &ind);
|
||
|
if (M_PRE_AMBIGUOUS > result) {
|
||
|
return ind;
|
||
|
} else if (M_PRE_AMBIGUOUS == result) {
|
||
| ... | ... | |
|
FC_FREE(help);
|
||
|
}
|
||
|
cmd_reply(help_cmd, caller, C_COMMENT,
|
||
|
_("Status: %s"), (setting_is_changeable(pset, NULL, NULL, 0)
|
||
|
_("Status: %s"), (setting_is_changeable(pset, nullptr,
|
||
|
nullptr, 0)
|
||
|
? _("changeable") : _("fixed")));
|
||
|
if (setting_is_visible(pset, caller)) {
|
||
| ... | ... | |
|
Only show options which the caller can SEE.
|
||
|
**************************************************************************/
|
||
|
static void show_help_option_list(struct connection *caller,
|
||
|
enum command_id help_cmd)
|
||
|
enum command_id help_cmd)
|
||
|
{
|
||
|
cmd_reply(help_cmd, caller, C_COMMENT, horiz_line);
|
||
|
cmd_reply(help_cmd, caller, C_COMMENT,
|
||
|
_("Explanations are available for the following server options:"));
|
||
|
_("Explanations are available for the following server options:"));
|
||
|
cmd_reply(help_cmd, caller, C_COMMENT, horiz_line);
|
||
|
if (!caller && con_get_style()) {
|
||
|
settings_iterate(SSET_ALL, pset) {
|
||
| ... | ... | |
|
} else {
|
||
|
show_help_option_list(caller, CMD_EXPLAIN);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
static bool wall(char *str, bool check)
|
||
|
{
|
||
|
if (!check) {
|
||
|
notify_conn(NULL, NULL, E_MESSAGE_WALL, ftc_server_prompt,
|
||
|
notify_conn(nullptr, nullptr, E_MESSAGE_WALL, ftc_server_prompt,
|
||
|
_("Server Operator: %s"), str);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
if (c == bufsize) {
|
||
|
/* Truncated */
|
||
|
cmd_reply(CMD_CONNECTMSG, caller, C_WARNING,
|
||
|
_("Connectmsg truncated to %u bytes."), bufsize);
|
||
|
_("Connectmsg truncated to %u bytes."), bufsize);
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
| ... | ... | |
|
case AI_LEVEL_COUNT : return CMD_NORMAL;
|
||
|
}
|
||
|
log_error("Unknown AI level variant: %d.", level);
|
||
|
return CMD_NORMAL;
|
||
|
}
|
||
| ... | ... | |
|
void set_ai_level_direct(struct player *pplayer, enum ai_level level)
|
||
|
{
|
||
|
set_ai_level_directer(pplayer, level);
|
||
|
send_player_info_c(pplayer, NULL);
|
||
|
cmd_reply(cmd_of_level(level), NULL, C_OK,
|
||
|
_("Player '%s' now has AI skill level '%s'."),
|
||
|
player_name(pplayer),
|
||
|
ai_level_translated_name(level));
|
||
|
|
||
|
send_player_info_c(pplayer, nullptr);
|
||
|
cmd_reply(cmd_of_level(level), nullptr, C_OK,
|
||
|
_("Player '%s' now has AI skill level '%s'."),
|
||
|
player_name(pplayer),
|
||
|
ai_level_translated_name(level));
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
| ... | ... | |
|
return TRUE;
|
||
|
}
|
||
|
set_ai_level_directer(pplayer, level);
|
||
|
send_player_info_c(pplayer, NULL);
|
||
|
send_player_info_c(pplayer, nullptr);
|
||
|
cmd_reply(cmd_of_level(level), caller, C_OK,
|
||
|
_("Player '%s' now has AI skill level '%s'."),
|
||
|
player_name(pplayer),
|
||
|
ai_level_translated_name(level));
|
||
|
_("Player '%s' now has AI skill level '%s'."),
|
||
|
player_name(pplayer),
|
||
|
ai_level_translated_name(level));
|
||
|
} else {
|
||
|
cmd_reply(cmd_of_level(level), caller, C_FAIL,
|
||
|
_("%s is not controlled by the AI."),
|
||
|
player_name(pplayer));
|
||
|
_("%s is not controlled by the AI."),
|
||
|
player_name(pplayer));
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else if (match_result == M_PRE_EMPTY) {
|
||
| ... | ... | |
|
players_iterate(cplayer) {
|
||
|
if (is_ai(cplayer)) {
|
||
|
set_ai_level_directer(cplayer, level);
|
||
|
send_player_info_c(cplayer, NULL);
|
||
|
send_player_info_c(cplayer, nullptr);
|
||
|
cmd_reply(cmd_of_level(level), caller, C_OK,
|
||
|
_("Player '%s' now has AI skill level '%s'."),
|
||
|
player_name(cplayer),
|
||
| ... | ... | |
|
}
|
||
|
} players_iterate_end;
|
||
|
game.info.skill_level = level;
|
||
|
send_game_info(NULL);
|
||
|
send_game_info(nullptr);
|
||
|
cmd_reply(cmd_of_level(level), caller, C_OK,
|
||
|
_("Default AI skill level set to '%s'."),
|
||
|
ai_level_translated_name(level));
|
||
| ... | ... | |
|
cmd_reply_no_such_player(cmd_of_level(level), caller, name, match_result);
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
struct player *pplayer;
|
||
|
if (caller == NULL) {
|
||
|
if (caller == nullptr) {
|
||
|
cmd_reply(CMD_AWAY, caller, C_FAIL, _("This command is client only."));
|
||
|
return FALSE;
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
char *show_arg = "changed";
|
||
|
/* show changed settings only at the top level of recursion */
|
||
|
/* Show changed settings only at the top level of recursion */
|
||
|
if (read_recursion != 0) {
|
||
|
return;
|
||
|
}
|
||
|
show_settings(caller, cmd, show_arg, check);
|
||
|
if (game.ruleset_summary != NULL) {
|
||
|
if (game.ruleset_summary != nullptr) {
|
||
|
char *translated = fc_strdup(_(game.ruleset_summary));
|
||
|
fc_break_lines(translated, LINE_BREAK);
|
||
| ... | ... | |
|
return TRUE;
|
||
|
}
|
||
|
} else {
|
||
|
/* to indicate that no command was specified */
|
||
|
/* To indicate that no command was specified */
|
||
|
cmd = LOOKUP_OPTION_NO_RESULT;
|
||
|
/* Use vital level by default. */
|
||
|
level = SSET_VITAL;
|
||
| ... | ... | |
|
cmd_reply(called_as, caller, C_COMMENT, "%s", string)
|
||
|
{
|
||
|
const char *heading = NULL;
|
||
|
const char *heading = nullptr;
|
||
|
switch (level) {
|
||
|
case SSET_NONE:
|
||
|
break;
|
||
| ... | ... | |
|
heading = _("Options locked by the ruleset");
|
||
|
break;
|
||
|
case OLEVELS_NUM:
|
||
|
/* nothing */
|
||
|
/* Nothing */
|
||
|
break;
|
||
|
}
|
||
|
if (heading) {
|
||
| ... | ... | |
|
} settings_iterate_end;
|
||
|
break;
|
||
|
case OLEVELS_NUM:
|
||
|
/* nothing */
|
||
|
/* Nothing */
|
||
|
break;
|
||
|
}
|
||
| ... | ... | |
|
static char prefix[OPTION_NAME_SPACE + 4 + 1] = "";
|
||
|
char defaultness;
|
||
|
fc_assert_ret(pset != NULL);
|
||
|
fc_assert_ret(pset != nullptr);
|
||
|
is_changed = setting_non_default(pset);
|
||
|
setting_value_name(pset, TRUE, value, sizeof(value));
|
||
| ... | ... | |
|
if (nl) {
|
||
|
char *p = strchr(nl, '\n');
|
||
|
fc_assert_action(p != NULL, break);
|
||
|
fc_assert_action(p != nullptr, break);
|
||
|
startpos = p + 1 - value;
|
||
|
}
|
||
|
} while (nl);
|
||
| ... | ... | |
|
return FALSE;
|
||
|
}
|
||
|
if (str != NULL || strlen(str) > 0) {
|
||
|
if (str != nullptr || strlen(str) > 0) {
|
||
|
sz_strlcpy(buf, str);
|
||
|
ntokens = get_tokens(buf, arg, 2, TOKEN_DELIMITERS);
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
pplayer = player_by_name_prefix(arg[0], &match_result);
|
||
|
if (pplayer == NULL) {
|
||
|
if (pplayer == nullptr) {
|
||
|
cmd_reply_no_such_player(CMD_TEAM, caller, arg[0], match_result);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
tslot = team_slot_by_rule_name(arg[1]);
|
||
|
if (NULL == tslot) {
|
||
|
if (tslot == nullptr) {
|
||
|
int teamno;
|
||
|
if (str_to_int(arg[1], &teamno)) {
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
if (NULL == tslot) {
|
||
|
if (tslot == nullptr) {
|
||
|
cmd_reply(CMD_TEAM, caller, C_SYNTAX,
|
||
|
_("No such team %s. Please give a "
|
||
|
"valid team name or number."), arg[1]);
|
||
| ... | ... | |
|
if (!check) {
|
||
|
/* Should never fail when slot given is not nullptr */
|
||
|
team_add_player(pplayer, team_new(tslot));
|
||
|
send_player_info_c(pplayer, NULL);
|
||
|
send_player_info_c(pplayer, nullptr);
|
||
|
cmd_reply(CMD_TEAM, caller, C_OK, _("Player %s set to team %s."),
|
||
|
player_name(pplayer),
|
||
|
team_slot_name_translation(tslot));
|
||
| ... | ... | |
|
res = TRUE;
|
||
|
cleanup:
|
||
|
cleanup:
|
||
|
for (i = 0; i < ntokens; i++) {
|
||
|
free(arg[i]);
|
||
|
}
|
||
| ... | ... | |
|
int count = 0;
|
||
|
const char *title;
|
||
|
if (vote_list != NULL) {
|
||
|
if (vote_list != nullptr) {
|
||
|
vote_list_iterate(vote_list, pvote) {
|
||
|
if (NULL != caller && !conn_can_see_vote(caller, pvote)) {
|
||
|
if (caller != nullptr && !conn_can_see_vote(caller, pvote)) {
|
||
|
continue;
|
||
|
}
|
||
|
/* TRANS: "Vote" or "Teamvote" is voting-as-a-process. Used as
|
||
| ... | ... | |
|
"%d against, and %d abstained out of %d players."),
|
||
|
title, pvote->vote_no, pvote->cmdline,
|
||
|
MIN(100, pvote->need_pc * 100 + 1),
|
||
|
/* TRANS: preserve leading space */
|
||
|
/* TRANS: Preserve leading space */
|
||
|
pvote->flags & VCF_NODISSENT ? _(" no dissent") : "",
|
||
|
pvote->yes, pvote->no, pvote->abstain, count_voters(pvote));
|
||
|
count++;
|
||
| ... | ... | |
|
"yes",
|
||
|
"no",
|
||
|
"abstain",
|
||
|
NULL
|
||
|
nullptr
|
||
|
};
|
||
|
static const char *vote_arg_accessor(int i)
|
||
|
{
|
||
| ... | ... | |
|
char *arg[2];
|
||
|
int ntokens = 0, i = 0, which = -1;
|
||
|
enum m_pre_result match_result;
|
||
|
struct vote *pvote = NULL;
|
||
|
struct vote *pvote = nullptr;
|
||
|
bool res = FALSE;
|
||
|
if (check) {
|
||
| ... | ... | |
|
if (ntokens == 0) {
|
||
|
show_votes(caller);
|
||
|
goto CLEANUP;
|
||
|
} else if (!conn_can_vote(caller, NULL)) {
|
||
|
} else if (!conn_can_vote(caller, nullptr)) {
|
||
|
cmd_reply(CMD_VOTE, caller, C_FAIL,
|
||
|
_("You are not allowed to use this command."));
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
match_result = match_prefix(vote_arg_accessor, VOTE_NUM, 0,
|
||
|
fc_strncasecmp, NULL, arg[0], &i);
|
||
|
fc_strncasecmp, nullptr, arg[0], &i);
|
||
|
if (match_result == M_PRE_AMBIGUOUS) {
|
||
|
cmd_reply(CMD_VOTE, caller, C_SYNTAX,
|
||
| ... | ... | |
|
res = TRUE;
|
||
|
CLEANUP:
|
||
|
CLEANUP:
|
||
|
free_tokens(arg, ntokens);
|
||
|
return res;
|
||
|
}
|
||
| ... | ... | |
|
static bool cancelvote_command(struct connection *caller,
|
||
|
char *arg, bool check)
|
||
|
{
|
||
|
struct vote *pvote = NULL;
|
||
|
struct vote *pvote = nullptr;
|
||
|
int vote_no;
|
||
|
if (check) {
|
||
| ... | ... | |
|
remove_leading_trailing_spaces(arg);
|
||
|
if (arg[0] == '\0') {
|
||
|
if (caller == NULL) {
|
||
|
if (caller == nullptr) {
|
||
|
/* Server prompt */
|
||
|
cmd_reply(CMD_CANCELVOTE, caller, C_SYNTAX,
|
||
|
/* TRANS: "vote" as a process */
|
||
| ... | ... | |
|
return FALSE;
|
||
|
} else if (!caller || conn_get_access(caller) >= ALLOW_ADMIN) {
|
||
|
clear_all_votes();
|
||
|
notify_conn(NULL, NULL, E_VOTE_ABORTED, ftc_server,
|
||
|
notify_conn(nullptr, nullptr, E_VOTE_ABORTED, ftc_server,
|
||
|
/* TRANS: "votes" as a process */
|
||
|
_("All votes have been removed."));
|
||
|
return TRUE;
|
||
| ... | ... | |
|
return FALSE;
|
||
|
}
|
||
|
fc_assert_ret_val(NULL != pvote, FALSE);
|
||
|
fc_assert_ret_val(pvote != nullptr, FALSE);
|
||
|
if (caller) {
|
||
|
notify_team(conn_get_player(vote_get_caller(pvote)),
|
||
|
NULL, E_VOTE_ABORTED, ftc_server,
|
||
|
nullptr, E_VOTE_ABORTED, ftc_server,
|
||
|
/* TRANS: "vote" as a process */
|
||
|
_("%s has canceled the vote \"%s\" (number %d)."),
|
||
|
caller->username, pvote->cmdline, pvote->vote_no);
|
||
|
} else {
|
||
|
/* Server prompt */
|
||
|
notify_team(conn_get_player(vote_get_caller(pvote)),
|
||
|
NULL, E_VOTE_ABORTED, ftc_server,
|
||
|
nullptr, E_VOTE_ABORTED, ftc_server,
|
||
|
/* TRANS: "vote" as a process */
|
||
|
_("The vote \"%s\" (number %d) has been canceled."),
|
||
|
pvote->cmdline, pvote->vote_no);
|
||
| ... | ... | |
|
return FALSE;
|
||
|
}
|
||
|
if (check) {
|
||
|
return TRUE; /* whatever! */
|
||
|
return TRUE; /* Whatever! */
|
||
|
}
|
||
|
if (str != NULL && strlen(str) > 0) {
|
||
|
if (str != nullptr && strlen(str) > 0) {
|
||
|
sz_strlcpy(buf, str);
|
||
|
ntokens = get_tokens(buf, arg, 3, TOKEN_DELIMITERS);
|
||
|
} else {
|
||
| ... | ... | |
|
goto cleanup;
|
||
|
}
|
||
|
pplayer = player_by_name_prefix(arg[1], &match_result);
|
||
|
if (pplayer == NULL) {
|
||
|
if (pplayer == nullptr) {
|
||
|
cmd_reply_no_such_player(CMD_DEBUG, caller, arg[1], match_result);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
if (BV_ISSET(pplayer->server.debug, PLAYER_DEBUG_DIPLOMACY)) {
|
||
|
BV_CLR(pplayer->server.debug, PLAYER_DEBUG_DIPLOMACY);
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy no longer debugged"),
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy no longer debugged"),
|
||
|
player_name(pplayer));
|
||
|
} else {
|
||
|
BV_SET(pplayer->server.debug, PLAYER_DEBUG_DIPLOMACY);
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy debugged"),
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy debugged"),
|
||
|
player_name(pplayer));
|
||
|
/* TODO: print some info about the player here */
|
||
|
}
|
||
|
/* TODO: Print some info about the player here */
|
||
|
}
|
||
|
} else if (ntokens > 0 && strcmp(arg[0], "tech") == 0) {
|
||
|
struct player *pplayer;
|
||
|
enum m_pre_result match_result;
|
||
| ... | ... | |
|
goto cleanup;
|
||
|
}
|
||
|
pplayer = player_by_name_prefix(arg[1], &match_result);
|
||
|
if (pplayer == NULL) {
|
||
|
if (pplayer == nullptr) {
|
||
|
cmd_reply_no_such_player(CMD_DEBUG, caller, arg[1], match_result);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
if (BV_ISSET(pplayer->server.debug, PLAYER_DEBUG_TECH)) {
|
||
|
BV_CLR(pplayer->server.debug, PLAYER_DEBUG_TECH);
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech no longer debugged"),
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech no longer debugged"),
|
||
|
player_name(pplayer));
|
||
|
} else {
|
||
|
BV_SET(pplayer->server.debug, PLAYER_DEBUG_TECH);
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech debugged"),
|
||
|
cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech debugged"),
|
||
|
player_name(pplayer));
|
||
|
/* TODO: print some info about the player here */
|
||
|
/* TODO: Print some info about the player here */
|
||
|
}
|
||
|
} else if (ntokens > 0 && strcmp(arg[0], "info") == 0) {
|
||
|
int cities = 0, players = 0, units = 0, citizen_count = 0;
|
||
| ... | ... | |
|
} players_iterate_end;
|
||
|
log_normal(_("players=%d cities=%d citizens=%d units=%d"),
|
||
|
players, cities, citizen_count, units);
|
||
|
notify_conn(game.est_connections, NULL, E_AI_DEBUG, ftc_log,
|
||
|
notify_conn(game.est_connections, nullptr, E_AI_DEBUG, ftc_log,
|
||
|
_("players=%d cities=%d citizens=%d units=%d"),
|
||
|
players, cities, citizen_count, units);
|
||
|
} else if (ntokens > 0 && strcmp(arg[0], "city") == 0) {
|
||
| ... | ... | |
|
_("Undefined argument. Usage:\n%s"),
|
||
|
command_synopsis(command_by_number(CMD_DEBUG)));
|
||
|
}
|
||
|
cleanup:
|
||
|
cleanup:
|
||
|
for (i = 0; i < ntokens; i++) {
|
||
|
free(arg[i]);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Helper to validate an argument referring to a server setting.
|
||
|
Sends error message and returns NULL on failure.
|
||
|
Sends error message and returns nullptr on failure.
|
||
|
**************************************************************************/
|
||
|
static struct setting *validate_setting_arg(enum command_id cmd,
|
||
|
struct connection *caller,
|
||
| ... | ... | |
|
fc_assert(opt >= LOOKUP_OPTION_RULESETDIR);
|
||
|
break;
|
||
|
}
|
||
|
return NULL;
|
||
|
return nullptr;
|
||
|
}
|
||
|
return setting_by_number(opt);
|
||
| ... | ... | |
|
char buf[256];
|
||
|
struct packet_chat_msg packet;
|
||
|
package_event(&packet, NULL, E_SETTING, ftc_server,
|
||
|
package_event(&packet, nullptr, E_SETTING, ftc_server,
|
||
|
_("Console: '%s' has been set to %s."), setting_name(pset),
|
||
|
setting_value_name(pset, TRUE, buf, sizeof(buf)));
|
||
|
conn_list_iterate(game.est_connections, pconn) {
|
||
| ... | ... | |
|
setting_changed(pset);
|
||
|
setting_action(pset);
|
||
|
send_server_setting(NULL, pset);
|
||
|
/*
|
||
|
* send any modified game parameters to the clients -- if sent
|
||
|
send_server_setting(nullptr, pset);
|
||
|
/*
|
||
|
* Send any modified game parameters to the clients -- if sent
|
||
|
* before S_S_RUNNING, triggers a popdown_races_dialog() call
|
||
|
* in client/packhand.c#handle_game_info()
|
||
|
* in client/packhand.c#handle_game_info()
|
||
|
*/
|
||
|
send_game_info(NULL);
|
||
|
send_game_info(nullptr);
|
||
|
reset_all_start_commands(FALSE);
|
||
|
send_server_info_to_metaserver(META_INFO);
|
||
|
}
|
||
|
cleanup:
|
||
|
cleanup:
|
||
|
free_tokens(args, nargs);
|
||
|
return ret;
|
||
|
}
|
||
| ... | ... | |
|
pset = validate_setting_arg(CMD_SET, caller, args[0]);
|
||
|
if (pset != NULL) {
|
||
|
if (pset != nullptr) {
|
||
|
setting_admin_lock_set(pset);
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
pset = validate_setting_arg(CMD_SET, caller, args[0]);
|
||
|
if (pset != NULL) {
|
||
|
if (pset != nullptr) {
|
||
|
setting_admin_lock_clear(pset);
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
observe a player.
|
||
|
NB: If this function returns FALSE, then callers expect that 'msg' will
|
||
|
be filled in with a NULL-terminated string containing the reason.
|
||
|
be filled in with a nullptr-terminated string containing the reason.
|
||
|
**************************************************************************/
|
||
|
static bool is_allowed_to_take(struct connection *requester,
|
||
|
struct connection *taker,
|
||
| ... | ... | |
|
bool ok = FALSE;
|
||
|
if (script_fcdb_call("user_take", requester, taker, pplayer, will_obs,
|
||
|
&ok) && ok) {
|
||
|
&ok) && ok) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
#endif /* HAVE_FCDB */
|
||
|
if (!pplayer && will_obs) {
|
||
|
/* Global observer. */
|
||
| ... | ... | |
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
} else {
|
||
|
if (!(allow = strchr(game.server.allow_take,
|
||
|
(game.info.is_new_game ? 'H' : 'h')))) {
|
||
|
if (will_obs) {
|
||
| ... | ... | |
|
static bool observe_command(struct connection *caller, char *str, bool check)
|
||
|
{
|
||
|
int i = 0, ntokens = 0;
|
||
|
char buf[MAX_LEN_CONSOLE_LINE], *arg[2], msg[MAX_LEN_MSG];
|
||
|
char buf[MAX_LEN_CONSOLE_LINE], *arg[2], msg[MAX_LEN_MSG];
|
||
|
bool is_newgame = !game_was_started();
|
||
|
enum m_pre_result result;
|
||
|
struct connection *pconn = NULL;
|
||
|
struct player *pplayer = NULL;
|
||
|
struct connection *pconn = nullptr;
|
||
|
struct player *pplayer = nullptr;
|
||
|
bool res = FALSE;
|
||
|
|
||
|
/******** PART I: fill pconn and pplayer ********/
|
||
|
/******** PART I: Fill pconn and pplayer ********/
|
||
|
sz_strlcpy(buf, str);
|
||
|
ntokens = get_tokens(buf, arg, 2, TOKEN_DELIMITERS);
|
||
|
|
||
|
/* check syntax, only certain syntax if allowed depending on the caller */
|
||
|
/* Check syntax, only certain syntax if allowed depending on the caller */
|
||
|
if (!caller && ntokens < 1) {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_SYNTAX, _("Usage:\n%s"),
|
||
|
command_synopsis(command_by_number(CMD_OBSERVE)));
|
||
|
goto end;
|
||
|
}
|
||
|
}
|
||
|
if (ntokens == 2 && (caller && caller->access_level != ALLOW_HACK)) {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_SYNTAX,
|
||
| ... | ... | |
|
goto end;
|
||
|
}
|
||
|
/* match connection if we're console, match a player if we're not */
|
||
|
/* Match connection if we're console, match a player if we're not */
|
||
|
if (ntokens == 1) {
|
||
|
if (!caller && !(pconn = conn_by_user_prefix(arg[0], &result))) {
|
||
|
cmd_reply_no_such_conn(CMD_OBSERVE, caller, arg[0], result);
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
/* get connection name then player name */
|
||
|
/* Get connection name then player name */
|
||
|
if (ntokens == 2) {
|
||
|
if (!(pconn = conn_by_user_prefix(arg[0], &result))) {
|
||
|
cmd_reply_no_such_conn(CMD_OBSERVE, caller, arg[0], result);
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
/* if we can't force other connections to observe, assign us to be pconn. */
|
||
|
/* If we can't force other connections to observe, assign us to be pconn. */
|
||
|
if (!pconn) {
|
||
|
pconn = caller;
|
||
|
}
|
||
|
/* if we have no pplayer, it means that we want to be a global observer */
|
||
|
/* If we have no pplayer, it means that we want to be a global observer */
|
||
|
/******** PART II: do the observing ********/
|
||
|
/******** PART II: Do the observing ********/
|
||
|
/* check allowtake for permission */
|
||
|
/* Check allowtake for permission */
|
||
|
if (!is_allowed_to_take(caller, pconn, pplayer, TRUE, msg, sizeof(msg))) {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_FAIL, "%s", msg);
|
||
|
goto end;
|
||
|
}
|
||
|
/* observing your own player (during pregame) makes no sense. */
|
||
|
if (NULL != pplayer
|
||
|
/* Observing your own player (during pregame) makes no sense. */
|
||
|
if (pplayer != nullptr
|
||
|
&& pplayer == pconn->playing
|
||
|
&& !pconn->observer
|
||
|
&& is_newgame
|
||
|
&& !pplayer->was_created) {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_FAIL,
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_FAIL,
|
||
|
_("%s already controls %s. Using 'observe' would remove %s"),
|
||
|
pconn->username,
|
||
|
player_name(pplayer),
|
||
| ... | ... | |
|
goto end;
|
||
|
}
|
||
|
/* attempting to observe a player you're already observing should fail. */
|
||
|
/* Attempting to observe a player you're already observing should fail. */
|
||
|
if (pplayer == pconn->playing && pconn->observer) {
|
||
|
if (pplayer) {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_FAIL,
|
||
|
_("%s is already observing %s."),
|
||
|
pconn->username,
|
||
|
player_name(pplayer));
|
||
|
_("%s is already observing %s."),
|
||
|
pconn->username,
|
||
|
player_name(pplayer));
|
||
|
} else {
|
||
|
cmd_reply(CMD_OBSERVE, caller, C_FAIL,
|
||
|
_("%s is already observing."),
|
||
|
pconn->username);
|
||
|
_("%s is already observing."),
|
||
|
pconn->username);
|
||
|
}
|
||
|
goto end;
|
||
|
}
|
||
|
res = TRUE; /* all tests passed */
|
||
|
res = TRUE; /* All tests passed */
|
||
|
if (check) {
|
||
|
goto end;
|
||
|
}
|
||
|
/* if the connection is already attached to a player,
|
||
|
/* If the connection is already attached to a player,
|
||
|
* unattach and cleanup old player (rename, remove, etc) */
|
||
|
if (TRUE) {
|
||
|
char name[MAX_LEN_NAME];
|
||
|
if (pplayer) {
|
||
|
/* if pconn->playing is removed, we'll lose pplayer */
|
||
|
/* If pconn->playing is removed, we'll lose pplayer */
|
||
|
sz_strlcpy(name, player_name(pplayer));
|
||
|
}
|
||