diff -Nurd -Xfreeciv/diff_ignore freeciv/server/sernet.c aug19+firstlevelcommand/server/sernet.c --- freeciv/server/sernet.c Thu Aug 17 05:20:26 2000 +++ aug19+firstlevelcommand/server/sernet.c Sat Aug 19 22:40:35 2000 @@ -444,7 +444,7 @@ pconn->first_packet = 1; pconn->byte_swap = 0; pconn->capability[0] = '\0'; - pconn->access_level = (i?default_access_level:first_access_level); + pconn->access_level = access_level_for_next_connection(); sz_strlcpy(pconn->name, makeup_connection_name(&pconn->id)); sz_strlcpy(pconn->addr, diff -Nurd -Xfreeciv/diff_ignore freeciv/server/srv_main.c aug19+firstlevelcommand/server/srv_main.c --- freeciv/server/srv_main.c Sat Aug 19 20:29:52 2000 +++ aug19+firstlevelcommand/server/srv_main.c Sun Aug 20 03:41:00 2000 @@ -1782,6 +1782,7 @@ send_conn_info_remove(&pconn->self, &game.est_connections); send_player_info(pplayer, 0); + notify_if_first_access_level_is_available(); if (game.is_new_game && !pplayer->is_connected /* eg multiple controllers */ diff -Nurd -Xfreeciv/diff_ignore freeciv/server/stdinhand.c aug19+firstlevelcommand/server/stdinhand.c --- freeciv/server/stdinhand.c Sat Aug 19 20:29:52 2000 +++ aug19+firstlevelcommand/server/stdinhand.c Sun Aug 20 04:01:49 2000 @@ -58,8 +58,49 @@ extern int gamelog_level; -enum cmdlevel_id default_access_level = ALLOW_INFO; -enum cmdlevel_id first_access_level = ALLOW_INFO; +static enum cmdlevel_id default_access_level = ALLOW_INFO; +static enum cmdlevel_id first_access_level = ALLOW_INFO; + +static int a_connection_exists(void) +{ + conn_list_iterate(game.est_connections, pconn) { + return 1; + } + conn_list_iterate_end; + return 0; +} + +static int first_access_level_is_taken(void) +{ + conn_list_iterate(game.est_connections, pconn) { + if (pconn->access_level >= first_access_level) { + return 1; + } + } + conn_list_iterate_end; + return 0; +} + +enum cmdlevel_id access_level_for_next_connection(void) +{ + if ((first_access_level > default_access_level) + && !a_connection_exists()) { + return first_access_level; + } else { + return default_access_level; + } +} + +void notify_if_first_access_level_is_available(void) +{ + if ((first_access_level > default_access_level) + && !first_access_level_is_taken()) { + notify_player(0, + _("Game: Anyone can assume command access level '%s' now by issuing the 'firstlevel' command."), + cmdlevel_name(first_access_level)); + } +} + static void cut_client_connection(struct connection *caller, char *playername); static void quit_game(struct connection *caller); @@ -811,6 +852,7 @@ CMD_NORMAL, CMD_HARD, CMD_CMDLEVEL, + CMD_FIRSTLEVEL, /* potentially harmful: */ CMD_END_GAME, @@ -984,27 +1026,35 @@ "cmdlevel new\n" "cmdlevel first\n" "cmdlevel "), - N_("Query or set command-level access."), - N_("The command-level controls which server commands are available to " - "users via the client chatline. The available levels are:\n" + N_("Query or set command access level access."), + N_("The command access level controls which server commands are available\n" + "to users via the client chatline. The available levels are:\n" " none - no commands\n" " info - informational commands only\n" " ctrl - commands that affect the game and users\n" " hack - *all* commands - dangerous!\n" - "With no arguments, the current command-levels are reported.\n" + "With no arguments, the current command access levels are reported.\n" "With a single argument, the level is set for all existing " - "connections, and the default is set for future connections.\n" + "connections,\nand the default is set for future connections.\n" "If 'new' is specified, the level is set for newly connecting clients.\n" - "If 'first' is specified, the level is set for the first client connected.\n" + "If 'first come' is specified, the 'first come' level is set; it will be\n" + "granted to the first client to connect, or if there are connections\n" + "already, the first client to issue the 'firstlevel' command.\n" "If a connection name is specified, the level is set for that " "connection only.\n" - "Command-levels do not persist if a client disconnects, " + "Command access levels do not persist if a client disconnects, " "because some untrusted person could reconnect with the same name. " - "If the first client to connect disconnects, then the next client " - "to connect receives 'first' status. " "Note that this command now takes connection names, not player names." ) }, + {"firstlevel", ALLOW_INFO, /* ! */ + /* translate <> only */ + N_("firstlevel\n"), + N_("Grab the 'first come' command access level."), + N_("If 'cmdlevel first come' has been used to set a special 'first come'\n" + "command access level, this is the command to grab it with." + ) + }, {"end", ALLOW_CTRL, "end", @@ -1150,7 +1200,7 @@ Whether the caller can SEE the specified option. caller == NULL means console, which can see all. client players can see "to client" options, or if player - has command level to change option. + has command access level to change option. **************************************************************************/ static int may_view_option(struct connection *caller, int option_idx) { @@ -1839,7 +1889,7 @@ ALLOW_HACK can take away ALLOW_HACK from others... --dwp */ cmd_reply(CMD_CMDLEVEL, caller, C_FAIL, - _("Cannot decrease command level '%s' for connection '%s';" + _("Cannot decrease command access level '%s' for connection '%s';" " you only have '%s'."), cmdlevel_name(ptarget->access_level), ptarget->name, @@ -1854,7 +1904,7 @@ } /************************************************************************** - Change command level for individual player, or all, or new. + Change command access level for individual player, or all, or new. **************************************************************************/ static void cmdlevel_command(struct connection *caller, char *str) { @@ -1889,7 +1939,7 @@ _("Command level for new connections: %s"), cmdlevel_name(default_access_level)); cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT, - _("Command level for first connections: %s"), + _("Command level for first player to take it: %s"), cmdlevel_name(first_access_level)); return; } @@ -1898,12 +1948,12 @@ if ((level = cmdlevel_named(arg_level)) == ALLOW_UNRECOGNIZED) { cmd_reply(CMD_CMDLEVEL, caller, C_SYNTAX, - _("Error: command level must be one of" + _("Error: command access level must be one of" " 'none', 'info', 'ctrl', or 'hack'.")); return; } else if (caller && level > caller->access_level) { cmd_reply(CMD_CMDLEVEL, caller, C_FAIL, - _("Cannot increase command level to '%s';" + _("Cannot increase command access level to '%s';" " you only have '%s' yourself."), arg_level, cmdlevel_name(caller->access_level)); return; @@ -1938,42 +1988,42 @@ default_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("default command access level set to '%s'"), + _("Default command access level set to '%s'."), cmdlevel_name(level)); notify_player(0, _("Game: All players now have access level '%s'."), cmdlevel_name(level)); if (level > first_access_level) { first_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("first connection command access level also raised to '%s'"), + _("'First come' command access level also raised to '%s'."), cmdlevel_name(level)); } } else if (strcmp(arg_name,"new") == 0) { default_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("default command access level set to '%s'"), + _("Default command access level set to '%s'."), cmdlevel_name(level)); notify_player(0, _("Game: New connections will have access level '%s'."), cmdlevel_name(level)); if (level > first_access_level) { first_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("first connection command access level also raised to '%s'"), + _("'First come' command access level also raised to '%s'."), cmdlevel_name(level)); } } else if (strcmp(arg_name,"first") == 0) { first_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("first connection command access level set to '%s'"), + _("'First come' command access level set to '%s'."), cmdlevel_name(level)); - notify_player(0, _("Game: First connections will have access level '%s'."), + notify_player(0, _("Game: 'First come' command access level set to '%s'."), cmdlevel_name(level)); if (level < default_access_level) { default_access_level = level; cmd_reply(CMD_CMDLEVEL, caller, C_OK, - _("default command access level also lowered to '%s'"), + _("Default command access level also lowered to '%s'."), cmdlevel_name(level)); } } @@ -1983,7 +2033,7 @@ _("Command access level set to '%s' for connection %s."), cmdlevel_name(level), ptarget->name); } else { - cmd_reply(CMD_CMDLEVEL, caller, C_OK, + cmd_reply(CMD_CMDLEVEL, caller, C_FAIL, _("Command access level could not be set to '%s'" " for connection %s."), cmdlevel_name(level), ptarget->name); @@ -1993,6 +2043,37 @@ } } +/************************************************************************** + This special command to set the command access level is not included into + cmdlevel_command because of its lower access level: it can be used + to promote one's own connection to 'first come' cmdlevel if that isn't + already taken. + **************************************************************************/ +static void firstlevel_command(struct connection *caller) +{ + if (!caller) { + cmd_reply(CMD_FIRSTLEVEL, caller, C_FAIL, + _("THe 'firstlevel' command makes no sense from the server command line.")); + } 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)); + } else if (first_access_level_is_taken()) { + cmd_reply(CMD_FIRSTLEVEL, caller, C_FAIL, + _("Someone else already has command access level '%s' or better."), + cmdlevel_name(first_access_level)); + } else { + caller->access_level = first_access_level; + cmd_reply(CMD_FIRSTLEVEL, caller, C_OK, + _("Your command access level has been increased to '%s'."), + cmdlevel_name(first_access_level)); + notify_player(0, + _("Game: Connection '%s' has grabbed 'first come' access level, '%s'."), + caller->name, cmdlevel_name(first_access_level)); + } +} + + static const char *optname_accessor(int i) { return settings[i].name; } @@ -2585,6 +2666,9 @@ case CMD_CMDLEVEL: cmdlevel_command(caller,arg); break; + case CMD_FIRSTLEVEL: + firstlevel_command(caller); + break; case CMD_START_GAME: if (server_state==PRE_GAME_STATE) { int plrs=0; @@ -2888,12 +2972,14 @@ cmd_reply_help(CMD_AITOGGLE, _("ai P - toggles AI on player")); cmd_reply_help(CMD_CMDLEVEL, - _("cmdlevel - see current command levels")); + _("cmdlevel - see current command access levels")); cmd_reply_help(CMD_CMDLEVEL, _("cmdlevel L - sets command access level to L for all players")); cmd_reply_help(CMD_CMDLEVEL, _("cmdlevel L new - sets command access level to L for new connections")); cmd_reply_help(CMD_CMDLEVEL, + _("cmdlevel L first - puts command access level L up for grabs")); + cmd_reply_help(CMD_CMDLEVEL, _("cmdlevel L P - sets command access level to L for player P")); cmd_reply_help(CMD_CREATE, _("create P - creates an AI player")); @@ -2907,6 +2993,8 @@ _("explain - help on server options")); cmd_reply_help(CMD_EXPLAIN, _("explain T - help on a particular server option")); + cmd_reply_help(CMD_FIRSTLEVEL, + _("firstlevel - grabs 'first come' command access level")); cmd_reply_help(CMD_HARD, _("hard - all AI players will be hard")); cmd_reply_help(CMD_HARD, @@ -3048,7 +3136,7 @@ cmd_reply(CMD_LIST, caller, C_COMMENT, "%s", buf); conn_list_iterate(pplayer->connections, pconn) { - my_snprintf(buf, sizeof(buf), _(" %s from %s (command level %s)"), + my_snprintf(buf, sizeof(buf), _(" %s from %s (command access level %s)"), pconn->name, pconn->addr, cmdlevel_name(pconn->access_level)); if (pconn->observer) { @@ -3079,7 +3167,7 @@ conn_list_iterate(game.all_connections, pconn) { sz_strlcpy(buf, conn_description(pconn)); if (pconn->established) { - cat_snprintf(buf, sizeof(buf), " command level %s", + cat_snprintf(buf, sizeof(buf), " command access level %s", cmdlevel_name(pconn->access_level)); } cmd_reply(CMD_LIST, caller, C_COMMENT, "%s", buf); diff -Nurd -Xfreeciv/diff_ignore freeciv/server/stdinhand.h aug19+firstlevelcommand/server/stdinhand.h --- freeciv/server/stdinhand.h Tue Aug 8 14:20:12 2000 +++ aug19+firstlevelcommand/server/stdinhand.h Sun Aug 20 03:40:42 2000 @@ -33,7 +33,9 @@ char **freeciv_completion(char *text, int start, int end); #endif -extern enum cmdlevel_id default_access_level; /* for sernet.c in */ -extern enum cmdlevel_id first_access_level; /* initing a new connection */ +extern enum cmdlevel_id access_level_for_next_connection(void); + /* for sernet.c in initing a new connection */ + +extern void notify_if_first_access_level_is_available(void); #endif /* FC__STDINHAND_H */