Minecraft-BungeeCord-Status/minecraft-bungeecord-status.php aktualisiert

This commit is contained in:
2026-01-02 21:07:18 +00:00
parent 187abfcbf5
commit 954bc4d622

View File

@@ -1,9 +1,9 @@
<?php
/**
/*
* Plugin Name: Minecraft BungeeCord Status Network Edition
* Description: Der ultimative Live-Status für dein BungeeCord Netzwerk (Border None Fix).
* Tags: minecraft, bungeecord, server status, player list
* Version: 3.6.0
* Version: 3.6.1
* Author: M_Viper
* Requires at least: 6.0
* Requires PHP: 7.4
@@ -16,6 +16,187 @@ define('MCSS_URL', plugin_dir_url(__FILE__));
require_once MCSS_DIR . 'rcon/Rcon.php';
/* ---------------- HELPER: MINECRAFT COLORS ---------------- */
function mcss_format_minecraft_colors($text) {
if (empty($text)) return '';
// Minecraft Color Map
$color_map = [
'0' => '#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 = '<span style="color:#AAAAAA;">'; // Standard Grau
// Ersetze Farben: &c -> </span><span style="color:#HEX">
foreach ($color_map as $char => $hex) {
$text = str_replace("&" . $char, "</span><span style=\"color:$hex;\">", $text);
}
// Formatierungen
$text = str_replace("&l", "</span><span style=\"font-weight:bold;\">", $text); // Bold
$text = str_replace("&o", "</span><span style=\"font-style:italic;\">", $text); // Italic
$text = str_replace("&n", "</span><span style=\"text-decoration:underline;\">", $text); // Underline
$text = str_replace("&m", "</span><span style=\"text-decoration:line-through;\">", $text); // Strikethrough
$text = str_replace("&r", "</span><span style=\"color:#AAAAAA;\">", $text); // Reset to Gray
$formatted .= $text . '</span>';
return $formatted;
}
/* ---------------- 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 ) {
?>
<div class="notice notice-warning is-dismissible">
<p>
<strong>Minecraft BungeeCord Status Update verfügbar</strong><br>
Neue Version: <strong><?php echo esc_html( $latest['version'] ); ?></strong><br>
Installiert: <strong><?php echo esc_html( $current_version ); ?></strong><br>
<a href="<?php echo esc_url( $latest['url'] ); ?>" class="button button-primary" target="_blank" rel="noreferrer noopener">Direkter Download (ZIP)</a>
<a href="<?php echo esc_url( 'https://git.viper.ipv64.net/' . rawurlencode( $this->repo_owner ) . '/' . rawurlencode( $this->repo_name ) . '/releases' ); ?>" class="button" target="_blank" style="margin-left:8px;" rel="noreferrer noopener">Releases ansehen</a>
</p>
</div>
<?php
} );
}
}
}
private function get_latest_release_info() {
$cached = get_transient( $this->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;
@@ -30,8 +211,8 @@ add_action('admin_enqueue_scripts', function($hook){
});
add_action('wp_enqueue_scripts', function(){
wp_enqueue_style('mcss-style', MCSS_URL . 'css/style.css', [], '3.6.0');
wp_enqueue_script('mcss-frontend-js', MCSS_URL . 'js/mcss-frontend.js', ['jquery'], '3.6.0', true);
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 ---------------- */
@@ -62,8 +243,8 @@ function mcss_sanitize_servers($input) {
'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'), // API Port
'player_port_copy' => sanitize_text_field($srv['player_port_copy'] ?? ''), // Display Port
'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']),
@@ -71,14 +252,12 @@ function mcss_sanitize_servers($input) {
'logo_id' => absint($srv['logo_id'] ?? 0),
'logo_url' => esc_url_raw($srv['logo_url'] ?? ''),
'custom_text' => wp_kses_post($srv['custom_text'] ?? ''),
// Styles
'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'),
// Events & Maintenance
'maintenance_mode' => !empty($srv['maintenance_mode']),
'maintenance_message' => wp_kses_post($srv['maintenance_message'] ?? 'Wartung'),
'announcement_enabled' => !empty($srv['announcement_enabled']),
@@ -86,7 +265,6 @@ function mcss_sanitize_servers($input) {
'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
'ranks_json' => mcss_sanitize_ranks($srv['ranks_json'] ?? '[]'),
];
}
@@ -136,7 +314,6 @@ function mcss_settings_page() {
$servers = [['id'=>'default', 'name'=>'Mein Netzwerk', 'host'=>'127.0.0.1', 'player_port'=>'9191', 'cache_ttl'=>10, 'hide_port'=>true, 'show_motd'=>true]];
}
// Vollständige Liste
$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',
@@ -149,7 +326,7 @@ function mcss_settings_page() {
<div class="wrap">
<h1>BungeeCord Netzwerk Einstellungen</h1>
<p style="color:#d97706;background:#fef3c7;padding:10px;border-radius:5px;">
<strong>Final:</strong> Expliziter `border: none` im Inline-Style für Wartungsmodus.
<strong>Wichtig:</strong> Bitte das Plugin StatusAPI.jar im Bungeecord Installieren.
</p>
<form method="post" action="options.php">
<?php settings_fields('mcss_settings_group'); ?>
@@ -365,17 +542,33 @@ function mcss_fetch_server_with_ranks($srv) {
}
$players_info = [];
$user_defined_ranks = json_decode($srv['ranks_json'] ?? '[]', true);
if (!is_array($user_defined_ranks)) $user_defined_ranks = [];
foreach ($api_data['players'] as $player_data) {
if (is_array($player_data)) {
$name = $player_data['name'];
$prefix = $player_data['prefix'] ?? '';
} else {
// Fallback für alte API
$name = $player_data;
$prefix = '';
}
// 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 = '<span style="color:black;">' . esc_html($name) . '</span>';
// 3. Zusammenbauen
$display_html = trim($prefix_html) . ' ' . $name_html;
foreach ($api_data['players'] as $name) {
$rank = 'Spieler';
$color = '#566d8dff';
$players_info[] = [
'name' => $name,
'avatar' => "https://mc-heads.net/avatar/" . rawurlencode($name) . "/64",
'rank' => $rank,
'color' => $color,
'prefix' => $prefix,
'display_html' => $display_html,
'rank' => $prefix ?: 'Spieler',
'color' => '#566d8dff',
];
}
@@ -389,7 +582,7 @@ function mcss_fetch_server_with_ranks($srv) {
'motd' => is_array($api_data['motd']) ? implode(' ', $api_data['motd']) : $api_data['motd']
];
$fast_cache_ttl = min(2, $srv['cache_tl'] ?? $srv['cache_ttl']);
$fast_cache_ttl = max(2, absint($srv['cache_ttl'] ?? 10));
set_transient($cache_key, $result, $fast_cache_ttl);
return $result;
}
@@ -421,7 +614,7 @@ function mcss_shortcode($atts) {
}
if (!$srv) return 'Server nicht gefunden';
// MAINTENANCE MODE (Rich Style - No Border)
// 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) {
@@ -439,10 +632,8 @@ function mcss_shortcode($atts) {
}
.mcss-status-maintenance { animation: pulse 2s infinite; }
</style>
<!-- FIX: border:none hinzugefügt -->
<div id="mcss-widget-<?php echo esc_attr($uid); ?>" style="max-width:650px;margin:30px auto;padding:0; background:#fef3c7;border:none;border-radius:20px; overflow:hidden;box-shadow:0 16px 40px rgba(0,0,0,0.12); font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
<!-- Rich Header -->
<div style="padding:28px 32px;background:#fef3c7;border-bottom:1px solid #fbbf24;display:flex;align-items:center;gap:20px;">
<img src="<?php echo esc_url($logo); ?>" alt="Logo" loading="lazy" style="width:60px;height:60px;border-radius:12px;box-shadow:0 8px 20px rgba(0,0,0,0.15);" onerror="this.src='<?php echo MCSS_URL.'img/default-server-logo.png'; ?>'" />
<div style="flex:1;">
@@ -453,7 +644,6 @@ function mcss_shortcode($atts) {
</div>
</div>
</div>
<!-- Rich Body -->
<div style="padding:24px 32px;background:#fef3c7;">
<div style="margin-bottom:16px;font-weight:700;color:#92400e;font-size:1.05em;">Wartungshinweis:</div>
<div style="font-size:1.1em;color:#78350f;line-height:1.6;"><?php echo wp_kses_post($maintenance_message); ?></div>
@@ -465,11 +655,10 @@ function mcss_shortcode($atts) {
<?php return ob_get_clean();
}
// NORMAL MODE (No Border)
// NORMAL MODE
$data = mcss_fetch_server_with_ranks($srv);
$uid = md5($srv['host']);
// STYLES
$name_color = $srv['name_color'] ?? '#333333';
$name_size = $srv['name_size'] ?? '1.3em';
$ct_color = $srv['ct_color'] ?? '#555555';
@@ -479,13 +668,11 @@ function mcss_shortcode($atts) {
$logo_size = "70px";
$player_head_size = "32px";
// Copy Logic (player_port_copy)
$copy_addr = !empty($srv['copy_address']) ? $srv['copy_address'] : $srv['host'];
if (empty($srv['hide_port']) && !empty($srv['player_port_copy'])) {
$copy_addr .= ':' . $srv['player_port_copy'];
}
// ANNOUNCEMENT CHECK
$show_announcement = mcss_should_show_announcement($srv);
$announcement_text = $srv['announcement_text'] ?? '';
$announcement_type = $srv['announcement_type'] ?? 'info';
@@ -499,7 +686,6 @@ function mcss_shortcode($atts) {
.mcss-announcement { animation: slideDown 0.5s ease-out; }
</style>
<!-- FIX: border:none hinzugefügt -->
<div id="mcss-widget-<?php echo esc_attr($uid); ?>" style="max-width:<?php echo $widget_width; ?>;margin:20px auto;padding:<?php echo $widget_padding; ?>;background:white;border:none;border-radius:10px;box-shadow:0 4px 15px rgba(0,0,0,0.1);font-family:sans-serif;position:relative;">
<!-- POPUP / TOAST -->
@@ -518,7 +704,6 @@ function mcss_shortcode($atts) {
<div style="display:flex;align-items:center;gap:12px;border-bottom:1px solid #eee;padding-bottom:12px;">
<img src="<?php echo esc_url($srv['logo_url'] ?: MCSS_URL.'img/default-server-logo.png'); ?>" style="width:<?php echo $logo_size; ?>;height:<?php echo $logo_size; ?>;border-radius:6px;">
<!-- GEÄNDERTER HEADER: Name -> IP + Status -> Zusatztext -->
<div style="flex:1;display:flex;flex-direction:column;gap:6px;">
<!-- NAME -->
@@ -531,13 +716,10 @@ function mcss_shortcode($atts) {
<!-- IP + STATUS -->
<div style="display:flex;align-items:center;gap:10px;font-size:0.9em;font-weight:600;">
<!-- IP -->
<span style="color:#374151;" id="mcss-ip-<?php echo esc_attr($uid); ?>">
<?php echo esc_html($copy_addr); ?>
</span>
<!-- PULSIERENDER STATUSPUNKT -->
<span id="mcss-status-dot-<?php echo esc_attr($uid); ?>"
class="<?php echo $data['online'] ? 'mcss-status-online' : ''; ?>"
style="width:10px;height:10px;border-radius:50%;
@@ -545,14 +727,13 @@ function mcss_shortcode($atts) {
box-shadow:0 0 8px <?php echo $data['online'] ? 'rgba(16,185,129,.7)' : 'rgba(239,68,68,.7)'; ?>;">
</span>
<!-- STATUS TEXT (EINDEUTIG) -->
<span id="mcss-status-text-<?php echo esc_attr($uid); ?>"
style="color:<?php echo $data['online'] ? '#10b981' : '#ef4444'; ?>;">
<?php echo $data['online'] ? 'Online' : 'Offline'; ?>
</span>
</div>
<!-- ZUSATZTEXT (wird NICHT von JS angefasst) -->
<!-- ZUSATZTEXT -->
<?php if (!empty($srv['custom_text'])): ?>
<div id="mcss-custom-text-<?php echo esc_attr($uid); ?>" style="font-size:<?php echo $ct_size; ?>;color:<?php echo $ct_color; ?>;font-weight:500;">
<?php echo wp_kses_post($srv['custom_text']); ?>
@@ -577,7 +758,7 @@ function mcss_shortcode($atts) {
<?php foreach ($data['players'] as $p): ?>
<div style="text-align:center;">
<img src="<?php echo esc_url($p['avatar']); ?>" style="width:<?php echo $player_head_size; ?>;height:<?php echo $player_head_size; ?>;border-radius:4px;">
<div style="font-size:0.75em;"><?php echo esc_html($p['name']); ?></div>
<div style="font-size:0.75em;"><?php echo $p['display_html']; ?></div>
</div>
<?php endforeach; ?>
<?php else: ?>
@@ -605,11 +786,9 @@ function mcss_shortcode($atts) {
});
}
// SET CLICK ON NAME
const nameEl = document.getElementById('mcss-name-<?php echo esc_attr($uid); ?>');
if(nameEl) nameEl.addEventListener('click', mcss_copy_<?php echo esc_attr($uid); ?>);
// CLOSE ANNOUNCEMENT FUNCTION
document.querySelectorAll('.mcss-announcement-close').forEach(function(btn){
btn.addEventListener('click', function(e){
e.preventDefault();
@@ -662,9 +841,10 @@ function mcss_shortcode($atts) {
var html = '';
if (d.players && Array.isArray(d.players) && d.players.length > 0) {
d.players.forEach(function(p){
var content = p.display_html ? p.display_html : p.name;
html += '<div style="text-align:center;">' +
'<img src="' + (p.avatar ? p.avatar : '') + '" style="width:<?php echo $player_head_size; ?>;height:<?php echo $player_head_size; ?>;border-radius:4px;">' +
'<div style="font-size:0.75em;">' + (p.name ? p.name : '') + '</div>' +
'<div style="font-size:0.75em;">' + content + '</div>' +
'</div>';
});
} else {
@@ -690,5 +870,4 @@ function mcss_shortcode($atts) {
<?php return ob_get_clean();
}
}