(function () { "use strict"; window.CO_ServerList = { pingClass: function (ping) { if (ping <= 50) return "co-ping-good"; if (ping <= 100) return "co-ping-mid"; return "co-ping-bad"; }, isLocalHost: function (host) { if (!host) return false; return /^(127\.0\.0\.1|localhost|::1)$/i.test(String(host).trim()); }, displayName: function (server) { if (!server) return ""; var host = server.host || server.address || ""; var port = server.port > 0 ? server.port : 7777; var name = String(server.name || "").trim(); var isLocal = server.region === "Local" || CO_ServerList.isLocalHost(host); var isDirect = server.id === "direct" || name === "Direct Connect"; if (!name || isLocal || isDirect) { return (host || "127.0.0.1") + ":" + port; } return name; }, render: function (root, state) { var wrap = root.querySelector(".co-server-list-wrap"); var list = root.querySelector(".co-server-list"); if (!wrap || !list) return; wrap.className = "co-server-list-wrap" + (state.focusZone === "server-list" ? " focused" : ""); var isRecent = state.activeTab === "recent"; var isLocal = state.activeTab === "local"; if (!state.servers.length) { var emptyText = "No servers found"; if (isRecent) emptyText = "No recent servers"; else if (isLocal) { emptyText = state.isScanningLocal ? "Scanning local network..." : "No local servers found. Check the host PC is running server.py and firewall allows UDP 7778 / TCP 7777."; } list.innerHTML = '
' + emptyText + "
"; CO_ServerList.updateScrollIndicator(wrap, list); return; } list.innerHTML = state.servers.map(function (server, index) { var selected = index === state.selectedServerIndex ? " selected" : ""; var label = CO_ServerList.displayName(server); if (isRecent) { return ( '
' + '
' + '' + escapeHtml(label) + "" + "
" + "
" ); } if (isLocal) { var pingCls = CO_ServerList.pingClass(server.ping || 0); return ( '
' + '
' + '' + escapeHtml(label) + "" + "
" + '
' + "" + (server.players || 0) + "/" + (server.maxPlayers || 16) + "" + '' + (server.ping || 0) + " ms" + "
" + "
" ); } var fav = server.favorite ? " on" : ""; var pingCls = CO_ServerList.pingClass(server.ping); return ( '
' + '
' + '' + (server.favorite ? "\u2605" : "\u2606") + "" + '' + escapeHtml(label) + "" + "
" + '
' + "" + server.players + "/" + server.maxPlayers + "" + '' + server.ping + " ms" + "
" + "
" ); }).join(""); CO_ServerList.updateScrollIndicator(wrap, list); }, updateScrollIndicator: function (wrap, list) { var indicator = wrap && wrap.querySelector(".co-scroll-indicator"); if (!indicator || !list) return; var hasOverflow = list.scrollHeight > list.clientHeight + 2; indicator.classList.toggle("hidden", !hasOverflow); }, bind: function (root, onSelect) { var list = root.querySelector(".co-server-list"); if (!list) return; list.addEventListener("click", function (e) { var row = e.target.closest(".co-server-row"); if (!row) return; onSelect(parseInt(row.getAttribute("data-index"), 10)); }); list.addEventListener("dblclick", function (e) { var row = e.target.closest(".co-server-row"); if (!row) return; onSelect(parseInt(row.getAttribute("data-index"), 10)); if (window.CO_App && window.CO_App.joinSelected) { window.CO_App.joinSelected(); } }); }, scrollToSelected: function (root, index) { var list = root.querySelector(".co-server-list"); var row = list && list.querySelector('.co-server-row[data-index="' + index + '"]'); if (row) { row.scrollIntoView({ block: "nearest" }); } var wrap = root.querySelector(".co-server-list-wrap"); if (wrap && list) { CO_ServerList.updateScrollIndicator(wrap, list); } } }; function escapeHtml(value) { return String(value) .replace(/&/g, "&") .replace(//g, ">"); } function escapeAttr(value) { return String(value).replace(/"/g, """); } })();