Adds LAN server discovery and a Local tab in the multiplayer UI so clients can find relays on the same LAN. Introduces a new F4T::LanDiscovery module (plugin/include/F4TLanDiscovery.h, plugin/src/F4TLanDiscovery.cpp) that probes LAN hosts via UDP discover (port 7778) and TCP welcome fallback (port 7777). Server-side support includes a UDP responder (server/lan_discovery.py) and integration in server_core.py to start/stop discovery. Plugin changes (F4TServerBrowserBridge/Data) add background scanning, dispatch results to the game thread, new local-server storage and events (scanLocalServers, localServersUpdated, localScanStarted/localScanFinished), and small join/recent handling updates. UI changes (ui/.../app.js and components) add localServers state, scanning UX, Recent persistence (localStorage), and join logic for local/direct entries. Docs updated (docs/protocol.md, docs/dev-log.md, server/README.md) and build script links iphlpapi. Also removes two unused exported sprite PNGs.
85 lines
2.2 KiB
JavaScript
85 lines
2.2 KiB
JavaScript
(function () {
|
|
"use strict";
|
|
|
|
var TAB_SWITCH_PROMPTS = [
|
|
{ key: "LB", label: "Prev Tab" },
|
|
{ key: "RB", label: "Next Tab" }
|
|
];
|
|
|
|
function renderIcon(key) {
|
|
if (window.CO_ControllerIcons && CO_ControllerIcons.render) {
|
|
return CO_ControllerIcons.render(key);
|
|
}
|
|
return '<span class="co-prompt-key">' + key + "</span>";
|
|
}
|
|
|
|
window.CO_ControllerPrompts = {
|
|
render: function (root, state) {
|
|
var el = root.querySelector(".co-prompts");
|
|
if (!el) return;
|
|
|
|
var prompts = CO_ControllerPrompts.getPrompts(state);
|
|
el.innerHTML = prompts.map(function (p) {
|
|
return (
|
|
'<div class="co-prompt">' +
|
|
renderIcon(p.key) +
|
|
"<span>" + p.label + "</span>" +
|
|
"</div>"
|
|
);
|
|
}).join("");
|
|
|
|
if (window.CO_ControllerGlyphs && CO_ControllerGlyphs.hydrate) {
|
|
CO_ControllerGlyphs.hydrate(el);
|
|
}
|
|
},
|
|
|
|
getPrompts: function (state) {
|
|
if (state.joinOverlay) {
|
|
if (state.joinOverlay.error) {
|
|
return [
|
|
{ key: "B", label: "Dismiss" },
|
|
{ key: "A", label: "Dismiss" }
|
|
];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
if (state.activeTab === "direct-connect") {
|
|
return TAB_SWITCH_PROMPTS.concat([
|
|
{ key: "A", label: "Connect" },
|
|
{ key: "B", label: "Back" }
|
|
]);
|
|
}
|
|
|
|
if (state.activeTab === "local") {
|
|
return TAB_SWITCH_PROMPTS.concat([
|
|
{ key: "A", label: "Join" },
|
|
{ key: "X", label: "Scan" },
|
|
{ key: "B", label: "Back" }
|
|
]);
|
|
}
|
|
|
|
if (state.focusZone === "filters") {
|
|
var isReset = state.selectedFilterIndex === CO_Filters.FILTER_ROWS.length;
|
|
return TAB_SWITCH_PROMPTS.concat([
|
|
{ key: "A", label: isReset ? "Reset" : "Change" },
|
|
{ key: "B", label: "Back" }
|
|
]);
|
|
}
|
|
|
|
if (state.focusZone === "tabs") {
|
|
return TAB_SWITCH_PROMPTS.concat([
|
|
{ key: "B", label: "Back" }
|
|
]);
|
|
}
|
|
|
|
return TAB_SWITCH_PROMPTS.concat([
|
|
{ key: "A", label: "Join" },
|
|
{ key: "X", label: "Refresh" },
|
|
{ key: "Y", label: "Favorite" },
|
|
{ key: "B", label: "Back" }
|
|
]);
|
|
}
|
|
};
|
|
})();
|