Files
Krzak.org/mc.html
2026-01-16 20:59:02 +01:00

654 lines
22 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<title>Krzak.org - Minecraft</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css" />
<style>
.server-status-widget {
background: var(--link-bg);
border-radius: 16px;
padding: 24px;
border: 1px solid var(--container-border);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.3);
margin: 24px 0;
transition: all 0.3s ease;
}
.server-status-widget:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.4);
border-color: var(--link-hover-border);
}
.status-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 12px;
}
.status-title {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.3rem;
font-weight: 600;
color: var(--accent-color);
}
.status-indicator {
width: 16px;
height: 16px;
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
}
.status-indicator.online {
background-color: #4ade80;
box-shadow: 0 0 12px #4ade80;
}
.status-indicator.offline {
background-color: #f87171;
box-shadow: 0 0 12px #f87171;
animation: none;
}
@keyframes pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.7;
transform: scale(1.1);
}
}
.status-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 16px;
animation: fadeSlideUp 0.5s ease-out forwards 0.2s;
}
@keyframes fadeSlideUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.info-card {
background: rgba(255, 255, 255, 0.03);
border-radius: 12px;
padding: 16px;
border: 1px solid var(--container-border);
transition: all 0.2s ease;
}
.info-card:hover {
transform: scale(1.02);
background: rgba(255, 255, 255, 0.08);
border-color: var(--accent-color);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.info-card.copyable {
cursor: pointer;
}
.info-label {
font-size: 0.85rem;
color: var(--text-muted);
margin-bottom: 6px;
font-weight: 500;
}
.info-value {
font-size: 1.3rem;
color: var(--text-color);
font-weight: 600;
word-break: break-all;
}
.server-motd {
background: rgba(0, 0, 0, 0.2);
border-radius: 12px;
padding: 16px;
border: 1px solid var(--container-border);
font-family: "Courier New", monospace;
color: var(--text-color);
font-size: 0.95rem;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
animation: fadeSlideUp 0.5s ease-out forwards 0.4s;
transition: all 0.2s ease;
}
.server-motd:hover {
border-color: var(--accent-color);
}
.last-updated {
font-size: 0.8rem;
color: var(--text-muted);
text-align: right;
margin-top: 12px;
animation: fadeIn 0.5s ease-out forwards 0.6s;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 0.8;
}
}
.loading {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
color: var(--text-muted);
padding: 20px;
}
.spinner {
width: 20px;
height: 20px;
border: 3px solid rgba(255, 255, 255, 0.1);
border-top-color: var(--accent-color);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.error-message {
color: #f87171;
text-align: center;
padding: 20px;
background: rgba(248, 113, 113, 0.1);
border-radius: 12px;
border: 1px solid rgba(248, 113, 113, 0.3);
}
.players-list {
margin-top: 8px;
font-size: 0.9rem;
color: var(--text-muted);
line-height: 1.5;
}
.fingerprint-widget {
background: var(--link-bg);
border-radius: 16px;
padding: 24px;
border: 1px solid var(--container-border);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.3);
margin: 24px 0;
transition: all 0.3s ease;
}
.fingerprint-widget:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.4);
border-color: var(--link-hover-border);
}
/* Copy button styles */
.info-value-wrapper {
display: flex;
align-items: center;
gap: 12px;
justify-content: space-between;
}
.copy-button {
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--container-border);
border-radius: 8px;
padding: 8px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
flex-shrink: 0;
}
.copy-button:hover {
background: rgba(255, 255, 255, 0.1);
border-color: var(--accent-color);
transform: scale(1.05);
}
.copy-button.copied {
background: rgba(74, 222, 128, 0.2);
border-color: rgba(74, 222, 128, 0.5);
}
.copy-icon {
width: 18px;
height: 18px;
color: var(--text-color);
flex-shrink: 0;
}
/* Resourcepack widget styles */
.resourcepack-widget {
background: var(--link-bg);
border-radius: 16px;
padding: 0;
border: 1px solid var(--container-border);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.3);
margin: 24px 0;
transition: all 0.3s ease;
overflow: hidden;
}
.resourcepack-widget:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.4);
border-color: var(--link-hover-border);
}
.resourcepack-link {
display: flex;
align-items: center;
gap: 16px;
padding: 20px 24px;
text-decoration: none;
color: var(--text-color);
transition: all 0.2s ease;
}
.resourcepack-link:hover {
background: rgba(255, 255, 255, 0.05);
}
.resourcepack-icon {
width: 32px;
height: 32px;
color: var(--accent-color);
flex-shrink: 0;
}
.resourcepack-link div {
flex: 1;
}
.resourcepack-link strong {
display: block;
font-size: 1.1rem;
margin-bottom: 4px;
}
.resourcepack-desc {
font-size: 0.9rem;
color: var(--text-muted);
}
.download-icon {
width: 24px;
height: 24px;
color: var(--text-muted);
flex-shrink: 0;
}
/* Disable card hover for copy cards */
#fingerprintCard {
cursor: default !important;
}
#fingerprintCard:hover {
transform: none !important;
}
</style>
</head>
<body>
<div class="container fade-in">
<h1 class="slide-down">
<span class="icon">
<img src="/icon.svg" alt="krzak.org" />
</span>
Krzak.org - Minecraft
</h1>
<div
class="server-status-widget slide-up"
style="animation-delay: 0.1s"
id="statusWidget"
>
<div class="loading">
<div class="spinner"></div>
<span>Loading server status...</span>
</div>
</div>
<div class="slide-up" style="animation-delay: 0.2s">
<h3>Instrukcja</h3>
<ol>
<li>Zainstalujcie fabric 1.21.10</li>
<li>Zainstalujcie moda AutoModpack</li>
<li>
Dołączcie na krzak.org i, kiedy o to zapyta, wklejcie
tekst z pliku automodpack_fingerprint.txt
</li>
</ol>
<h3>Polecam też dodać nasz resourcepack</h3>
<h3>
Do skinów polecam ely.by jak ktoś nie ma premium (nie musi)
</h3>
</div>
<div
class="fingerprint-widget slide-up"
style="animation-delay: 0.3s"
id="fingerprintWidget"
>
<div class="info-card" id="fingerprintCard">
<div class="info-label">AutoModpack Fingerprint</div>
<div class="info-value-wrapper">
<div class="info-value" id="fingerprintValue">
3b180a41fe913487c1c86ad79c6dc085d01a272ac2da556f4bf7379ee3a535f8
</div>
<button
class="copy-button"
data-copy-target="fingerprintValue"
title="Copy to clipboard"
>
<svg
class="copy-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect
x="9"
y="9"
width="13"
height="13"
rx="2"
ry="2"
></rect>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
></path>
</svg>
</button>
</div>
</div>
</div>
<div
class="resourcepack-widget slide-up"
style="animation-delay: 0.35s"
>
<a href="/mc/pack.zip" class="resourcepack-link">
<svg
class="resourcepack-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
></path>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</svg>
<div>
<strong>Download Resource Pack</strong>
<span class="resourcepack-desc"
>Custom vanillatweaks setup</span
>
</div>
<svg
class="download-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path
d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
></path>
<polyline points="7 10 12 15 17 10"></polyline>
<line x1="12" y1="15" x2="12" y2="3"></line>
</svg>
</a>
</div>
<ul>
<li class="slide-up" style="animation-delay: 0.4s">
<a href="/">
<strong>Back</strong>
</a>
</li>
</ul>
<div class="librecounter fade-in" style="animation-delay: 0.75s">
<span class="librecounter-text">
Indexed by
<a
href="https://librecounter.org/referer/show"
target="_blank"
>LibreCounter</a
>
</span>
<a href="https://librecounter.org/referer/show" target="_blank">
<img
src="https://librecounter.org/counter.svg"
referrerpolicy="unsafe-url"
alt="LibreCounter"
/>
</a>
</div>
</div>
<!-- Back to top button -->
<button
id="back-to-top"
class="back-to-top"
aria-label="Back to top"
title="Back to top"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
</button>
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script>
// Configuration
const SERVER_ADDRESS = "krzak.org";
const FINGERPRINT =
"3b180a41fe913487c1c86ad79c6dc085d01a272ac2da556f4bf7379ee3a535f8";
const REFRESH_INTERVAL = 30000;
// Single event listener for all copy buttons (event delegation)
document.addEventListener("click", function (e) {
const copyButton = e.target.closest(".copy-button");
if (!copyButton) return;
const target = copyButton.dataset.copyTarget;
const textToCopy =
target === "serverAddress" ? SERVER_ADDRESS : FINGERPRINT;
navigator.clipboard
.writeText(textToCopy)
.then(() => {
// Show success feedback
const originalHTML = copyButton.innerHTML;
copyButton.innerHTML =
'<svg class="copy-icon" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"></polyline></svg>';
copyButton.classList.add("copied");
setTimeout(() => {
copyButton.innerHTML = originalHTML;
copyButton.classList.remove("copied");
}, 2000);
})
.catch((err) => console.error("Failed to copy:", err));
});
// Server status functions
async function fetchServerStatus() {
try {
const response = await fetch(
`https://api.mcsrvstat.us/3/${SERVER_ADDRESS}`,
);
return await response.json();
} catch (error) {
console.error("Error fetching server status:", error);
return null;
}
}
function formatMOTD(motd) {
if (!motd) return "No MOTD available";
if (typeof motd === "object" && motd.clean) {
return Array.isArray(motd.clean)
? motd.clean.join("\n")
: motd.clean;
}
return Array.isArray(motd) ? motd.join("\n") : motd;
}
function renderStatus(data) {
const widget = document.getElementById("statusWidget");
if (!data || !data.online) {
widget.innerHTML = `
<div class="status-header">
<div class="status-title">
<div class="status-indicator offline"></div>
Server Status
</div>
</div>
<div class="error-message">
Server is currently offline or unreachable
</div>
<div class="last-updated">
Last checked: ${new Date().toLocaleTimeString()}
</div>
`;
return;
}
const playersOnline = data.players?.online || 0;
const playersMax = data.players?.max || 0;
const version = data.version || "Unknown";
const motd = formatMOTD(data.motd);
const playersList = data.players?.list || [];
widget.innerHTML = `
<div class="status-header">
<div class="status-title">
<div class="status-indicator online"></div>
Server Status
</div>
</div>
<div class="status-info">
<div class="info-card">
<div class="info-label">Players Online</div>
<div class="info-value">${playersOnline} / ${playersMax}</div>
${
playersList.length > 0
? `
<div class="players-list">
${playersList.slice(0, 10).join(", ")}${playersList.length > 10 ? "..." : ""}
</div>
`
: ""
}
</div>
<div class="info-card">
<div class="info-label">Version</div>
<div class="info-value" style="font-size: 1.1rem;">${version}</div>
</div>
<div class="info-card" id="serverAddressCard">
<div class="info-label">Server Address</div>
<div class="info-value-wrapper">
<div class="info-value" style="font-size: 1rem;">${SERVER_ADDRESS}</div>
<button class="copy-button" data-copy-target="serverAddress" title="Copy to clipboard">
<svg class="copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
</div>
</div>
${
motd
? `
<div class="info-card">
<div class="info-label">MOTD</div>
<div style="font-family: 'Courier New', monospace; font-size: 0.9rem; line-height: 1.4; color: var(--text-color); white-space: pre-wrap;">${motd}</div>
</div>
`
: ""
}
</div>
<div class="last-updated">
Last updated: ${new Date().toLocaleTimeString()}
</div>
`;
}
async function updateStatus() {
renderStatus(await fetchServerStatus());
}
// Initial load and auto-refresh
updateStatus();
setInterval(updateStatus, REFRESH_INTERVAL);
</script>
</body>
</html>