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));
|
||
}
|
||