enable most shell commands to affect a specific session
This commit is contained in:
+64
-22
@@ -24,11 +24,14 @@ void ServerShell::print_prompt() {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
shared_ptr<ProxyServer::LinkedSession> ServerShell::get_proxy_session() {
|
||||
shared_ptr<ProxyServer::LinkedSession> ServerShell::get_proxy_session(
|
||||
const string& name) {
|
||||
if (!this->state->proxy_server.get()) {
|
||||
throw runtime_error("the proxy server is disabled");
|
||||
}
|
||||
return this->state->proxy_server->get_session();
|
||||
return name.empty()
|
||||
? this->state->proxy_server->get_session()
|
||||
: this->state->proxy_server->get_session_by_name(name);
|
||||
}
|
||||
|
||||
static void set_boolean(bool* target, const string& args) {
|
||||
@@ -68,12 +71,23 @@ static string get_quoted_string(string& s) {
|
||||
}
|
||||
|
||||
void ServerShell::execute_command(const string& command) {
|
||||
// find the entry in the command table and run the command
|
||||
// Find the entry in the command table and run the command
|
||||
size_t command_end = skip_non_whitespace(command, 0);
|
||||
size_t args_begin = skip_whitespace(command, command_end);
|
||||
string command_name = command.substr(0, command_end);
|
||||
string command_args = command.substr(args_begin);
|
||||
|
||||
string session_name;
|
||||
if (command_name == "on") {
|
||||
size_t session_name_end = skip_non_whitespace(command_args, 0);
|
||||
size_t command_begin = skip_whitespace(command_args, session_name_end);
|
||||
command_end = skip_non_whitespace(command_args, command_begin);
|
||||
args_begin = skip_whitespace(command_args, command_end);
|
||||
session_name = command_args.substr(0, session_name_end);
|
||||
command_name = command_args.substr(command_begin, command_end - command_begin);
|
||||
command_args = command_args.substr(args_begin);
|
||||
}
|
||||
|
||||
if (command_name == "exit") {
|
||||
throw exit_shell();
|
||||
|
||||
@@ -144,9 +158,10 @@ Server commands:\n\
|
||||
Show the current state of a tournament. The quotes are required unless the\n\
|
||||
tournament name contains no spaces.\n\
|
||||
\n\
|
||||
Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
Proxy commands:\n\
|
||||
sc <data>\n\
|
||||
Send a command to the client.\n\
|
||||
Send a command to the client. This command also can be used to send data to\n\
|
||||
a client on the game server.\n\
|
||||
ss <data>\n\
|
||||
Send a command to the server.\n\
|
||||
chat <text>\n\
|
||||
@@ -203,6 +218,15 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
Set the next item to be dropped as if the client had run the $item command.\n\
|
||||
close-idle-sessions\n\
|
||||
Closes all sessions that don\'t have a client and server connected.\n\
|
||||
\n\
|
||||
If there are multiple clients connected, or multiple proxy sessions open, many\n\
|
||||
of the above commands will fail since they can\'t determine which session should\n\
|
||||
be affected. To specify a session, prefix the command with `on <ident>`. For\n\
|
||||
game server sessions, <ident> may be the client\'s ID (e.g. C-3), player name,\n\
|
||||
license serial number (specified in hex or in decimal), or BB account username.\n\
|
||||
For proxy sessions, <ident> may only be the session ID (which is generally the\n\
|
||||
same as the client\'s serial number). For example, to send a ping to the proxy\n\
|
||||
session with ID 17205AE4, run the command `on 17205AE4 sc 1D 00 04 00`.\n\
|
||||
");
|
||||
|
||||
|
||||
@@ -473,7 +497,7 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
|
||||
shared_ptr<ProxyServer::LinkedSession> proxy_session;
|
||||
try {
|
||||
proxy_session = this->get_proxy_session();
|
||||
proxy_session = this->get_proxy_session(session_name);
|
||||
} catch (const exception&) { }
|
||||
|
||||
if (proxy_session.get()) {
|
||||
@@ -488,12 +512,30 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
throw runtime_error("cannot send to server in non-proxy session");
|
||||
}
|
||||
|
||||
auto c = this->state->game_server->get_client();
|
||||
send_command_with_header(c->channel, data.data(), data.size());
|
||||
shared_ptr<Client> c;
|
||||
if (session_name.empty()) {
|
||||
c = this->state->game_server->get_client();
|
||||
} else {
|
||||
auto clients = this->state->game_server->get_clients_by_identifier(
|
||||
session_name);
|
||||
if (clients.empty()) {
|
||||
throw runtime_error("no such client");
|
||||
}
|
||||
if (clients.size() > 1) {
|
||||
throw runtime_error("multiple clients found");
|
||||
}
|
||||
c = move(clients[0]);
|
||||
}
|
||||
|
||||
if (c) {
|
||||
send_command_with_header(c->channel, data.data(), data.size());
|
||||
} else {
|
||||
throw runtime_error("no client available");
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((command_name == "chat") || (command_name == "dchat")) {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
|
||||
string data(8, '\0');
|
||||
data.push_back('\x09');
|
||||
@@ -509,18 +551,18 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
session->server_channel.send(0x06, 0x00, data);
|
||||
|
||||
} else if (command_name == "marker") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
session->server_channel.send(0x89, stoul(command_args));
|
||||
|
||||
} else if (command_name == "warp") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
|
||||
uint8_t area = stoul(command_args);
|
||||
send_warp(session->client_channel, session->lobby_client_id, area);
|
||||
send_warp(session->server_channel, session->lobby_client_id, area);
|
||||
|
||||
} else if ((command_name == "info-board") || (command_name == "info-board-data")) {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
|
||||
string data;
|
||||
if (command_name == "info-board-data") {
|
||||
@@ -534,7 +576,7 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
session->server_channel.send(0xD9, 0x00, data);
|
||||
|
||||
} else if (command_name == "set-override-section-id") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
if (command_args.empty()) {
|
||||
session->options.override_section_id = -1;
|
||||
} else {
|
||||
@@ -542,7 +584,7 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
}
|
||||
|
||||
} else if (command_name == "set-override-event") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
if (command_args.empty()) {
|
||||
session->options.override_lobby_event = -1;
|
||||
} else {
|
||||
@@ -556,7 +598,7 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
}
|
||||
|
||||
} else if (command_name == "set-override-lobby-number") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
if (command_args.empty()) {
|
||||
session->options.override_lobby_number = -1;
|
||||
} else {
|
||||
@@ -564,27 +606,27 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
}
|
||||
|
||||
} else if (command_name == "set-chat-filter") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
set_boolean(&session->options.enable_chat_filter, command_args);
|
||||
|
||||
} else if (command_name == "set-infinite-hp") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
set_boolean(&session->options.infinite_hp, command_args);
|
||||
|
||||
} else if (command_name == "set-infinite-tp") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
set_boolean(&session->options.infinite_tp, command_args);
|
||||
|
||||
} else if (command_name == "set-switch-assist") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
set_boolean(&session->options.switch_assist, command_args);
|
||||
|
||||
} else if (command_name == "set-save-files" && this->state->proxy_allow_save_files) {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
set_boolean(&session->options.save_files, command_args);
|
||||
|
||||
} else if (command_name == "set-block-function-calls") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
if (command_args.empty()) {
|
||||
session->options.function_call_return_value = -1;
|
||||
} else {
|
||||
@@ -592,7 +634,7 @@ Proxy commands (these will only work when exactly one client is connected):\n\
|
||||
}
|
||||
|
||||
} else if (command_name == "set-next-item") {
|
||||
auto session = this->get_proxy_session();
|
||||
auto session = this->get_proxy_session(session_name);
|
||||
|
||||
if (session->version == GameVersion::BB) {
|
||||
throw runtime_error("proxy session is BB");
|
||||
|
||||
Reference in New Issue
Block a user