16 Commits
1.0.0 ... 1.0.1

Author SHA1 Message Date
Git Manager GUI
4449446770 Upload via Git Manager GUI 2026-05-28 20:22:11 +02:00
Git Manager GUI
c06a573b17 Upload via Git Manager GUI 2026-05-28 20:22:07 +02:00
Git Manager GUI
a33e1324fc Upload via Git Manager GUI 2026-05-28 20:22:02 +02:00
Git Manager GUI
01f797dcf9 Upload via Git Manager GUI 2026-05-28 20:21:58 +02:00
Git Manager GUI
7a56a2c276 Upload via Git Manager GUI 2026-05-28 20:21:54 +02:00
Git Manager GUI
53055040c6 Upload folder via GUI - js 2026-05-28 20:21:50 +02:00
Git Manager GUI
160c9c507d Upload folder via GUI - images 2026-05-28 20:21:44 +02:00
Git Manager GUI
67d1605805 Upload via Git Manager GUI 2026-05-28 20:21:41 +02:00
Git Manager GUI
1d491a58b5 Upload via Git Manager GUI 2026-05-28 20:21:39 +02:00
Git Manager GUI
1cd6742877 Upload via Git Manager GUI 2026-05-28 20:21:37 +02:00
Git Manager GUI
85b0402b68 Upload via Git Manager GUI 2026-05-28 20:21:35 +02:00
Git Manager GUI
0ee3416cf4 Upload via Git Manager GUI 2026-05-28 20:21:33 +02:00
Git Manager GUI
8eaadb0365 Upload via Git Manager GUI 2026-05-28 20:21:31 +02:00
Git Manager GUI
8504f82961 Upload via Git Manager GUI 2026-05-28 20:21:29 +02:00
Git Manager GUI
f6e7395e87 Upload via Git Manager GUI 2026-05-28 20:21:26 +02:00
Git Manager GUI
4636812f1b Upload via Git Manager GUI 2026-05-28 20:21:24 +02:00
26 changed files with 4788 additions and 1 deletions

View File

@@ -1,2 +1,60 @@
# bluesky-theme # BlueSky MC Theme — WordPress Theme
## Beschreibung
Offizielles WordPress Theme für den BlueSky Minecraft Server.
## Anforderungen
- WordPress 6.0+
- PHP 8.0+
## Installation
1. Theme-Ordner nach `/wp-content/themes/bluesky-mc/` hochladen
2. Theme im WordPress-Backend aktivieren
3. Unter **BlueSky MC → Server Settings** die Server-IP, Discord-ID und alle Einstellungen konfigurieren
## Seiten erstellen (nach Aktivierung)
Erstelle folgende Seiten und weise das jeweilige Template zu:
| Seite | Template | URL (Permalink) |
|------------|-----------------------|-----------------|
| Startseite | BlueSky - Startseite | `/` |
| Wiki | BlueSky - Wiki | `/wiki/` |
| Regeln | BlueSky - Regeln | `/regeln/` |
| Team | BlueSky - Team | `/team/` |
| Impressum | BlueSky - Impressum | `/impressum/` |
## Backend-Übersicht (im WordPress Admin)
### 🎮 BlueSky MC (Hauptmenü)
- **Server Settings**: Server-IP, Discord-ID, Skin-Typ, Version
- **Homepage Text**: Alle Texte der Startseite bearbeiten
- **Impressum**: Impressum & Datenschutz bearbeiten
### 👤 Team Mitglieder
- In-Game Namen eingeben → Skin wird automatisch geladen
- Rang, Rangfarbe (RGBA), Gruppe und Sortierung einstellbar
### 📚 Wiki Artikel
- Artikel mit vollem Text-Editor erstellen
- Kategorien für Übersicht (Taxonomie: Wiki Kategorien)
- Beitragsbild = Icon auf der Übersichtsseite
### 🛡️ Server Regeln
- Jede Regelsektion als eigener Eintrag
- Sortierung per "Reihenfolge"-Feld
### ❓ FAQs
- Frage = Titel, Antwort = Inhalt
- Erscheinen als Accordion auf der Startseite
### ⭐ Vote Links
- Vote-URL und Beschreibung eintragen
### 🎮 Spielmodi
- Name, Beschreibung, Beitragsbild (wird als Sektionsbild verwendet)
- Features kommagetrennt eintragen
## Farben & Anpassung
Farben in `/style.css` unter `:root {}` ändern:
- `--main-color`: Hauptfarbe (Standard: #39BEFF)
- `--background-color`: Hintergrund (Standard: #24272B)

3
footer.php Normal file
View File

@@ -0,0 +1,3 @@
<?php wp_footer(); ?>
</body>
</html>

139
front-page.php Normal file
View File

@@ -0,0 +1,139 @@
<?php get_header(); bluesky_navbar('home');
$server_ip = get_option('bluesky_server_ip','mc.example.com');
$disc_link = get_option('bluesky_discord_link','#');
$logo_url = bluesky_get_image('bluesky_logo_url','images/logo.png');
$header_bg = bluesky_get_image('bluesky_header_bg_url','images/header-background.jpg');
$about_img = bluesky_get_image('bluesky_about_image_url','images/teambild.png');
$copy_label = get_option('bluesky_copy_ip_btn_label','Copy IP');
$more_label = get_option('bluesky_see_more_btn_label','Siehe mehr');
?>
<style>
#header { background-image: url('<?php echo esc_url($header_bg); ?>') !important; }
#discord { background-image: url('<?php echo esc_url($header_bg); ?>') !important; }
</style>
<section id="header">
<div class="content">
<div class="left">
<div class="server-name">
<p><?php echo esc_html(get_option('bluesky_header_subtitle','Survival Minecraft Server')); ?></p>
<h1 class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></h1>
</div>
<p class="server-description"><?php echo esc_html(get_option('bluesky_header_description','Erlebe Survival, eigene Welten, Jobs, Haustiere und ein dynamisches Wirtschaftssystem.')); ?></p>
<div class="buttons">
<button class="copy-ip"><?php echo esc_html($copy_label); ?></button>
<a href="<?php echo home_url('/wiki/'); ?>"><button class="how-to-join"><?php echo esc_html($more_label); ?></button></a>
</div>
<p class="ip-copied">War Erfolgreich!</p>
</div>
<div class="right">
<img src="<?php echo esc_url($logo_url); ?>" alt="Server Logo" class="logo-img logo-img-header">
<div class="stats">
<div class="stat">
<div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/discord.png" width="40" height="40" alt="Discord"></div>
<div class="texts"><h5 class="stat-title">Discord Server</h5><p><span class="stat-number discord-online-users"></span> Online</p></div>
</div>
<div class="stat">
<div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/creeper.png" width="40" height="40" alt="MC"></div>
<div class="texts"><h5 class="stat-title">Minecraft Server</h5><p><span class="stat-number minecraft-online-players"></span> Online</p></div>
</div>
</div>
</div>
</div>
</section>
<section id="about">
<div class="content">
<div class="left">
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title1','Wer wir sind?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text1','Wir sind ein engagiertes Team aus drei kreativen Köpfen, die Minecraft lieben!')); ?></p>
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title2','Was macht BlueSky so besonders?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text2','BlueSky gibt dir die Freiheit, deine eigene Welt zu erstellen und zu erweitern.')); ?></p>
</div>
<div class="right">
<img src="<?php echo esc_url($about_img); ?>" alt="Team">
<div class="img-background"></div>
</div>
</div>
</section>
<section id="minigames">
<div class="content miniGames-list">
<?php
$gq = new WP_Query(['post_type'=>'bluesky_gamemode','posts_per_page'=>-1,'post_status'=>'publish','orderby'=>'menu_order','order'=>'ASC']);
if ($gq->have_posts()): while($gq->have_posts()): $gq->the_post();
$svcs = get_post_meta(get_the_ID(),'_bluesky_gamemode_services',true);
$svcs = $svcs ? array_map('trim',explode(',',$svcs)) : [];
$img = has_post_thumbnail() ? get_the_post_thumbnail_url(get_the_ID(),'large') : get_template_directory_uri().'/images/survival.png';
?>
<div class="game">
<div class="game-img">
<img src="<?php echo esc_url($img); ?>" alt="<?php the_title_attribute(); ?>">
</div>
<div class="info">
<h2 class="section-title"><?php the_title(); ?></h2>
<div class="game-description">
<?php the_content(); ?>
<?php if($svcs): ?><ul class="services"><?php foreach($svcs as $s): ?><li class="service"><?php echo esc_html($s); ?></li><?php endforeach; ?></ul><?php endif; ?>
</div>
</div>
</div>
<?php endwhile; wp_reset_postdata();
else: ?>
<div class="game">
<div class="game-img"><img src="<?php echo get_template_directory_uri(); ?>/images/survival.png" alt="Survival"></div>
<div class="info"><h2 class="section-title">Survival</h2><div class="game-description"><p>Tauche ein in ein einzigartiges Minecraft-Survival-Erlebnis! Erkunde eine offene Welt voller Möglichkeiten, verdiene Ingame-Geld durch verschiedene Jobs und handle mit anderen Spielern.</p><ul class="services"><li class="service">Jobs</li><li class="service">Pet</li><li class="service">Shops</li><li class="service">und mehr</li></ul></div></div>
</div>
<div class="game">
<div class="game-img"><img src="<?php echo get_template_directory_uri(); ?>/images/survival-minigames-image.jpg" alt="Spielerwelten"></div>
<div class="info"><h2 class="section-title">Spielerwelten</h2><div class="game-description"><p>Jede Spielerwelt beginnt mit einer Größe von 20x20 Blöcken, begrenzt durch eine World Border. Mit Ingame-Währung kannst du sie nach und nach erweitern.</p><ul class="services"><li class="service">Wirtschaft</li><li class="service">Lagersystem</li><li class="service">Erweiterbare Welt</li><li class="service">Freie Gestaltung</li></ul></div></div>
</div>
<?php endif; ?>
</div>
</section>
<section id="discord">
<div class="content">
<h2 class="section-title">
<?php
$txt = get_option('bluesky_discord_section_text',"Du hast ein Problem oder möchtest mit anderen in Kontakt treten?\nTritt unserem Discord bei!");
$lines = explode("\n", $txt);
foreach ($lines as $i => $line) {
echo preg_replace_callback('/\b(Problem|Discord|discord)\b/', fn($m) => '<span>'.esc_html($m[0]).'</span>', esc_html($line));
if ($i < count($lines)-1) echo '<br>';
}
?>
</h2>
<a href="<?php echo esc_url($disc_link); ?>"><button class="join-discord">Join Discord</button></a>
</div>
</section>
<section id="vote">
<div class="content">
<div class="info">
<h2 class="section-title">Warum Voten?</h2>
<p class="section-description"><?php echo esc_html(get_option('bluesky_vote_description','Durchs Voten erhältst du wertvolle Belohnungen!')); ?></p>
</div>
<div class="links voteLinks">
<?php
$vq = new WP_Query(['post_type'=>'bluesky_vote','posts_per_page'=>-1,'post_status'=>'publish']);
if ($vq->have_posts()): while($vq->have_posts()): $vq->the_post();
$vu = get_post_meta(get_the_ID(),'_bluesky_vote_url',true);
$vd = get_post_meta(get_the_ID(),'_bluesky_vote_description',true)?:'Klicke hier um jetzt zu Voten.';
?>
<a href="<?php echo esc_url($vu); ?>" class="url" target="_blank" rel="noopener">
<div class="link"><h5><?php the_title(); ?></h5><div class="link-description"><p class="description"><?php echo esc_html($vd); ?></p><div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→"></div></div></div>
</a>
<?php endwhile; wp_reset_postdata();
else: ?>
<a href="https://minecraft-server.eu/vote/index/23242" class="url">
<div class="link"><h5>servers-minecraft</h5><div class="link-description"><p class="description">Klicke hier um jetzt zu Voten.</p><div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→"></div></div></div>
</a>
<?php endif; ?>
</div>
</div>
</section>
<?php bluesky_footer(); get_footer(); ?>

1582
functions.php Normal file

File diff suppressed because it is too large Load Diff

11
header.php Normal file
View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>html,body{background:#24272B!important;margin:0;padding:0;}</style>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?> style="background:#24272B;margin:0;padding:0;">
<?php wp_body_open(); ?>

BIN
images/creeper.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

BIN
images/discord.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 KiB

BIN
images/icon2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

BIN
images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
images/namnam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
images/pfeil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 MiB

BIN
images/survival.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

BIN
images/teambild.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
images/warnung.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

139
index.php Normal file
View File

@@ -0,0 +1,139 @@
<?php get_header(); bluesky_navbar('home');
$server_ip = get_option('bluesky_server_ip','mc.example.com');
$disc_link = get_option('bluesky_discord_link','#');
$logo_url = bluesky_get_image('bluesky_logo_url','images/logo.png');
$header_bg = bluesky_get_image('bluesky_header_bg_url','images/header-background.jpg');
$about_img = bluesky_get_image('bluesky_about_image_url','images/teambild.png');
$copy_label = get_option('bluesky_copy_ip_btn_label','Copy IP');
$more_label = get_option('bluesky_see_more_btn_label','Siehe mehr');
?>
<style>
#header { background-image: url('<?php echo esc_url($header_bg); ?>') !important; }
#discord { background-image: url('<?php echo esc_url($header_bg); ?>') !important; }
</style>
<section id="header">
<div class="content">
<div class="left">
<div class="server-name">
<p><?php echo esc_html(get_option('bluesky_header_subtitle','Survival Minecraft Server')); ?></p>
<h1 class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></h1>
</div>
<p class="server-description"><?php echo esc_html(get_option('bluesky_header_description','Erlebe Survival, eigene Welten, Jobs, Haustiere und ein dynamisches Wirtschaftssystem.')); ?></p>
<div class="buttons">
<button class="copy-ip"><?php echo esc_html($copy_label); ?></button>
<a href="<?php echo home_url('/wiki/'); ?>"><button class="how-to-join"><?php echo esc_html($more_label); ?></button></a>
</div>
<p class="ip-copied">War Erfolgreich!</p>
</div>
<div class="right">
<img src="<?php echo esc_url($logo_url); ?>" alt="Server Logo" class="logo-img logo-img-header">
<div class="stats">
<div class="stat">
<div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/discord.png" width="40" height="40" alt="Discord"></div>
<div class="texts"><h5 class="stat-title">Discord Server</h5><p><span class="stat-number discord-online-users"></span> Online</p></div>
</div>
<div class="stat">
<div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/creeper.png" width="40" height="40" alt="MC"></div>
<div class="texts"><h5 class="stat-title">Minecraft Server</h5><p><span class="stat-number minecraft-online-players"></span> Online</p></div>
</div>
</div>
</div>
</div>
</section>
<section id="about">
<div class="content">
<div class="left">
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title1','Wer wir sind?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text1','Wir sind ein engagiertes Team aus drei kreativen Köpfen, die Minecraft lieben!')); ?></p>
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title2','Was macht BlueSky so besonders?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text2','BlueSky gibt dir die Freiheit, deine eigene Welt zu erstellen und zu erweitern.')); ?></p>
</div>
<div class="right">
<img src="<?php echo esc_url($about_img); ?>" alt="Team">
<div class="img-background"></div>
</div>
</div>
</section>
<section id="minigames">
<div class="content miniGames-list">
<?php
$gq = new WP_Query(['post_type'=>'bluesky_gamemode','posts_per_page'=>-1,'post_status'=>'publish','orderby'=>'menu_order','order'=>'ASC']);
if ($gq->have_posts()): while($gq->have_posts()): $gq->the_post();
$svcs = get_post_meta(get_the_ID(),'_bluesky_gamemode_services',true);
$svcs = $svcs ? array_map('trim',explode(',',$svcs)) : [];
$img = has_post_thumbnail() ? get_the_post_thumbnail_url(get_the_ID(),'large') : get_template_directory_uri().'/images/survival.png';
?>
<div class="game">
<div class="game-img">
<img src="<?php echo esc_url($img); ?>" alt="<?php the_title_attribute(); ?>">
</div>
<div class="info">
<h2 class="section-title"><?php the_title(); ?></h2>
<div class="game-description">
<?php the_content(); ?>
<?php if($svcs): ?><ul class="services"><?php foreach($svcs as $s): ?><li class="service"><?php echo esc_html($s); ?></li><?php endforeach; ?></ul><?php endif; ?>
</div>
</div>
</div>
<?php endwhile; wp_reset_postdata();
else: ?>
<div class="game">
<div class="game-img"><img src="<?php echo get_template_directory_uri(); ?>/images/survival.png" alt="Survival"></div>
<div class="info"><h2 class="section-title">Survival</h2><div class="game-description"><p>Tauche ein in ein einzigartiges Minecraft-Survival-Erlebnis! Erkunde eine offene Welt voller Möglichkeiten, verdiene Ingame-Geld durch verschiedene Jobs und handle mit anderen Spielern.</p><ul class="services"><li class="service">Jobs</li><li class="service">Pet</li><li class="service">Shops</li><li class="service">und mehr</li></ul></div></div>
</div>
<div class="game">
<div class="game-img"><img src="<?php echo get_template_directory_uri(); ?>/images/survival-minigames-image.jpg" alt="Spielerwelten"></div>
<div class="info"><h2 class="section-title">Spielerwelten</h2><div class="game-description"><p>Jede Spielerwelt beginnt mit einer Größe von 20x20 Blöcken, begrenzt durch eine World Border. Mit Ingame-Währung kannst du sie nach und nach erweitern.</p><ul class="services"><li class="service">Wirtschaft</li><li class="service">Lagersystem</li><li class="service">Erweiterbare Welt</li><li class="service">Freie Gestaltung</li></ul></div></div>
</div>
<?php endif; ?>
</div>
</section>
<section id="discord">
<div class="content">
<h2 class="section-title">
<?php
$txt = get_option('bluesky_discord_section_text',"Du hast ein Problem oder möchtest mit anderen in Kontakt treten?\nTritt unserem Discord bei!");
$lines = explode("\n", $txt);
foreach ($lines as $i => $line) {
echo preg_replace_callback('/\b(Problem|Discord|discord)\b/', fn($m) => '<span>'.esc_html($m[0]).'</span>', esc_html($line));
if ($i < count($lines)-1) echo '<br>';
}
?>
</h2>
<a href="<?php echo esc_url($disc_link); ?>"><button class="join-discord">Join Discord</button></a>
</div>
</section>
<section id="vote">
<div class="content">
<div class="info">
<h2 class="section-title">Warum Voten?</h2>
<p class="section-description"><?php echo esc_html(get_option('bluesky_vote_description','Durchs Voten erhältst du wertvolle Belohnungen!')); ?></p>
</div>
<div class="links voteLinks">
<?php
$vq = new WP_Query(['post_type'=>'bluesky_vote','posts_per_page'=>-1,'post_status'=>'publish']);
if ($vq->have_posts()): while($vq->have_posts()): $vq->the_post();
$vu = get_post_meta(get_the_ID(),'_bluesky_vote_url',true);
$vd = get_post_meta(get_the_ID(),'_bluesky_vote_description',true)?:'Klicke hier um jetzt zu Voten.';
?>
<a href="<?php echo esc_url($vu); ?>" class="url" target="_blank" rel="noopener">
<div class="link"><h5><?php the_title(); ?></h5><div class="link-description"><p class="description"><?php echo esc_html($vd); ?></p><div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→"></div></div></div>
</a>
<?php endwhile; wp_reset_postdata();
else: ?>
<a href="https://minecraft-server.eu/vote/index/23242" class="url">
<div class="link"><h5>servers-minecraft</h5><div class="link-description"><p class="description">Klicke hier um jetzt zu Voten.</p><div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→"></div></div></div>
</a>
<?php endif; ?>
</div>
</div>
</section>
<?php bluesky_footer(); get_footer(); ?>

341
js/main.js Normal file
View File

@@ -0,0 +1,341 @@
/**
* BlueSky MC Theme - main.js
*/
// =============================================
// MOBILE NAVBAR
// =============================================
const navbar = document.querySelector('.navbar');
const hamburger = document.querySelector('.hamburger');
if (hamburger) {
hamburger.addEventListener('click', () => {
navbar.classList.toggle('active');
const links = navbar.querySelector('.links');
if (links) links.classList.toggle('active');
});
}
// =============================================
// ACCORDION
// =============================================
document.querySelectorAll('.accordion-item-header').forEach(header => {
header.addEventListener('click', () => {
header.classList.toggle('active');
const body = header.nextElementSibling;
body.style.maxHeight = header.classList.contains('active') ? body.scrollHeight + 'px' : '0px';
});
});
// =============================================
// COPY IP
// =============================================
const copyIpButton = document.querySelector('.copy-ip');
const copyIpAlert = document.querySelector('.ip-copied');
const serverIp = (typeof BlueSkyConfig !== 'undefined') ? BlueSkyConfig.serverIp : 'mc.example.com';
if (copyIpButton) {
copyIpButton.addEventListener('click', () => {
try {
navigator.clipboard.writeText(serverIp);
copyIpAlert.classList.add('active');
setTimeout(() => copyIpAlert.classList.remove('active'), 5000);
} catch (e) {
if (copyIpAlert) {
copyIpAlert.textContent = 'Fehler beim Kopieren!';
copyIpAlert.classList.add('active', 'error');
setTimeout(() => { copyIpAlert.classList.remove('active','error'); copyIpAlert.textContent = 'War Erfolgreich!'; }, 5000);
}
}
});
}
// =============================================
// DISCORD ONLINE USERS
// =============================================
const discordEl = document.querySelector('.discord-online-users');
if (discordEl && typeof BlueSkyConfig !== 'undefined' && BlueSkyConfig.discordServerId) {
(async () => {
try {
const res = await fetch(`https://discord.com/api/guilds/${BlueSkyConfig.discordServerId}/widget.json`);
const data = await res.json();
discordEl.textContent = data.presence_count || '0';
} catch { discordEl.textContent = '0'; }
})();
}
// =============================================
// MINECRAFT ONLINE PLAYERS
// =============================================
const mcEl = document.querySelector('.minecraft-online-players');
if (mcEl && typeof BlueSkyConfig !== 'undefined' && BlueSkyConfig.serverIp) {
(async () => {
try {
const res = await fetch(`https://api.mcsrvstat.us/3/${BlueSkyConfig.serverIp}`);
const data = await res.json();
mcEl.textContent = data?.players?.online ?? '0';
} catch { mcEl.textContent = '0'; }
})();
}
// =============================================
// UUID LOOKUP — mehrere APIs als Fallback
// =============================================
async function getUUID(username) {
// API 1: Mojang direkt
try {
const res = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`);
if (res.ok) {
const data = await res.json();
if (data?.id) return data.id;
}
} catch {}
// API 2: PlayerDB
try {
const res = await fetch(`https://playerdb.co/api/player/minecraft/${username}`);
if (res.ok) {
const data = await res.json();
if (data?.data?.player?.raw_id) return data.data.player.raw_id;
}
} catch {}
// API 3: MCHeads
try {
const res = await fetch(`https://mc-heads.net/minecraft/profile/${username}`);
if (res.ok) {
const data = await res.json();
if (data?.id) return data.id;
}
} catch {}
return null;
}
// =============================================
// TEAM MEMBER SKINS
// =============================================
const memberSkins = document.querySelectorAll('.member-skin');
if (memberSkins.length > 0) {
const skinType = (typeof BlueSkyConfig !== 'undefined') ? BlueSkyConfig.skinType : 'bust';
memberSkins.forEach(async (img) => {
const memberDiv = img.closest('.user');
if (!memberDiv) return;
const customSkin = memberDiv.dataset.skin;
// Eigene URL gesetzt → direkt verwenden
if (customSkin && customSkin.trim().length > 0) {
img.src = customSkin;
return;
}
const inGameName = memberDiv.dataset.ingame;
if (!inGameName) return;
// Lade-Platzhalter
img.style.opacity = '0.4';
img.style.filter = 'grayscale(1)';
try {
const uuid = await getUUID(inGameName);
if (uuid) {
// visage.surgeplay.com für hohe Qualität
const skinUrl = `https://visage.surgeplay.com/${skinType}/256/${uuid}`;
img.src = skinUrl;
img.onload = () => {
img.style.opacity = '1';
img.style.filter = 'none';
};
img.onerror = () => {
// Fallback: crafthead
img.src = `https://crafthead.net/${skinType === 'bust' ? 'bust' : skinType === 'head' ? 'avatar' : 'body'}/${uuid}/256`;
img.style.opacity = '1';
img.style.filter = 'none';
};
} else {
// Kein UUID gefunden → crafthead direkt mit Username
img.src = `https://crafthead.net/bust/${inGameName}/256`;
img.style.opacity = '1';
img.style.filter = 'none';
}
} catch (e) {
img.src = `https://crafthead.net/bust/${inGameName}/256`;
img.style.opacity = '1';
img.style.filter = 'none';
console.warn('Skin load error for', inGameName, e);
}
});
}
// =============================================
// SMOOTH SCROLL
// =============================================
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const target = document.querySelector(this.getAttribute('href'));
if (target) { e.preventDefault(); target.scrollIntoView({ behavior: 'smooth' }); }
});
});
// =============================================
// WIKI SIDEBAR TOGGLE
// =============================================
(function initWikiSidebarToggle() {
const categories = document.querySelectorAll('.wiki-nav-cat');
if (!categories.length) return;
const updateCategory = (cat, isOpen) => {
const header = cat.querySelector('.wiki-nav-cat-header');
const body = cat.querySelector('.wiki-nav-cat-body');
if (!header || !body) return;
cat.classList.toggle('open', isOpen);
header.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
body.style.maxHeight = isOpen ? body.scrollHeight + 'px' : '0px';
};
categories.forEach((cat, index) => {
const header = cat.querySelector('.wiki-nav-cat-header');
const body = cat.querySelector('.wiki-nav-cat-body');
if (!header || !body) return;
const bodyId = `wiki-nav-body-${index + 1}`;
body.id = bodyId;
header.setAttribute('role', 'button');
header.setAttribute('tabindex', '0');
header.setAttribute('aria-controls', bodyId);
const initiallyOpen = cat.classList.contains('open');
updateCategory(cat, initiallyOpen);
header.addEventListener('click', () => {
const isOpen = !cat.classList.contains('open');
updateCategory(cat, isOpen);
});
header.addEventListener('keydown', (event) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
const isOpen = !cat.classList.contains('open');
updateCategory(cat, isOpen);
}
});
});
window.addEventListener('resize', () => {
categories.forEach((cat) => {
if (!cat.classList.contains('open')) return;
const body = cat.querySelector('.wiki-nav-cat-body');
if (!body) return;
body.style.maxHeight = body.scrollHeight + 'px';
});
});
})();
// =============================================
// WIKI ARTICLE ANSWER ACCORDION
// =============================================
(function initWikiAnswerAccordion() {
const accordions = document.querySelectorAll('[data-wiki-answer]');
if (!accordions.length) return;
const setOpenState = (accordion, open) => {
const toggle = accordion.querySelector('.wiki-answer-toggle');
const panel = accordion.querySelector('.wiki-answer-panel');
if (!toggle || !panel) return;
accordion.classList.toggle('is-open', open);
toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
panel.style.maxHeight = open ? panel.scrollHeight + 'px' : '0px';
};
accordions.forEach((accordion) => {
const toggle = accordion.querySelector('.wiki-answer-toggle');
if (!toggle) return;
setOpenState(accordion, false);
toggle.addEventListener('click', () => {
const shouldOpen = !accordion.classList.contains('is-open');
setOpenState(accordion, shouldOpen);
});
});
window.addEventListener('resize', () => {
accordions.forEach((accordion) => {
if (!accordion.classList.contains('is-open')) return;
const panel = accordion.querySelector('.wiki-answer-panel');
if (!panel) return;
panel.style.maxHeight = panel.scrollHeight + 'px';
});
});
})();
// =============================================
// RULES ACCORDION
// =============================================
(function initRulesAccordion() {
const cards = document.querySelectorAll('.rule-card');
if (!cards.length) return;
const setOpenState = (card, open) => {
const toggle = card.querySelector('.rule-toggle');
const panel = card.querySelector('.rule-content-panel');
if (!toggle || !panel) return;
card.classList.toggle('is-open', open);
toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
panel.style.maxHeight = open ? panel.scrollHeight + 'px' : '0px';
};
cards.forEach((card) => {
const toggle = card.querySelector('.rule-toggle');
if (!toggle) return;
setOpenState(card, false);
toggle.addEventListener('click', () => {
const shouldOpen = !card.classList.contains('is-open');
cards.forEach((otherCard) => {
if (otherCard !== card) setOpenState(otherCard, false);
});
setOpenState(card, shouldOpen);
});
});
window.addEventListener('resize', () => {
cards.forEach((card) => {
if (!card.classList.contains('is-open')) return;
const panel = card.querySelector('.rule-content-panel');
if (!panel) return;
panel.style.maxHeight = panel.scrollHeight + 'px';
});
});
})();
// =============================================
// WIKI OVERVIEW TABS
// =============================================
(function initWikiOverviewTabs() {
const tabButtons = document.querySelectorAll('.wiki-tab-button');
const tabPanels = document.querySelectorAll('.wiki-tab-panel');
if (!tabButtons.length || !tabPanels.length) return;
tabButtons.forEach((button) => {
button.addEventListener('click', () => {
const targetId = button.getAttribute('data-tab');
if (!targetId) return;
tabButtons.forEach((btn) => btn.classList.remove('active'));
tabPanels.forEach((panel) => panel.classList.remove('active'));
button.classList.add('active');
const targetPanel = document.getElementById(targetId);
if (targetPanel) targetPanel.classList.add('active');
});
});
})();

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

