netcode-revival: make room/server fields actually apply
Typing a room or relay and pressing Enter did not commit: the fields only wrote the cvar on ImGuiInputTextFlags_EnterReturnsTrue, and Enter was flaky in the game. Now: - Room code commits on every keystroke (uppercase), so the relay follows the typed code immediately. A room change re-joins the relay on the next tick instead of waiting up to the 5s heartbeat. - Relay server commits on Enter OR when the field loses focus (clicking away), so a swallowed Enter can't leave the old relay active; kept commit-on-deactivate (not per keystroke) so partial hostnames don't flap the connection while typing. - Display name commits on change (same Enter flakiness). - The network loop now splits a 'host:port' server string and uses the embedded port for both the relay resolve and the game's netcode transport, so typing '127.0.0.1:40001' works (previously it produced a broken 'host:port:port' resolve).
This commit is contained in:
parent
2bc46451fc
commit
658d727aba
2 changed files with 38 additions and 14 deletions
|
|
@ -733,11 +733,27 @@ void GhostNetworkLoop() {
|
|||
}
|
||||
|
||||
const bool debug = Debug();
|
||||
const uint16_t port = uint16_t(REXCVAR_GET(skate3_ghost_port));
|
||||
std::string server = REXCVAR_GET(skate3_ghost_server);
|
||||
if (server.empty()) {
|
||||
server = kGhostDefaultServer;
|
||||
}
|
||||
// A server string may carry its own port ("host:port"); prefer it over
|
||||
// the port slider so the relay resolve AND the game's netcode transport
|
||||
// agree on the endpoint.
|
||||
std::string host = server;
|
||||
uint16_t port = uint16_t(REXCVAR_GET(skate3_ghost_port));
|
||||
const size_t colon = server.rfind(':');
|
||||
if (colon != std::string::npos && colon != 0 &&
|
||||
colon != server.size() - 1) {
|
||||
host = server.substr(0, colon);
|
||||
try {
|
||||
const int p = std::stoi(server.substr(colon + 1));
|
||||
if (p > 0 && p <= 65535) {
|
||||
port = uint16_t(p);
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
const std::string room_str = REXCVAR_GET(skate3_ghost_room);
|
||||
char room_buf[kGhostMaxRoomLen] = {};
|
||||
uint8_t room_len = 0;
|
||||
|
|
@ -754,6 +770,13 @@ void GhostNetworkLoop() {
|
|||
g_room_len = room_len;
|
||||
}
|
||||
}
|
||||
// A typed/clicked room change re-joins the relay on the next tick
|
||||
// instead of waiting up to the heartbeat interval.
|
||||
static std::string s_last_room;
|
||||
if (room_len != 0 && s_last_room != room_str) {
|
||||
s_last_room = room_str;
|
||||
g_peer_public.last_join = 0.0;
|
||||
}
|
||||
|
||||
if (sock == GHOST_INVALID_SOCKET) {
|
||||
sock = GhostSocketCreate(/*allow_broadcast=*/true);
|
||||
|
|
@ -768,7 +791,7 @@ void GhostNetworkLoop() {
|
|||
if (server != last_server || port != last_port) {
|
||||
GhostAddr a;
|
||||
g_peer_public.configured =
|
||||
GhostResolve(server + ":" + std::to_string(port), port, &a);
|
||||
GhostResolve(host + ":" + std::to_string(port), port, &a);
|
||||
if (g_peer_public.configured) {
|
||||
g_peer_public.addr = a;
|
||||
} else {
|
||||
|
|
@ -793,7 +816,7 @@ void GhostNetworkLoop() {
|
|||
std::lock_guard<std::mutex> lock(g_mu);
|
||||
std::memcpy(active_room, g_room, g_room_len);
|
||||
}
|
||||
rex::system::XNetTransport::Instance().SetRelay(server.c_str(), port, active_room);
|
||||
rex::system::XNetTransport::Instance().SetRelay(host.c_str(), port, active_room);
|
||||
if (now - g_peer_public.last_join >= kJoinIntervalSec) {
|
||||
SendJoin(sock, g_peer_public.addr, /*ping=*/false);
|
||||
g_peer_public.last_join = now;
|
||||
|
|
|
|||
|
|
@ -97,11 +97,12 @@ void GhostDialog::OnDraw(ImGuiIO& io) {
|
|||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Room code");
|
||||
// Commits on every change so the relay follows the typed code immediately
|
||||
// (no Enter required - Enter was flaky here). Partial codes are harmless:
|
||||
// the relay just moves you to each intermediate room as you type.
|
||||
if (ImGui::InputText("##ghost_room", room_input_, sizeof(room_input_),
|
||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_CharsUppercase)) {
|
||||
REXCVAR_SET(skate3_ghost_room, std::string(room_input_));
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
// Copy the ACTIVE room (the one this player is actually in), which for an
|
||||
|
|
@ -125,10 +126,8 @@ void GhostDialog::OnDraw(ImGuiIO& io) {
|
|||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Display name");
|
||||
if (ImGui::InputText("##ghost_name", name_input_, sizeof(name_input_),
|
||||
ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
if (ImGui::InputText("##ghost_name", name_input_, sizeof(name_input_))) {
|
||||
REXCVAR_SET(skate3_ghost_name, std::string(name_input_));
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
}
|
||||
ImGui::TextDisabled("Shown on your nameplate above the ghost. Empty = "
|
||||
"your OS user name.");
|
||||
|
|
@ -174,14 +173,16 @@ void GhostDialog::OnDraw(ImGuiIO& io) {
|
|||
|
||||
ImGui::Text("Relay server (optional)");
|
||||
ImGui::PushItemWidth(-1.0f);
|
||||
if (ImGui::InputText("##ghost_server", server_input_, sizeof(server_input_),
|
||||
ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
// Commit on Enter OR when the field loses focus (clicking away), so a
|
||||
// swallowed Enter cannot leave the old server active. Not commit-on-change:
|
||||
// partial hostnames would flap the connection while typing.
|
||||
ImGui::InputText("##ghost_server", server_input_, sizeof(server_input_));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
REXCVAR_SET(skate3_ghost_server, std::string(server_input_));
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::TextDisabled("Empty = built-in default relay. No port forwarding "
|
||||
"needed on any client.");
|
||||
ImGui::TextDisabled("Empty = built-in default relay. Press Enter or click "
|
||||
"away to apply. No port forwarding needed on any client.");
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue