'#000000', // Black
'1' => '#0000AA', // Dark Blue
'2' => '#00AA00', // Dark Green
'3' => '#00AAAA', // Dark Aqua
'4' => '#AA0000', // Dark Red
'5' => '#AA00AA', // Dark Purple
'6' => '#FFAA00', // Gold
'7' => '#AAAAAA', // Gray
'8' => '#555555', // Dark Gray
'9' => '#5555FF', // Blue
'a' => '#55FF55', // Green
'b' => '#55FFFF', // Aqua
'c' => '#FF5555', // Red
'd' => '#FF55FF', // Light Purple
'e' => '#FFFF55', // Yellow
'f' => '#FFFFFF' // White
];
// Base Wrapper
$formatted = ''; // Standard Grau
// Ersetze Farben: &c ->
foreach ($color_map as $char => $hex) {
$text = str_replace("&" . $char, "", $text);
}
// Formatierungen
$text = str_replace("&l", "", $text); // Bold
$text = str_replace("&o", "", $text); // Italic
$text = str_replace("&n", "", $text); // Underline
$text = str_replace("&m", "", $text); // Strikethrough
$text = str_replace("&r", "", $text); // Reset to Gray
$formatted .= $text . '';
return $formatted;
}
/* ---------------- HELPER: 3D AVATAR URL ---------------- */
function mcss_get_3d_avatar($name, $uuid = null) {
// Bedrock-Spieler erkennen (Name enthält Punkt oder UUID beginnt mit xuid)
$is_bedrock = strpos($name, '.') !== false || ($uuid && strpos($uuid, 'xuid') === 0);
if ($is_bedrock) {
// Bedrock: mc-heads.net mit 3D Head (nutze UUID falls vorhanden)
if ($uuid && !empty($uuid)) {
return 'https://mc-heads.net/head/' . rawurlencode($uuid) . '/100';
}
return 'https://mc-heads.net/head/' . rawurlencode($name) . '/100';
} else {
// Java: mc-heads.net mit 3D Head
return 'https://mc-heads.net/head/' . rawurlencode($name) . '/100';
}
}
/* ---------------- AUTO UPDATE (MCSS) ---------------- */
if ( ! class_exists( 'MCSS_Auto_Update' ) ) {
class MCSS_Auto_Update {
private $plugin_file;
private $repo_owner = 'M_Viper';
private $repo_name = 'Minecraft-BungeeCord-Status';
private $api_url;
private $transient_key;
public function __construct( $plugin_file ) {
$this->plugin_file = $plugin_file;
$this->api_url = 'https://git.viper.ipv64.net/api/v1/repos/' . rawurlencode( $this->repo_owner ) . '/' . rawurlencode( $this->repo_name ) . '/releases';
$this->transient_key = 'mcss_update_check_' . md5( $this->repo_owner . '/' . $this->repo_name );
if ( is_admin() ) {
add_action( 'admin_init', array( $this, 'check_for_update' ) );
}
}
public function check_for_update() {
if ( ! function_exists( 'get_file_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$current = get_file_data( $this->plugin_file, array( 'Version' => 'Version' ), 'plugin' );
$current_version = isset( $current['Version'] ) ? $current['Version'] : '0.0.0';
$latest = $this->get_latest_release_info();
if ( $latest && ! empty( $latest['version'] ) && ! empty( $latest['url'] ) ) {
if ( version_compare( $latest['version'], $current_version, '>' ) ) {
add_action( 'admin_notices', function() use ( $latest, $current_version ) {
?>
transient_key );
if ( false !== $cached && is_array( $cached ) && ! empty( $cached['version'] ) ) {
return $cached;
}
$result = false;
$response = wp_remote_get( $this->api_url, array(
'timeout' => 8,
'headers' => array(
'Accept' => 'application/json',
'User-Agent' => 'MCSS-Update-Checker/1.0',
),
) );
if ( is_wp_error( $response ) ) {
set_transient( $this->transient_key, array( 'version' => '', 'url' => '' ), HOUR_IN_SECONDS );
return false;
}
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== (int) $code ) {
set_transient( $this->transient_key, array( 'version' => '', 'url' => '' ), HOUR_IN_SECONDS );
return false;
}
$body = wp_remote_retrieve_body( $response );
$json = json_decode( $body, true );
if ( ! is_array( $json ) || empty( $json ) ) {
set_transient( $this->transient_key, array( 'version' => '', 'url' => '' ), HOUR_IN_SECONDS );
return false;
}
foreach ( $json as $release ) {
$tag = '';
if ( ! empty( $release['tag_name'] ) ) {
$tag = ltrim( (string) $release['tag_name'], 'vV' );
} elseif ( ! empty( $release['name'] ) ) {
$tag = ltrim( (string) $release['name'], 'vV' );
}
if ( ! empty( $release['assets'] ) && is_array( $release['assets'] ) ) {
foreach ( $release['assets'] as $asset ) {
if ( empty( $asset['name'] ) || empty( $asset['browser_download_url'] ) ) {
continue;
}
if ( strtolower( $asset['name'] ) === 'minecraft-bungeecord-status.zip' ) {
$version = $tag ?: $this->extract_version_from_string( $asset['name'] . ' ' . ( $release['name'] ?? '' ) );
if ( $version ) {
$result = array(
'version' => $version,
'url' => $asset['browser_download_url'],
);
break 2;
} else {
$result = array(
'version' => ( $tag ?: (string) ( $release['name'] ?? '' ) ),
'url' => $asset['browser_download_url'],
);
break 2;
}
}
}
}
}
if ( $result ) {
set_transient( $this->transient_key, $result, 12 * HOUR_IN_SECONDS );
return $result;
}
set_transient( $this->transient_key, array( 'version' => '', 'url' => '' ), 6 * HOUR_IN_SECONDS );
return false;
}
private function extract_version_from_string( $str ) {
if ( preg_match( '/([0-9]+\.[0-9]+(?:\.[0-9]+)?)/', $str, $m ) ) {
return $m[1];
}
return '';
}
}
new MCSS_Auto_Update( __FILE__ );
}
/* ---------------- Assets ---------------- */
add_action('admin_enqueue_scripts', function($hook){
global $pagenow;
if ($pagenow === 'admin.php' && isset($_GET['page']) && $_GET['page'] === 'mcss-settings') {
wp_enqueue_media();
wp_enqueue_style('wp-color-picker');
wp_enqueue_script('wp-color-picker');
wp_enqueue_script('jquery-ui-datepicker');
wp_enqueue_style('jquery-ui-css', 'https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.min.css');
wp_enqueue_script('mcss-admin-js', MCSS_URL . 'js/admin.js', ['jquery', 'wp-color-picker', 'jquery-ui-datepicker'], '1.0.0', true);
}
});
add_action('wp_enqueue_scripts', function(){
wp_enqueue_style('mcss-style', MCSS_URL . 'css/style.css', [], '3.8.1');
wp_enqueue_script('mcss-frontend-js', MCSS_URL . 'js/mcss-frontend.js', ['jquery'], '3.8.1', true);
});
/* ---------------- Settings ---------------- */
add_action('admin_menu', function(){
add_menu_page(
'BungeeCord Einstellungen',
'BungeeCord Status',
'manage_options',
'mcss-settings',
'mcss_settings_page',
'dashicons-networking',
100
);
});
add_action('admin_init', function(){
register_setting('mcss_settings_group', 'mcss_servers', ['sanitize_callback'=>'mcss_sanitize_servers']);
});
function mcss_sanitize_servers($input) {
if (!is_array($input)) return [];
$clean = [];
foreach ($input as $srv) {
if (!is_array($srv)) continue;
$clean[] = [
'id' => sanitize_key($srv['id'] ?? 'srv_'.wp_rand()),
'name' => sanitize_text_field($srv['name'] ?? 'BungeeCord'),
'host' => sanitize_text_field($srv['host'] ?? ''),
'rcon_port' => absint($srv['rcon_port'] ?? 25577),
'rcon_pass' => sanitize_text_field($srv['rcon_pass'] ?? ''),
'player_port' => sanitize_text_field($srv['player_port'] ?? '9191'),
'player_port_copy' => sanitize_text_field($srv['player_port_copy'] ?? ''),
'copy_address' => sanitize_text_field($srv['copy_address'] ?? ''),
'hide_port' => !empty($srv['hide_port']),
'show_motd' => !empty($srv['show_motd']),
'cache_ttl' => max(2, absint($srv['cache_ttl'] ?? 10)),
'logo_id' => absint($srv['logo_id'] ?? 0),
'logo_url' => esc_url_raw($srv['logo_url'] ?? ''),
'custom_text' => wp_kses_post($srv['custom_text'] ?? ''),
'ip_color' => sanitize_hex_color($srv['ip_color'] ?? '#1f2937'),
'ct_color' => sanitize_hex_color($srv['ct_color'] ?? '#1e293b'),
'ip_size' => sanitize_text_field($srv['ip_size'] ?? '1.5em'),
'ct_size' => sanitize_text_field($srv['ct_size'] ?? '1.05em'),
'name_color' => sanitize_hex_color($srv['name_color'] ?? '#333333'),
'name_size' => sanitize_text_field($srv['name_size'] ?? '1.8em'),
'maintenance_mode' => !empty($srv['maintenance_mode']),
'maintenance_message' => wp_kses_post($srv['maintenance_message'] ?? 'Wartung'),
'announcement_enabled' => !empty($srv['announcement_enabled']),
'announcement_text' => wp_kses_post($srv['announcement_text'] ?? ''),
'announcement_start' => sanitize_text_field($srv['announcement_start'] ?? ''),
'announcement_end' => sanitize_text_field($srv['announcement_end'] ?? ''),
'announcement_type' => sanitize_text_field($srv['announcement_type'] ?? 'info'),
'ranks_json' => mcss_sanitize_ranks($srv['ranks_json'] ?? '[]'),
];
}
return $clean;
}
function mcss_sanitize_ranks($input) {
$decoded = json_decode($input, true);
if (!is_array($decoded)) return '[]';
$out = [];
foreach ($decoded as $r) {
if (!is_array($r) || empty($r['name'])) continue;
$out[] = ['name'=>sanitize_text_field($r['name']), 'color'=>sanitize_text_field($r['color']??'#6c5ce7')];
}
return wp_json_encode($out);
}
/* ---------------- Helper Functions ---------------- */
function mcss_should_show_announcement($srv) {
if (empty($srv['announcement_enabled'])) return false;
if (empty($srv['announcement_text'])) return false;
if (empty($srv['announcement_start'])) return true;
$current_time = current_time('timestamp');
$start_time = strtotime($srv['announcement_start']);
if ($start_time > $current_time) return false;
if (empty($srv['announcement_end'])) return true;
$end_time = strtotime($srv['announcement_end']);
return $end_time >= $current_time;
}
function mcss_get_announcement_style($type) {
switch ($type) {
case 'warning': return ['bg' => '#fef3c7','border' => '#fbbf24','text' => '#92400e','icon' => '⚠️'];
case 'success': return ['bg' => '#d1fae5','border' => '#10b981','text' => '#065f46','icon' => '✅'];
case 'error': return ['bg' => '#fee2e2','border' => '#ef4444','text' => '#991b1b','icon' => '❌'];
case 'info': default: return ['bg' => '#dbeafe','border' => '#3b82f6','text' => '#1e40af','icon' => 'ℹ️'];
}
}
/* ---------------- Backend Page ---------------- */
function mcss_settings_page() {
$servers = get_option('mcss_servers', []);
if (empty($servers)) {
$servers = [['id'=>'default', 'name'=>'Mein Netzwerk', 'host'=>'127.0.0.1', 'player_port'=>'9191', 'cache_ttl'=>10, 'hide_port'=>true, 'show_motd'=>true]];
}
$font_sizes = [
'0.7em'=>'Sehr klein','0.85em'=>'Klein','1em'=>'Normal','1.2em'=>'Etwas größer',
'1.4em'=>'Groß','1.5em'=>'Sehr groß','1.7em'=>'Extra groß','2em'=>'Riesig',
'2.5em'=>'Enorm','3em'=>'Gigantisch',
];
$announcement_types = ['info'=>'Info (Blau)','warning'=>'Warnung (Orange)','success'=>'Erfolg (Grün)','error'=>'Fehler (Rot)'];
?>
BungeeCord Netzwerk Einstellungen
Wichtig: Bitte das Plugin StatusAPI.jar im Bungeecord Installieren.
false,'players'=>[],'version'=>'Offline','ping'=>9999,'motd'=>'Verbindung fehlgeschlagen'];
}
$players_info = [];
foreach ($api_data['players'] as $player_data) {
if (is_array($player_data)) {
$name = $player_data['name'];
$prefix = $player_data['prefix'] ?? '';
$uuid = $player_data['uuid'] ?? null;
} else {
// Fallback für alte API
$name = $player_data;
$prefix = '';
$uuid = null;
}
// 1. Prefix mit Farben konvertieren
$prefix_html = mcss_format_minecraft_colors($prefix);
// 2. Namen immer Schwarz darstellen (überschreibt eventuelle Farben aus dem Prefix)
$name_html = '' . esc_html($name) . '';
// 3. Zusammenbauen (Nur Abstand, wenn Prefix existiert)
if (!empty($prefix_html)) {
$display_html = $prefix_html . ' ' . $name_html;
} else {
$display_html = $name_html;
}
// 4. 3D Avatar URL generieren (mit Bedrock-Support)
$avatar_url = mcss_get_3d_avatar($name, $uuid);
$players_info[] = [
'name' => $name,
'uuid' => $uuid,
'avatar' => $avatar_url,
'prefix' => $prefix,
'display_html' => $display_html,
'rank' => $prefix ?: 'Spieler',
'color' => '#566d8dff',
];
}
$clean_version = mcss_parse_bungeecord_version($api_data['version'] ?? 'BungeeCord');
$result = [
'online' => true,
'players' => $players_info,
'version' => $clean_version,
'ping' => 1,
'motd' => is_array($api_data['motd']) ? implode(' ', $api_data['motd']) : $api_data['motd']
];
$fast_cache_ttl = max(2, absint($srv['cache_ttl'] ?? 10));
set_transient($cache_key, $result, $fast_cache_ttl);
return $result;
}
/* ---------------- AJAX ---------------- */
add_action('wp_ajax_mcss_fetch', 'mcss_ajax_fetch');
add_action('wp_ajax_nopriv_mcss_fetch', 'mcss_ajax_fetch');
function mcss_ajax_fetch() {
$id = sanitize_text_field($_POST['server_id'] ?? '');
$servers = get_option('mcss_servers', []);
foreach ($servers as $srv) {
if (($srv['id'] ?? '') === $id) wp_send_json(mcss_fetch_server_with_ranks($srv));
if (($srv['name'] ?? '') === $id) wp_send_json(mcss_fetch_server_with_ranks($srv));
}
wp_send_json(['online'=>false]);
}
/* ---------------- FRONTEND (SHORTCODE) ---------------- */
add_shortcode('bungeecord_status', 'mcss_shortcode');
function mcss_shortcode($atts) {
$atts = shortcode_atts(['id' => ''], $atts);
if (empty($atts['id'])) return 'Fehler';
$servers = get_option('mcss_servers', []);
$srv = null;
foreach ($servers as $s) {
if (($s['id'] ?? '') === $atts['id']) { $srv = $s; break; }
if (($s['name'] ?? '') === $atts['id']) { $srv = $s; break; }
}
if (!$srv) return 'Server nicht gefunden';
// MAINTENANCE MODE
$maintenance_mode = !empty($srv['maintenance_mode']);
$maintenance_message = $srv['maintenance_message'] ?? 'Der Server befindet sich derzeit im Wartungsmodus. Wir sind bald wieder für dich da!';
if ($maintenance_mode) {
$uid = md5($srv['host']);
$logo = $srv['logo_id'] ? wp_get_attachment_image_url($srv['logo_id'], 'full') : ($srv['logo_url'] ?: MCSS_URL.'img/default-server-logo.png');
$name_color = $srv['name_color'] ?? '#333333';
$name_size = $srv['name_size'] ?? '1.8em';
ob_start(); ?>