176
single-bluesky_wiki.php Normal file
View File

@@ -0,0 +1,176 @@
<?php
/**
* Single Wiki Article
*/
get_header();
bluesky_navbar('wiki');
$header_bg = bluesky_get_image('bluesky_header_bg_url', 'images/header-background.jpg');
the_post();
$cats = get_the_terms(get_the_ID(), 'wiki_category');
$breadcrumb = [];
if ($cats && !is_wp_error($cats)) {
$cat = $cats[0];
if ($cat->parent) {
$parent = get_term($cat->parent, 'wiki_category');
if ($parent && !is_wp_error($parent))
$breadcrumb[] = ['label' => $parent->name, 'url' => get_term_link($parent)];
}
$breadcrumb[] = ['label' => $cat->name, 'url' => get_term_link($cat)];
}
// Sidebar: alle Kategorien & Artikel
$all_top_cats = get_terms(['taxonomy'=>'wiki_category','hide_empty'=>true,'parent'=>0,'orderby'=>'menu_order']);
$current_cat_ids = wp_list_pluck($cats ?: [], 'term_id');
$current_post_id = get_the_ID();
?>
<!-- PAGE HEADER -->
<section id="page-header" style="background-image: url('<?php echo esc_url($header_bg); ?>')">
<div class="content">
<nav class="wiki-breadcrumb">
<a href="<?php echo home_url('/wiki/'); ?>">Wiki</a>
<?php foreach ($breadcrumb as $crumb): ?>
<span class="sep"></span>
<a href="<?php echo esc_url($crumb['url']); ?>"><?php echo esc_html($crumb['label']); ?></a>
<?php endforeach; ?>
<span class="sep"></span>
<span class="current"><?php the_title(); ?></span>
</nav>
<h1 class="title"><span><?php the_title(); ?></span></h1>
</div>
</section>
<!-- ARTIKEL -->
<section id="wiki-article">
<div class="content" style="padding-top:50px;padding-bottom:80px">
<div class="wiki-article-layout">
<!-- SIDEBAR -->
<aside class="wiki-sidebar">
<div class="wiki-sidebar-inner">
<h4 class="wiki-sidebar-title">📚 Navigation</h4>
<?php if (!empty($all_top_cats) && !is_wp_error($all_top_cats)):
foreach ($all_top_cats as $top_cat):
$sub_cats = get_terms(['taxonomy'=>'wiki_category','hide_empty'=>true,'parent'=>$top_cat->term_id]);
$top_articles = new WP_Query([
'post_type'=>'bluesky_wiki','posts_per_page'=>-1,'post_status'=>'publish',
'orderby'=>'title','order'=>'ASC',
'tax_query'=>[['taxonomy'=>'wiki_category','field'=>'term_id','terms'=>$top_cat->term_id,'include_children'=>false]],
]);
$is_open = in_array($top_cat->term_id, $current_cat_ids);
// Auch öffnen wenn ein Kind-Element aktiv ist
if (!$is_open && !empty($sub_cats) && !is_wp_error($sub_cats)) {
foreach ($sub_cats as $sub) {
if (in_array($sub->term_id, $current_cat_ids)) { $is_open = true; break; }
}
}
?>
<div class="wiki-nav-cat <?php echo $is_open ? 'open' : ''; ?>">
<div class="wiki-nav-cat-header">
<span><?php echo esc_html($top_cat->name); ?></span>
<span class="wiki-nav-toggle">▾</span>
</div>
<div class="wiki-nav-cat-body">
<?php if ($top_articles->have_posts()):
while ($top_articles->have_posts()): $top_articles->the_post(); ?>
<a href="<?php the_permalink(); ?>"
class="wiki-nav-link <?php echo get_the_ID() === $current_post_id ? 'active' : ''; ?>">
<?php the_title(); ?>
</a>
<?php endwhile; wp_reset_postdata(); endif; ?>
<?php if (!empty($sub_cats) && !is_wp_error($sub_cats)):
foreach ($sub_cats as $sub):
$sub_articles = new WP_Query([
'post_type'=>'bluesky_wiki','posts_per_page'=>-1,'post_status'=>'publish',
'orderby'=>'title','order'=>'ASC',
'tax_query'=>[['taxonomy'=>'wiki_category','field'=>'term_id','terms'=>$sub->term_id,'include_children'=>false]],
]);
if (!$sub_articles->have_posts()) { wp_reset_postdata(); continue; }
?>
<div class="wiki-nav-subcat">
<span class="wiki-nav-subcat-label"><?php echo esc_html($sub->name); ?></span>
<?php while ($sub_articles->have_posts()): $sub_articles->the_post(); ?>
<a href="<?php the_permalink(); ?>"
class="wiki-nav-link wiki-nav-link-sub <?php echo get_the_ID() === $current_post_id ? 'active' : ''; ?>">
<?php the_title(); ?>
</a>
<?php endwhile; wp_reset_postdata(); ?>
</div>
<?php endforeach; endif; ?>
</div>
</div>
<?php endforeach; endif; ?>
</div>
</aside>
<!-- ARTIKEL CONTENT -->
<article class="wiki-article-content">
<!-- Header -->
<div class="wiki-article-header">
<nav class="wiki-breadcrumb" style="margin-bottom:8px">
<a href="<?php echo home_url('/wiki/'); ?>">Wiki</a>
<?php foreach ($breadcrumb as $crumb): ?>
<span class="sep"></span>
<a href="<?php echo esc_url($crumb['url']); ?>"><?php echo esc_html($crumb['label']); ?></a>
<?php endforeach; ?>
</nav>
<h1><?php the_title(); ?></h1>
</div>
<?php if (has_post_thumbnail()): ?>
<div class="wiki-article-hero">
<?php the_post_thumbnail('large', ['class'=>'wiki-hero-img']); ?>
</div>
<?php endif; ?>
<!-- Body -->
<section class="wiki-answer-accordion" data-wiki-answer>
<button
type="button"
class="wiki-answer-toggle"
aria-expanded="false"
aria-controls="wiki-answer-content-<?php echo esc_attr($current_post_id); ?>"
>
<span class="wiki-answer-toggle-label">Antwort</span>
<span class="wiki-answer-toggle-hint">Zum Anzeigen aufklappen</span>
<span class="wiki-answer-toggle-icon" aria-hidden="true"></span>
</button>
<div class="wiki-answer-panel" id="wiki-answer-content-<?php echo esc_attr($current_post_id); ?>">
<div class="wiki-article-body">
<?php the_content(); ?>
</div>
</div>
</section>
<!-- Vor/Zurück -->
<?php
$prev = get_previous_post(true, '', 'wiki_category');
$next = get_next_post(true, '', 'wiki_category');
if ($prev || $next):
?>
<div class="wiki-article-nav">
<?php if ($prev): ?>
<a href="<?php echo get_permalink($prev); ?>" class="wiki-nav-prev">
<span class="label">← Vorheriger Artikel</span>
<span class="title"><?php echo esc_html(get_the_title($prev)); ?></span>
</a>
<?php else: ?><div></div><?php endif; ?>
<?php if ($next): ?>
<a href="<?php echo get_permalink($next); ?>" class="wiki-nav-next">
<span class="label">Nächster Artikel →</span>
<span class="title"><?php echo esc_html(get_the_title($next)); ?></span>
</a>
<?php endif; ?>
</div>
<?php endif; ?>
</article>
</div>
</div>
</section>
<?php bluesky_footer(); ?>
<?php get_footer(); ?>

