📄 Source: about.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once __DIR__ . '/vendor/autoload.php';
use xPaw\MinecraftPing;
use xPaw\MinecraftPingException;
$server_ip = '127.0.0.1';
$server_port = 25565;
// --- Handle Manual Commands ---
$command_result = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['fog_command'])) {
$command = $_POST['fog_command'];
$command_file = '/mnt/1tb_ssd/NeoSV1/fog_command.txt';
$valid_commands = ['rise', 'fall', 'reset', 'clear', 'status'];
if (in_array($command, $valid_commands)) {
file_put_contents($command_file, $command);
$command_result = "✅ Command '$command' sent to fog controller!";
} else {
$command_result = "❌ Invalid command: $command";
}
}
// --- Fog Status Functions (Read from JSON) ---
function getFogStatusFromJson() {
$json_file = __DIR__ . '/fog_status.json';
if (file_exists($json_file)) {
$data = json_decode(file_get_contents($json_file), true);
if ($data) {
return $data;
}
}
return [
'status' => '🌤️ Fog is down',
'current_height' => 0,
'next_event' => '',
'last_updated' => 'Never'
];
}
// Get server status
function getServerStatus() {
global $server_ip, $server_port;
try {
$Query = new MinecraftPing($server_ip, $server_port, 3);
$info = $Query->Query();
$Query->Close();
return [
'online' => true,
'players' => $info['players']['online'] ?? 0,
'max_players' => $info['players']['max'] ?? 0,
'version' => $info['version']['name'] ?? '1.21.1',
'players_list' => $info['players']['sample'] ?? []
];
} catch (MinecraftPingException $e) {
return [
'online' => false,
'players' => 0,
'max_players' => 0,
'version' => 'Offline',
'players_list' => []
];
}
}
$server = getServerStatus();
$fog = getFogStatusFromJson();
$last_updated = $fog['last_updated'] ?? 'Never';
if ($last_updated !== 'Never') {
try {
$dt = new DateTime($last_updated);
$last_updated = $dt->format('Y-m-d H:i:s');
} catch (Exception $e) {}
}
$is_fog_active = strpos($fog['status'], '🌫️') !== false;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CreateCraft - About</title>
<link rel="stylesheet" href="style.css">
<style>
.server-status-line {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
margin-bottom: 25px;
padding: 10px;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
.status-dot.online {
background-color: #4caf50;
animation: pulse 1.5s ease-in-out infinite;
}
.status-dot.offline {
background-color: #f44336;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(0.85); }
}
.status-title {
font-size: 18px;
font-weight: bold;
color: #5a9e4e;
}
.status-title.offline {
color: #f44336;
}
.fog-status-line {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
margin: 15px 0 10px 0;
padding: 12px;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
flex-wrap: wrap;
cursor: default;
}
.fog-icon {
font-size: 28px;
cursor: pointer;
user-select: none;
transition: transform 0.3s;
display: inline-block;
}
.fog-icon:hover {
transform: scale(1.15);
}
.fog-icon.active {
animation: fogFloat 3s ease-in-out infinite;
}
@keyframes fogFloat {
0%, 100% { transform: translateY(0px) scale(1); }
50% { transform: translateY(-5px) scale(1.05); }
}
.fog-label {
font-size: 16px;
font-weight: 500;
color: #ddd;
}
.fog-status-text {
font-size: 18px;
font-weight: bold;
color: #ff9800;
}
.fog-next-event {
font-size: 14px;
opacity: 0.7;
margin-left: 8px;
}
.fog-height {
font-size: 14px;
opacity: 0.7;
text-align: center;
padding: 4px 0;
}
.fog-last-update {
font-size: 12px;
opacity: 0.4;
text-align: center;
margin-top: 2px;
}
/* Fog Controls - Hidden in Dev Panel */
.fog-controls {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.fog-btn {
padding: 6px 16px;
border: none;
border-radius: 6px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
color: white;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.15);
}
.fog-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
.fog-btn:active {
transform: translateY(0px);
}
.fog-btn-rise { background: rgba(255, 152, 0, 0.7); border-color: #ff9800; }
.fog-btn-rise:hover { background: #ff9800; }
.fog-btn-fall { background: rgba(33, 150, 243, 0.7); border-color: #2196f3; }
.fog-btn-fall:hover { background: #2196f3; }
.fog-btn-reset { background: rgba(244, 67, 54, 0.7); border-color: #f44336; }
.fog-btn-reset:hover { background: #f44336; }
.fog-btn-clear { background: rgba(76, 175, 80, 0.7); border-color: #4caf50; }
.fog-btn-clear:hover { background: #4caf50; }
.fog-btn-status { background: rgba(156, 39, 176, 0.7); border-color: #9c27b0; }
.fog-btn-status:hover { background: #9c27b0; }
.command-result {
text-align: center;
padding: 6px 12px;
margin-top: 8px;
border-radius: 6px;
font-size: 13px;
background: rgba(0,0,0,0.3);
color: #8f8;
}
.command-result.error {
color: #f88;
}
.player-stats {
text-align: center;
padding: 15px;
margin: 10px 0;
}
.player-number {
font-size: 56px;
font-weight: bold;
color: #5a9e4e;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
line-height: 1;
}
.player-max {
font-size: 16px;
opacity: 0.8;
margin-top: 5px;
}
.version-line {
text-align: center;
padding: 8px;
margin: 10px 0;
font-size: 13px;
opacity: 0.7;
border-top: 1px solid rgba(255,255,255,0.1);
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.players-section {
margin-top: 20px;
}
.players-toggle {
cursor: pointer;
color: #5a9e4e;
text-align: center;
padding: 10px;
background: rgba(90, 158, 78, 0.15);
border-radius: 8px;
transition: background 0.3s;
}
.players-toggle:hover {
background: rgba(90, 158, 78, 0.25);
}
.players-container {
margin-top: 15px;
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
}
.player-badge {
background: rgba(90, 158, 78, 0.85);
color: white;
padding: 6px 14px;
border-radius: 20px;
font-size: 13px;
font-weight: 500;
backdrop-filter: blur(4px);
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.no-players-msg {
text-align: center;
padding: 15px;
color: rgba(255,255,255,0.6);
font-style: italic;
}
.quick-links-nav {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 15px;
justify-content: center;
}
.quick-links-nav a {
color: white;
text-decoration: none;
display: inline-block;
padding: 8px 20px;
background: rgba(90, 158, 78, 0.8);
border-radius: 8px;
transition: all 0.3s ease;
font-weight: 500;
}
.quick-links-nav a:hover {
background: rgba(90, 158, 78, 1);
transform: translateY(-2px);
}
.dev-hint {
font-size: 11px;
opacity: 0.15;
text-align: center;
margin-top: 4px;
cursor: default;
user-select: none;
}
.dev-hint:hover {
opacity: 0.5;
}
.dev-panel {
display: none;
margin-top: 15px;
padding: 15px;
background: rgba(0, 0, 0, 0.5);
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: 'Courier New', monospace;
font-size: 13px;
color: #8f8;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-all;
}
.dev-panel.visible {
display: block;
}
@media (max-width: 768px) {
.player-number {
font-size: 44px;
}
.status-title {
font-size: 16px;
}
.player-badge {
padding: 5px 12px;
font-size: 12px;
}
.fog-status-line {
flex-wrap: wrap;
}
.fog-controls {
gap: 5px;
}
.fog-btn {
padding: 5px 12px;
font-size: 12px;
}
.dev-panel {
font-size: 11px;
}
}
</style>
</head>
<body>
<div class="video-background">
<video autoplay muted loop playsinline id="bgVideo">
<source src="videos/timelapse.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
</div>
<div class="content">
<header>
<h1>CreateCraft: <strong>About</strong></h1>
<p><a href="demo.php">DEMO</a></p>
</header>
<main>
<!-- Server Status Card -->
<div class="card">
<div class="server-status-line">
<div class="status-dot <?php echo $server['online'] ? 'online' : 'offline'; ?>"></div>
<div class="status-title <?php echo $server['online'] ? 'online' : 'offline'; ?>">
CreateCraft is <?php echo $server['online'] ? 'Online' : 'Offline'; ?>
</div>
</div>
<!-- Fog Status Line -->
<div class="fog-status-line" id="fogStatusLine">
<span class="fog-icon <?php echo $is_fog_active ? 'active' : ''; ?>" id="fogIcon" title="Double-click for details"><?php echo substr($fog['status'], 0, 2); ?></span>
<span class="fog-label">Status:</span>
<span class="fog-status-text" id="fogStatusText"><?php echo htmlspecialchars($fog['status']); ?></span>
<?php if (!empty($fog['next_event'])): ?>
<span class="fog-next-event" id="fogNextEvent">⏳ <?php echo htmlspecialchars($fog['next_event']); ?></span>
<?php endif; ?>
</div>
<div class="fog-height" id="fogHeight">Fog height: <?php echo $fog['current_height'] ?? 0; ?> blocks</div>
<div class="fog-last-update" id="fogUpdate">Last updated: <?php echo $last_updated; ?></div>
<!-- Secret Dev Panel (double-click fog icon) -->
<div class="dev-panel" id="devPanel">
<div style="margin-bottom: 10px; color: #ff9; font-weight: bold;">🔧 Developer Controls</div>
<!-- Fog Control Buttons -->
<div class="fog-controls">
<form method="POST" style="display: contents;">
<button type="submit" name="fog_command" value="rise" class="fog-btn fog-btn-rise">🌫️ Rise</button>
<button type="submit" name="fog_command" value="fall" class="fog-btn fog-btn-fall">🌤️ Fall</button>
<button type="submit" name="fog_command" value="clear" class="fog-btn fog-btn-clear">✨ Clear</button>
<button type="submit" name="fog_command" value="reset" class="fog-btn fog-btn-reset">🔄 Reset</button>
<button type="submit" name="fog_command" value="status" class="fog-btn fog-btn-status">📊 Status</button>
</form>
</div>
<?php if ($command_result): ?>
<div class="command-result <?php echo strpos($command_result, '✅') !== false ? '' : 'error'; ?>">
<?php echo $command_result; ?>
</div>
<?php endif; ?>
<!-- Full JSON Data -->
<div style="margin-top: 12px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 12px;">
<span style="color: #ff9;">📊 Full Fog Data</span>
<?php
echo "\n" . json_encode($fog, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>
</div>
</div>
<div class="dev-hint" id="devHint">🔧 double-click the fog icon</div>
<?php if ($server['online']): ?>
<div class="player-stats">
<div class="player-number" id="playerCount"><?php echo $server['players']; ?></div>
<div class="player-max">Players Online / <?php echo $server['max_players']; ?></div>
</div>
<div class="version-line">
Running: <?php echo htmlspecialchars($server['version']); ?>
</div>
<div class="players-section">
<div class="players-toggle" onclick="togglePlayers()">
📋 <?php echo !empty($server['players_list']) ? count($server['players_list']) . ' player' . (count($server['players_list']) != 1 ? 's' : '') . ' online' : 'No players online'; ?>
</div>
<div id="playersContainer" class="players-container" style="<?php echo !empty($server['players_list']) ? 'display: flex;' : 'display: none;'; ?>">
<?php foreach ($server['players_list'] as $player): ?>
<span class="player-badge"><?php echo htmlspecialchars($player['name']); ?></span>
<?php endforeach; ?>
<?php if (empty($server['players_list'])): ?>
<div class="no-players-msg">Be the first to join!</div>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="no-players-msg">
Server is offline. Start it to see player information!
</div>
<?php endif; ?>
</div>
<!-- Quick Links Card -->
<div class="card">
<h2>Quick Links</h2>
<div class="quick-links-nav">
<a href="index.php">Home</a>
<a href="factions.php">Factions</a>
<a href="about.php">About</a>
<a href="https://discord.com/invite/959SAvcCpp" target="_blank">Discord</a>
</div>
</div>
</main>
<footer>
<p>© <?php echo date('Y'); ?> CreateCraft SI | Built with PHP | Server status updates every 5 seconds</p>
</footer>
</div>
<script>
let lastPlayerCount = <?php echo $server['players']; ?>;
let devPanelVisible = false;
function togglePlayers() {
const container = document.getElementById('playersContainer');
if (container.style.display === 'none' || container.style.display === '') {
container.style.display = 'flex';
} else {
container.style.display = 'none';
}
}
document.getElementById('fogIcon').addEventListener('dblclick', function(e) {
const panel = document.getElementById('devPanel');
const hint = document.getElementById('devHint');
devPanelVisible = !devPanelVisible;
if (devPanelVisible) {
panel.classList.add('visible');
hint.textContent = '🔧 double-click to hide';
} else {
panel.classList.remove('visible');
hint.textContent = '🔧 double-click the fog icon';
}
});
function updateServerStatus() {
fetch(window.location.href + '?ajax=1')
.then(response => response.text())
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const newCountElem = doc.querySelector('.player-number');
if (newCountElem) {
const newCount = parseInt(newCountElem.textContent);
const countElem = document.getElementById('playerCount');
if (countElem && !isNaN(newCount) && newCount !== lastPlayerCount) {
countElem.style.transform = 'scale(1.1)';
setTimeout(() => {
countElem.style.transform = 'scale(1)';
}, 200);
countElem.textContent = newCount;
lastPlayerCount = newCount;
}
}
const newPlayersContainer = doc.querySelector('.players-container');
const newPlayersToggle = doc.querySelector('.players-toggle');
if (newPlayersContainer && newPlayersToggle) {
const currentContainer = document.getElementById('playersContainer');
const currentToggle = document.querySelector('.players-toggle');
if (currentContainer && currentToggle) {
currentContainer.innerHTML = newPlayersContainer.innerHTML;
currentToggle.textContent = newPlayersToggle.textContent;
const hasPlayers = newPlayersContainer.innerHTML.includes('player-badge');
if (hasPlayers && currentContainer.style.display === 'none') {
currentContainer.style.display = 'flex';
} else if (!hasPlayers && currentContainer.style.display !== 'none') {
currentContainer.style.display = 'none';
}
}
}
const newFogStatus = doc.querySelector('.fog-status-text');
const newFogNext = doc.querySelector('.fog-next-event');
const newFogHeight = doc.querySelector('.fog-height');
const newFogUpdate = doc.querySelector('.fog-last-update');
const newFogIcon = doc.querySelector('.fog-icon');
if (newFogStatus) {
const currentFogStatus = document.getElementById('fogStatusText');
if (currentFogStatus) currentFogStatus.textContent = newFogStatus.textContent;
}
if (newFogNext) {
const currentFogNext = document.getElementById('fogNextEvent');
if (currentFogNext) {
currentFogNext.textContent = newFogNext.textContent;
currentFogNext.style.display = 'inline';
}
} else {
const currentFogNext = document.getElementById('fogNextEvent');
if (currentFogNext) currentFogNext.style.display = 'none';
}
if (newFogHeight) {
const currentFogHeight = document.getElementById('fogHeight');
if (currentFogHeight) currentFogHeight.textContent = newFogHeight.textContent;
}
if (newFogUpdate) {
const currentFogUpdate = document.getElementById('fogUpdate');
if (currentFogUpdate) currentFogUpdate.textContent = newFogUpdate.textContent;
}
if (newFogIcon) {
const currentFogIcon = document.getElementById('fogIcon');
if (currentFogIcon) {
currentFogIcon.textContent = newFogIcon.textContent;
const isActive = newFogIcon.textContent.includes('🌫️');
if (isActive) {
currentFogIcon.classList.add('active');
} else {
currentFogIcon.classList.remove('active');
}
}
}
})
.catch(err => console.log('Update failed:', err));
}
setInterval(updateServerStatus, 5000);
document.querySelectorAll('.fog-btn').forEach(btn => {
btn.addEventListener('click', function(e) {
const command = this.value;
if (command === 'reset') {
if (!confirm('⚠️ Are you sure you want to reset the fog system? This will restart the 24-hour grace period.')) {
e.preventDefault();
}
}
if (command === 'clear') {
if (!confirm('⚠️ Are you sure you want to clear the fog immediately?')) {
e.preventDefault();
}
}
});
});
</script>
</body>
</html>
← Back