diff --git a/index.html b/index.html index 75576ac..6dfc839 100644 --- a/index.html +++ b/index.html @@ -33,6 +33,9 @@
  • Wiki
  • +
  • + Server List +
  • @@ -51,10 +54,11 @@ diff --git a/servers/index.html b/servers/index.html new file mode 100644 index 0000000..fab5812 --- /dev/null +++ b/servers/index.html @@ -0,0 +1,93 @@ + + + + + + My-MC.Link | Server List + + + + + + + + + + + + + +
    +
    +
    +
    +
    + +
    +
    +
    +

    + My-MC.Link Servers

    +

    Explore Public Minecraft Servers

    +
    + + +
    +
    + +
    +
    +

    + Public Server List

    +

    + Discover servers publically hosted on My-MC.
    Our public Realms list resets daily at 12 AM EST daily. +

    +
    + +
    +
    + +
    +

    Loading servers...

    + +
    +
    + + + + + + + + \ No newline at end of file diff --git a/servers/server_list.js b/servers/server_list.js new file mode 100644 index 0000000..b7855f7 --- /dev/null +++ b/servers/server_list.js @@ -0,0 +1,150 @@ + // Function to copy text to clipboard and trigger animation + function copyToClipboard(text, button) { + navigator.clipboard.writeText(text).then(() => { + button.classList.add('copied'); + setTimeout(() => { + button.classList.remove('copied'); + }, 2000); + }).catch(err => { + console.error('Failed to copy:', err); + }); + } + + // Function to create a server card + function createServerCard(server, isNew = false) { + const ownerName = server.ops && server.ops.length > 0 ? server.ops[0].name : 'Unknown'; + const serverCard = document.createElement('div'); + serverCard.className = `feature-card tilt-card ${isNew ? 'new-server-animation' : ''}`; + serverCard.dataset.connect = server.connect; // Add identifier + serverCard.innerHTML = ` +
    + +

    ${ownerName}'s Server

    +
    +

    MOTD: ${server.motd}

    +

    Version: ${server.gameVersion}

    +

    Gamemode: ${server.gamemode}

    +

    Hardcore: ${server.hardcore ? 'Yes' : 'No'}

    +

    Status: ${server.online ? 'Online' : 'Offline'}

    +
    + Connect: + ${server.connect} + +
    + `; + return serverCard; + } + + // Function to update server list dynamically + function updateServerList(newServers) { + const serverList = document.getElementById('server-list'); + const currentCards = Array.from(serverList.children); + const currentConnects = currentCards.map(card => card.dataset.connect); + const newConnects = newServers.map(server => server.connect); + + // Find new servers + const serversToAdd = newServers.filter(server => !currentConnects.includes(server.connect)); + const serversToRemove = currentCards.filter(card => !newConnects.includes(card.dataset.connect)); + + // Remove old servers + serversToRemove.forEach(card => { + card.style.opacity = '0'; + card.style.transform = 'translateY(20px)'; + setTimeout(() => card.remove(), 300); + }); + + // Add new servers with animation + serversToAdd.forEach(server => { + const newCard = createServerCard(server, true); + serverList.insertBefore(newCard, serverList.firstChild); + }); + + // Update existing servers + newServers.forEach(server => { + const existingCard = currentCards.find(card => card.dataset.connect === server.connect); + if (existingCard) { + const ownerName = server.ops && server.ops.length > 0 ? server.ops[0].name : 'Unknown'; + const updatedCard = createServerCard(server); + existingCard.innerHTML = updatedCard.innerHTML; + existingCard.className = updatedCard.className; + } + }); + + console.log('Server list updated:', { + added: serversToAdd.length, + removed: serversToRemove.length, + total: newServers.length + }); + } + + // Function to fetch and display servers + async function fetchServers() { + const serverList = document.getElementById('server-list'); + const loadingMessage = document.getElementById('loading-message'); + const errorMessage = document.getElementById('error-message'); + const searchInput = document.getElementById('search-input'); + + try { + const response = await fetch('https://api.my-mc.link/list_all_servers_public'); + const data = await response.json(); + + if (data.success && data.servers) { + loadingMessage.classList.add('hidden'); + errorMessage.classList.add('hidden'); + + // Store servers globally for search filtering + window.serverData = data.servers; + + // Initial render or update + if (serverList.children.length === 0) { + window.serverData.forEach(server => { + serverList.appendChild(createServerCard(server)); + }); + } else { + updateServerList(window.serverData); + } + + // Add search event listener (only once) + if (!searchInput.dataset.listener) { + searchInput.dataset.listener = 'true'; + searchInput.addEventListener('input', () => { + const searchTerm = searchInput.value.trim().toLowerCase(); + const filteredServers = window.serverData.filter(server => { + const ownerName = server.ops && server.ops.length > 0 ? server.ops[0].name.toLowerCase() : 'unknown'; + const motd = server.motd.toLowerCase(); + const version = server.gameVersion.toLowerCase(); + const status = server.online ? 'online' : 'offline'; + + return ( + ownerName.includes(searchTerm) || + motd.includes(searchTerm) || + version.includes(searchTerm) || + status.includes(searchTerm) + ); + }); + + updateServerList(filteredServers); + }); + } + } else { + throw new Error('No servers found'); + } + } catch (error) { + loadingMessage.classList.add('hidden'); + errorMessage.classList.remove('hidden'); + console.error('Error fetching servers:', error); + } + } + + // Initial fetch + fetchServers(); + + // Fetch servers every 60 seconds + setInterval(fetchServers, 60000); \ No newline at end of file diff --git a/servers/style.css b/servers/style.css new file mode 100644 index 0000000..ec60d27 --- /dev/null +++ b/servers/style.css @@ -0,0 +1,91 @@ +html, body { + height: 100%; + margin: 0; +} +body { + display: flex; + flex-direction: column; +} +main { + flex: 1 0 auto; +} +footer { + flex-shrink: 0; + position: sticky; + bottom: 0; + width: 100%; +} +.copy-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + background-color: rgba(45, 212, 191, 0.2); + border-radius: 4px; + transition: all 0.3s ease; + z-index: 10; +} +.copy-btn:hover { + background-color: rgba(45, 212, 191, 0.4); +} +.copy-btn.copied { + background-color: rgba(34, 197, 94, 0.4); +} +.copy-btn.copied svg.clipboard { + display: none; +} +.copy-btn.copied svg.checkmark { + display: block; + opacity: 1; + transform: scale(1); +} +.copy-btn svg { + width: 16px; + height: 16px; +} +.copy-btn svg.clipboard { + display: block; +} +.copy-btn svg.checkmark { + display: none; + opacity: 0; + transform: scale(0.5); + transition: all 0.3s ease; +} +.search-container { + max-width: 500px; + margin: 0 auto 1.5rem; +} +.search-input { + width: 100%; + padding: 0.75rem 1rem; + border: 2px solid #2DD4BF; + border-radius: 0.5rem; + background-color: rgba(255, 255, 255, 0.1); + color: white; + font-size: 1rem; + outline: none; + transition: border-color 0.3s ease; +} +.search-input:focus { + border-color: #3B82F6; +} +.search-input::placeholder { + color: rgba(255, 255, 255, 0.5); +} +.new-server-animation { + animation: slideIn 0.5s ease-out forwards; + border: 2px solid #2DD4BF; + box-shadow: 0 0 10px rgba(45, 212, 191, 0.5); +} +@keyframes slideIn { + 0% { + opacity: 0; + transform: translateY(20px) scale(0.95); + } + 100% { + opacity: 1; + transform: translateY(0) scale(1); + } +} \ No newline at end of file