1680
style.css Normal file

File diff suppressed because it is too large Load Diff

279
template-home.php Normal file
View File

@@ -0,0 +1,279 @@
<?php
/**
* Template Name: BlueSky - Startseite
* Template Post Type: page
*/
get_header();
bluesky_navbar('home');
$server_name = get_option('bluesky_server_name', 'BlueSky');
$server_ip = get_option('bluesky_server_ip', 'mc.example.com');
$disc_link = get_option('bluesky_discord_link', '#');
$logo_url = get_template_directory_uri() . '/images/logo.png';
if (has_custom_logo()) {
$logo_id = get_theme_mod('custom_logo');
$logo_url = wp_get_attachment_image_url($logo_id, 'full');
}
?>
<!-- ===== HEADER ===== -->
<section id="header">
<div class="content">
<div class="left">
<div class="server-name">
<p><?php echo esc_html(get_option('bluesky_header_subtitle', 'Survival Minecraft Server')); ?></p>
<h1 class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></h1>
</div>
<p class="server-description">
<?php echo esc_html(get_option('bluesky_header_description', 'Erlebe Survival, eigene Welten, Jobs, Haustiere und ein dynamisches Wirtschaftssystem. Tritt unserer Community bei und starte dein Abenteuer.')); ?>
</p>
<div class="buttons">
<button class="copy-ip">Copy IP</button>
<a href="#faq"><button class="how-to-join">Siehe mehr</button></a>
</div>
<p class="ip-copied">War Erfolgreich!</p>
</div>
<div class="right">
<img src="<?php echo esc_url($logo_url); ?>" alt="Server Logo" class="logo-img logo-img-header">
<div class="stats">
<div class="stat">
<div class="icon">
<img src="<?php echo get_template_directory_uri(); ?>/images/discord.png" alt="Discord" width="40" height="40">
</div>
<div class="texts">
<h5 class="stat-title">Discord Server</h5>
<p><span class="stat-number discord-online-users">0</span> Online</p>
</div>
</div>
<div class="stat">
<div class="icon">
<img src="<?php echo get_template_directory_uri(); ?>/images/creeper.png" alt="Minecraft" width="40" height="40">
</div>
<div class="texts">
<h5 class="stat-title">Minecraft Server</h5>
<p><span class="stat-number minecraft-online-players">0</span> Online</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ===== ABOUT ===== -->
<section id="about">
<div class="content">
<div class="left">
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title1', 'Wer wir sind?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text1', 'Wir sind ein engagiertes Team aus drei kreativen Köpfen, die Minecraft lieben!')); ?></p>
<h2 class="section-title"><?php echo esc_html(get_option('bluesky_about_title2', 'Was macht BlueSky so besonders?')); ?></h2>
<p class="about-us"><?php echo esc_html(get_option('bluesky_about_text2', 'BlueSky gibt dir die Freiheit, deine eigene Welt zu erstellen.')); ?></p>
</div>
<div class="right">
<img src="<?php echo get_template_directory_uri(); ?>/images/teambild.png" alt="Team">
<div class="img-background"></div>
</div>
</div>
</section>
<!-- ===== SPIELMODI ===== -->
<section id="minigames">
<div class="content miniGames-list">
<?php
$gamemodes = new WP_Query([
'post_type' => 'bluesky_gamemode',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'menu_order',
'order' => 'ASC',
]);
if ($gamemodes->have_posts()):
while ($gamemodes->have_posts()):
$gamemodes->the_post();
$services_raw = get_post_meta(get_the_ID(), '_bluesky_gamemode_services', true);
$services = $services_raw ? array_map('trim', explode(',', $services_raw)) : [];
$thumb_url = has_post_thumbnail() ? get_the_post_thumbnail_url(get_the_ID(), 'large') : get_template_directory_uri() . '/images/survival.png';
?>
<div class="game">
<img src="<?php echo esc_url($thumb_url); ?>" alt="<?php the_title_attribute(); ?>">
<div class="info">
<h2 class="section-title"><?php the_title(); ?></h2>
<div class="game-description">
<?php the_content(); ?>
<?php if (!empty($services)): ?>
<ul class="services">
<?php foreach ($services as $service): ?>
<li class="service"><?php echo esc_html($service); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</div>
</div>
<?php
endwhile;
wp_reset_postdata();
else:
?>
<!-- Fallback: Standard-Spielmodi -->
<div class="game">
<img src="<?php echo get_template_directory_uri(); ?>/images/survival.png" alt="Survival">
<div class="info">
<h2 class="section-title">Survival</h2>
<div class="game-description">
<p>Tauche ein in ein einzigartiges Minecraft-Survival-Erlebnis! Erkunde eine offene Welt voller Möglichkeiten, verdiene Ingame-Geld durch verschiedene Jobs, sammle wertvolle Ressourcen und handle mit anderen Spielern.</p>
<ul class="services">
<li class="service">Jobs</li>
<li class="service">Pet</li>
<li class="service">Shops</li>
<li class="service">und mehr</li>
</ul>
</div>
</div>
</div>
<div class="game">
<img src="<?php echo get_template_directory_uri(); ?>/images/survival-minigames-image.jpg" alt="Spielerwelten">
<div class="info">
<h2 class="section-title">Spielerwelten</h2>
<div class="game-description">
<p>Bevor du deine eigene Welt betreten kannst, musst du sie beim Welten-NPC am Spawn generieren lassen. Jede Spielerwelt beginnt mit einer Größe von 20x20 Blöcken, begrenzt durch eine World Border.</p>
<ul class="services">
<li class="service">Wirtschaft</li>
<li class="service">Lagersystem</li>
<li class="service">Erweiterbare Welt</li>
<li class="service">Freie Gestaltung</li>
</ul>
</div>
</div>
</div>
<?php endif; ?>
</div>
</section>
<!-- ===== DISCORD ===== -->
<section id="discord">
<div class="content">
<h2 class="section-title">
<?php
$discord_text = get_option('bluesky_discord_section_text', "Du hast ein Problem oder möchtest mit anderen in Kontakt treten?\nTritt unserem Discord bei!");
$lines = explode("\n", $discord_text);
foreach ($lines as $i => $line) {
$parts = preg_split('/\b(Problem|Discord|discord)\b/i', $line, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($parts as $part) {
if (preg_match('/^(Problem|Discord|discord)$/i', $part)) {
echo '<span>' . esc_html($part) . '</span>';
} else {
echo esc_html($part);
}
}
if ($i < count($lines) - 1) echo '<br>';
}
?>
</h2>
<a href="<?php echo esc_url($disc_link); ?>" class="discord-link">
<button class="join-discord">Join Discord</button>
</a>
</div>
</section>
<!-- ===== VOTE ===== -->
<section id="vote">
<div class="content">
<div class="info">
<h2 class="section-title">Warum Voten?</h2>
<p class="section-description">
<?php echo esc_html(get_option('bluesky_vote_description', 'Durchs Voten erhältst du nicht nur wertvolle Belohnungen, sondern auch eine zeitbegrenzte Premium-Berechtigung mit zahlreichen Vorteilen!')); ?>
</p>
</div>
<div class="links voteLinks">
<?php
$votes = new WP_Query([
'post_type' => 'bluesky_vote',
'posts_per_page' => -1,
'post_status' => 'publish',
]);
if ($votes->have_posts()):
while ($votes->have_posts()):
$votes->the_post();
$vote_url = get_post_meta(get_the_ID(), '_bluesky_vote_url', true);
$vote_desc = get_post_meta(get_the_ID(), '_bluesky_vote_description', true) ?: 'Klicke hier um jetzt zu Voten.';
?>
<a href="<?php echo esc_url($vote_url); ?>" class="url" target="_blank" rel="noopener">
<div class="link">
<h5><?php the_title(); ?></h5>
<div class="link-description">
<p class="description"><?php echo esc_html($vote_desc); ?></p>
<div class="icon">
<img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→">
</div>
</div>
</div>
</a>
<?php
endwhile;
wp_reset_postdata();
else:
?>
<a href="https://minecraft-server.eu/vote/index/23242" class="url">
<div class="link">
<h5>servers-minecraft</h5>
<div class="link-description">
<p class="description">Klicke hier um jetzt zu Voten.</p>
<div class="icon">
<img src="<?php echo get_template_directory_uri(); ?>/images/pfeil.png" width="40" height="40" alt="→">
</div>
</div>
</div>
</a>
<?php endif; ?>
</div>
</div>
</section>
<!-- ===== FAQ ===== -->
<section id="faq">
<div class="content">
<div class="info">
<h2 class="section-title">Server <span>FAQs.</span></h2>
<p class="section-description"><?php echo esc_html(get_option('bluesky_faq_description', 'Meist gestellte Fragen und Antworten')); ?></p>
</div>
<div class="accordion faqList">
<?php
$faqs = new WP_Query([
'post_type' => 'bluesky_faq',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'menu_order',
'order' => 'ASC',
]);
if ($faqs->have_posts()):
while ($faqs->have_posts()):
$faqs->the_post();
?>
<div class="accordion-item">
<div class="accordion-item-header"><?php the_title(); ?></div>
<div class="accordion-item-body">
<div class="accordion-item-body-content"><?php the_content(); ?></div>
</div>
</div>
<?php
endwhile;
wp_reset_postdata();
else:
?>
<div class="accordion-item">
<div class="accordion-item-header">Wie bekomme ich meine eigene Welt?</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">Du kannst deine eigene Welt am Spawn über einen NPC namens "Welten" betreten.</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
</section>
<?php bluesky_footer(); ?>
<?php get_footer(); ?>

38
template-impressum.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
/**
* Template Name: BlueSky - Impressum
* Template Post Type: page
*/
get_header();
bluesky_navbar();
$server_ip = get_option('bluesky_server_ip', 'mc.example.com');
?>
<section id="page-header">
<div class="content">
<div class="info">
<p class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></p>
<h1 class="title"><span>Impressum</span></h1>
</div>
<p class="description">Impressum & Datenschutzerklärung</p>
</div>
</section>
<section id="impressum">
<div class="content">
<div class="impressum-content" id="impressum">
<?php echo wp_kses_post(get_option('bluesky_impressum_content', '<h2>Impressum</h2><p>Bitte im Backend unter BlueSky MC → Impressum eintragen.</p>')); ?>
</div>
<hr style="border-color: var(--border-color); margin: 60px 0;">
<div class="impressum-content" id="datenschutz">
<?php echo wp_kses_post(get_option('bluesky_datenschutz_content', '<h2>Datenschutzerklärung</h2><p>Bitte im Backend unter BlueSky MC → Impressum eintragen.</p>')); ?>
</div>
</div>
</section>
<?php bluesky_footer(); ?>
<?php get_footer(); ?>

79
template-regeln.php Normal file
View File

@@ -0,0 +1,79 @@
<?php
/**
* Template Name: BlueSky - Regeln
*/
get_header(); bluesky_navbar('rules');
$server_ip = get_option('bluesky_server_ip','mc.example.com');
$header_bg = bluesky_get_image('bluesky_header_bg_url','images/header-background.jpg');
$warn_text = get_option('bluesky_rules_warning_text','Achtung: Bei einer Abwesenheit von mehr als 90 Tagen werden alle Spielerinformationen und Daten gelöscht.');
?>
<section id="page-header" style="background-image:url('<?php echo esc_url($header_bg); ?>')">
<div class="content">
<p class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></p>
<h1 class="title"><span>Regeln</span></h1>
<p class="description">Liste aller Minecraft-Regeln.</p>
</div>
</section>
<section id="rules">
<div class="content">
<div class="warning">
<p><strong><?php echo esc_html($warn_text); ?></strong></p>
<div class="icon"><img src="<?php echo get_template_directory_uri(); ?>/images/warnung.png" alt="Warnung" width="40" height="40"></div>
</div>
<?php
$rq = new WP_Query(['post_type'=>'bluesky_rule','posts_per_page'=>-1,'post_status'=>'publish','meta_key'=>'_bluesky_rule_sort_order','orderby'=>'meta_value_num','order'=>'ASC']);
if ($rq->have_posts()): ?>
<div class="rules-listing">
<?php while($rq->have_posts()): $rq->the_post();
$sid = get_post_meta(get_the_ID(),'_bluesky_rule_section_id',true)?:'regel-'.get_the_ID();
$items_raw = get_post_meta(get_the_ID(), '_bluesky_rule_items', true);
$rule_items = array_values(array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', (string) $items_raw))));
$panel_id = 'rule-panel-' . get_the_ID();
?>
<article id="<?php echo esc_attr($sid); ?>" class="rule-card">
<button type="button" class="rule-toggle" aria-expanded="false" aria-controls="<?php echo esc_attr($panel_id); ?>">
<span class="rule-toggle-icon" aria-hidden="true"></span>
<span class="rules-title"><?php the_title(); ?></span>
</button>
<div class="rule-content-panel" id="<?php echo esc_attr($panel_id); ?>">
<?php if (!empty($rule_items)): ?>
<ul class="rule-items">
<?php foreach ($rule_items as $item): ?>
<li class="rule-item-line"><?php echo esc_html($item); ?></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<ul class="rule-items">
<li class="rule-item-line">Noch keine Regeln hinterlegt.</li>
</ul>
<?php endif; ?>
</div>
</article>
<?php endwhile; wp_reset_postdata(); ?>
</div>
<?php else: ?>
<div class="rules-listing">
<article id="regel-1" class="rule-card">
<button type="button" class="rule-toggle" aria-expanded="false" aria-controls="rule-panel-fallback-1">
<span class="rule-toggle-icon" aria-hidden="true"></span>
<span class="rules-title">&sect;1. Vorwort</span>
</button>
<div class="rule-content-panel" id="rule-panel-fallback-1">
<ul class="rule-items"><li class="rule-item-line">Alle Spieler müssen sich an die folgenden Regeln halten.</li></ul>
</div>
</article>
<article id="regel-2" class="rule-card">
<button type="button" class="rule-toggle" aria-expanded="false" aria-controls="rule-panel-fallback-2">
<span class="rule-toggle-icon" aria-hidden="true"></span>
<span class="rules-title">&sect;2. Inhalte</span>
</button>
<div class="rule-content-panel" id="rule-panel-fallback-2">
<ul class="rule-items"><li class="rule-item-line">Beleidigungen, Mobbing und diskriminierende Aussagen sind verboten.</li></ul>
</div>
</article>
</div>
<?php endif; ?>
</div>
</section>
<?php bluesky_footer(); get_footer(); ?>

95
template-team.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
/**
* Template Name: BlueSky - Team
*/
get_header(); bluesky_navbar('team');
$server_ip = get_option('bluesky_server_ip','mc.example.com');
$header_bg = bluesky_get_image('bluesky_header_bg_url','images/header-background.jpg');
?>
<section id="page-header" style="background-image:url('<?php echo esc_url($header_bg); ?>')">
<div class="content">
<p class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></p>
<h1 class="title"><span>Team</span></h1>
<p class="description">Liste aller Server Team-Mitglieder.</p>
</div>
</section>
<section id="admin-team">
<div class="content at-content">
<?php
$q = new WP_Query([
'post_type' => 'bluesky_team',
'posts_per_page' => -1,
'post_status' => 'publish',
'meta_key' => '_bluesky_sort_order',
'orderby' => 'meta_value_num',
'order' => 'ASC',
]);
$groups = [];
if ($q->have_posts()) {
while ($q->have_posts()) {
$q->the_post();
$id = get_the_ID();
$g = get_post_meta($id, '_bluesky_team_group', true) ?: 'Team';
$groups[$g][] = [
'in_game_name' => get_post_meta($id, '_bluesky_in_game_name', true),
'rank' => get_post_meta($id, '_bluesky_rank', true),
'rank_color' => get_post_meta($id, '_bluesky_rank_color', true),
'skin_url' => get_post_meta($id, '_bluesky_skin_url', true),
];
}
wp_reset_postdata();
}
$skin_type = get_option('bluesky_skin_type', 'bust');
// Steve UUID als Fallback-Platzhalter
$placeholder = 'https://crafthead.net/bust/ec561538f3fd461daff5086b22154bce/256';
if (!empty($groups)):
foreach ($groups as $gname => $members):
?>
<div class="group <?php echo esc_attr(sanitize_html_class($gname)); ?>">
<h2 class="rank-title"><?php echo esc_html(ucfirst($gname)); ?></h2>
<div class="users">
<?php foreach ($members as $m):
// Wenn eigene URL → direkt nutzen, sonst Platzhalter bis JS lädt
$initial_src = !empty($m['skin_url']) ? $m['skin_url'] : $placeholder;
$rank_color = !empty($m['rank_color']) ? $m['rank_color'] : 'rgba(57,190,255,0.6)';
$rank_label = !empty($m['rank']) ? $m['rank'] : '—';
?>
<div class="user"
data-ingame="<?php echo esc_attr($m['in_game_name']); ?>"
data-skin="<?php echo esc_url($m['skin_url']); ?>"
data-skintype="<?php echo esc_attr($skin_type); ?>">
<div class="skin-wrapper">
<img src="<?php echo esc_url($initial_src); ?>"
alt="<?php echo esc_attr($m['in_game_name']); ?>"
class="member-skin"
loading="lazy">
</div>
<div class="user-info">
<span class="name"><?php echo esc_html($m['in_game_name']); ?></span>
<span class="rank" style="background: <?php echo esc_attr($rank_color); ?>">
<?php echo esc_html($rank_label); ?>
</span>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
endforeach;
else:
?>
<p style="color:var(--description-color);text-align:center;padding:60px 0">
Noch keine Team-Mitglieder vorhanden.<br>
<a href="<?php echo admin_url('post-new.php?post_type=bluesky_team'); ?>" style="color:var(--main-color)">→ Jetzt hinzufügen</a>
</p>
<?php endif; ?>
</div>
</section>
<?php bluesky_footer(); get_footer(); ?>

167
template-wiki.php Normal file
View File

@@ -0,0 +1,167 @@
<?php
/**
* Template Name: BlueSky - Wiki
*/
get_header();
bluesky_navbar('wiki');
$server_ip = get_option('bluesky_server_ip', 'mc.example.com');
$header_bg = bluesky_get_image('bluesky_header_bg_url', 'images/header-background.jpg');
// Nur Top-Level Kategorien holen
$top_cats = get_terms([
'taxonomy' => 'wiki_category',
'hide_empty' => false,
'parent' => 0,
'orderby' => 'menu_order',
'order' => 'ASC',
]);
?>
<section id="page-header" style="background-image:url('<?php echo esc_url($header_bg); ?>')">
<div class="content">
<p class="minecraft-server-ip"><?php echo esc_html($server_ip); ?></p>
<h1 class="title"><span>Wiki</span></h1>
<p class="description">Alle Informationen zum Server auf einen Blick.</p>
</div>
</section>
<section id="wiki-overview">
<div class="content">
<?php if (!empty($top_cats) && !is_wp_error($top_cats)): ?>
<div class="wiki-plugin-container">
<div class="wiki-tabs-nav">
<?php foreach ($top_cats as $index => $cat): ?>
<button
type="button"
class="wiki-tab-button <?php echo $index === 0 ? 'active' : ''; ?>"
data-tab="wiki-tab-<?php echo esc_attr($cat->term_id); ?>"
>
<?php echo esc_html($cat->name); ?>
</button>
<?php endforeach; ?>
</div>
<div class="wiki-tabs-content">
<?php foreach ($top_cats as $index => $cat):
$sub_cats = get_terms([
'taxonomy' => 'wiki_category',
'hide_empty' => false,
'parent' => $cat->term_id,
'orderby' => 'menu_order',
'order' => 'ASC',
]);
$direct_articles = new WP_Query([
'post_type' => 'bluesky_wiki',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'menu_order title',
'order' => 'ASC',
'tax_query' => [[
'taxonomy' => 'wiki_category',
'field' => 'term_id',
'terms' => $cat->term_id,
'include_children' => false,
]],
]);
?>
<div id="wiki-tab-<?php echo esc_attr($cat->term_id); ?>" class="wiki-tab-panel <?php echo $index === 0 ? 'active' : ''; ?>">
<div class="wiki-cat-header">
<?php if ($cat->description): ?>
<div class="wiki-cat-icon"><?php echo wp_kses_post($cat->description); ?></div>
<?php endif; ?>
<div>
<h2 class="wiki-cat-title"><?php echo esc_html($cat->name); ?></h2>
<span class="wiki-cat-count"><?php echo esc_html($cat->count); ?> Artikel</span>
</div>
</div>
<?php if ($direct_articles->have_posts()): ?>
<div class="wiki-panel-block">
<h3 class="wiki-subcat-title"><span class="wiki-subcat-dot"></span>Allgemein</h3>
<div class="wiki-articles-grid">
<?php while ($direct_articles->have_posts()): $direct_articles->the_post();
$thumb = has_post_thumbnail()
? get_the_post_thumbnail_url(get_the_ID(), 'thumbnail')
: get_template_directory_uri() . '/images/logo.png';
$excerpt = get_the_excerpt() ?: wp_trim_words(get_the_content(), 15, '...');
?>
<a href="<?php the_permalink(); ?>" class="wiki-article-card">
<div class="wiki-card-icon">
<img src="<?php echo esc_url($thumb); ?>" alt="<?php the_title_attribute(); ?>">
</div>
<div class="wiki-card-body">
<h3><?php the_title(); ?></h3>
<?php if ($excerpt): ?><p><?php echo esc_html($excerpt); ?></p><?php endif; ?>
</div>
<div class="wiki-card-arrow">→</div>
</a>
<?php endwhile; wp_reset_postdata(); ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($sub_cats) && !is_wp_error($sub_cats)):
foreach ($sub_cats as $sub):
$sub_articles = new WP_Query([
'post_type' => 'bluesky_wiki',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'menu_order title',
'order' => 'ASC',
'tax_query' => [[
'taxonomy' => 'wiki_category',
'field' => 'term_id',
'terms' => $sub->term_id,
'include_children' => false,
]],
]);
if (!$sub_articles->have_posts()) { wp_reset_postdata(); continue; }
?>
<div class="wiki-subcat-block">
<h3 class="wiki-subcat-title"><span class="wiki-subcat-dot"></span><?php echo esc_html($sub->name); ?></h3>
<div class="wiki-articles-grid">
<?php while ($sub_articles->have_posts()): $sub_articles->the_post();
$thumb = has_post_thumbnail()
? get_the_post_thumbnail_url(get_the_ID(), 'thumbnail')
: get_template_directory_uri() . '/images/logo.png';
$excerpt = get_the_excerpt() ?: wp_trim_words(get_the_content(), 15, '...');
?>
<a href="<?php the_permalink(); ?>" class="wiki-article-card">
<div class="wiki-card-icon">
<img src="<?php echo esc_url($thumb); ?>" alt="<?php the_title_attribute(); ?>">
</div>
<div class="wiki-card-body">
<h3><?php the_title(); ?></h3>
<?php if ($excerpt): ?><p><?php echo esc_html($excerpt); ?></p><?php endif; ?>
</div>
<div class="wiki-card-arrow">→</div>
</a>
<?php endwhile; wp_reset_postdata(); ?>
</div>
</div>
<?php endforeach; endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php else: ?>
<!-- Noch keine Kategorien — Hinweis -->
<div class="wiki-empty">
<div class="wiki-empty-icon">📚</div>
<h2>Wiki ist noch leer</h2>
<p>Erstelle im Backend zuerst <strong>Wiki-Kategorien</strong> und dann <strong>Wiki-Artikel</strong>.</p>
<?php if (current_user_can('manage_options')): ?>
<div style="display:flex;gap:12px;justify-content:center;margin-top:20px">
<a href="<?php echo admin_url('edit-tags.php?taxonomy=wiki_category&post_type=bluesky_wiki'); ?>" class="wiki-btn">+ Kategorie erstellen</a>
<a href="<?php echo admin_url('post-new.php?post_type=bluesky_wiki'); ?>" class="wiki-btn wiki-btn-secondary">+ Artikel erstellen</a>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</section>
<?php bluesky_footer(); get_footer(); ?>