diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index 6b2d1ec2..46b6a7d9 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -927,18 +927,19 @@ void ProxyServer::LinkedSession::on_server_input() { } } -void ProxyServer::LinkedSession::send_to_end(const string& data, bool to_server) { - string name = string_printf("ProxySession:%08" PRIX32 ":shell:%s", - this->license->serial_number, to_server ? "server" : "client"); - +void ProxyServer::LinkedSession::send_to_end( + const void* data, size_t size, bool to_server) { size_t header_size = PSOCommandHeader::header_size(this->version); - if (data.size() < header_size) { + if (size < header_size) { throw runtime_error("command is too small for header"); } - if (data.size() & 3) { + if (size & 3) { throw runtime_error("command size is not a multiple of 4"); } - const auto* header = reinterpret_cast(data.data()); + const auto* header = reinterpret_cast(data); + + string name = string_printf("ProxySession:%08" PRIX32 ":shell:%s", + this->license->serial_number, to_server ? "server" : "client"); send_command( to_server ? this->server_bev.get() : this->client_bev.get(), @@ -946,11 +947,15 @@ void ProxyServer::LinkedSession::send_to_end(const string& data, bool to_server) to_server ? this->server_output_crypt.get() : this->client_output_crypt.get(), header->command(this->version), header->flag(this->version), - data.data() + header_size, - data.size() - header_size, + reinterpret_cast(data) + header_size, + size - header_size, name.c_str()); } +void ProxyServer::LinkedSession::send_to_end(const string& data, bool to_server) { + this->send_to_end(data.data(), data.size(), to_server); +} + shared_ptr ProxyServer::get_session() { if (this->serial_number_to_session.empty()) { throw runtime_error("no sessions exist"); diff --git a/src/ProxyServer.hh b/src/ProxyServer.hh index 538e6557..6ee7fba0 100644 --- a/src/ProxyServer.hh +++ b/src/ProxyServer.hh @@ -97,6 +97,7 @@ public: void on_server_input(); void on_stream_error(short events, bool is_server_stream); + void send_to_end(const void* data, size_t size, bool to_server); void send_to_end(const std::string& data, bool to_server); void disconnect(); diff --git a/src/ServerShell.cc b/src/ServerShell.cc index 42b4f8a8..04974cae 100644 --- a/src/ServerShell.cc +++ b/src/ServerShell.cc @@ -95,6 +95,8 @@ Proxy commands (these will only work when exactly one client is connected):\n\ Send a lobby marker message to the server.\n\ event \n\ Send a lobby event update to yourself.\n\ + warp \n\ + Send yourself to a specific area.\n\ ship\n\ Request the ship select menu from the server.\n\ "); @@ -279,6 +281,18 @@ Proxy commands (these will only work when exactly one client is connected):\n\ session->send_to_end(data, false); + } else if (command_name == "warp") { + auto session = this->get_proxy_session(); + + PSOSubcommand cmds[3]; + cmds[0].dword = 0x000C0060; // header (60 00 0C 00) + cmds[1].word[0] = 0x0294; + cmds[1].word[1] = session->lobby_client_id; + cmds[2].dword = stoul(command_args); + + session->send_to_end(&cmds, sizeof(cmds), false); + session->send_to_end(&cmds, sizeof(cmds), true); + } else if (command_name == "ship") { auto session = this->get_proxy_session();