Version Forge
@@ -324,6 +325,9 @@ function getDashboardHTML() {
async function loadDashboardData() {
try {
+ // Charger les joueurs en ligne
+ await window.loadOnlinePlayers();
+
const response = await fetch(`${API_URL}/server`, {
credentials: 'include'
});
@@ -340,6 +344,27 @@ async function loadDashboardData() {
| Max Joueurs | ${data.properties['max-players'] || '20'} |
`;
}
+
+ // Mettre à jour le nombre de joueurs
+ const onlineResponse = await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: 'list' })
+ });
+
+ if (onlineResponse.ok) {
+ const rconData = await onlineResponse.json();
+ const output = rconData.response || '';
+ const cleanOutput = output.replace(/§[0-9a-fk-or]/gi, '');
+ const match = cleanOutput.match(/There are (\d+) out of maximum (\d+) players online/i);
+
+ if (match) {
+ const onlineCount = parseInt(match[1]);
+ const maxPlayers = parseInt(match[2]);
+ document.getElementById('playerCount').textContent = `${onlineCount}/${maxPlayers}`;
+ }
+ }
} catch (e) {
console.error('Erreur chargement dashboard:', e);
}
@@ -351,10 +376,21 @@ function getConsoleHTML() {
⌨️ Console RCON
Exécutez des commandes directement sur le serveur
-
-
+
+
+
+
+
💬 Envoyer un Message
+
+
+
+
+
+
+
+
+
+
+
+
⏹️ Arrêter le Serveur
+
+
+
+
+
+
+
+
+
⚠️ Un message d'avertissement sera envoyé tous les 10 secondes
+
+
+
+
+
+
+
+
+
+
+
🔄 Redémarrer le Serveur
+
+
+
+
+
+
+
+
+
ℹ️ Un message d'avertissement sera envoyé tous les 10 secondes
+
+
+
+
+
+
`;
}
@@ -443,7 +531,7 @@ async function sendRconCommand() {
if (!command) return;
const output = document.getElementById('consoleOutput');
- output.innerHTML += `
$ ${command}
`;
+ output.textContent += `admin@nationsglory:~$ ${command}\n`;
commandInput.value = '';
try {
@@ -457,22 +545,264 @@ async function sendRconCommand() {
const data = await response.json();
if (response.ok) {
- output.innerHTML += `
${data.response || '(pas de réponse)'}
`;
+ const responseText = data.response || '(pas de réponse)';
+ output.textContent += `${responseText}\n`;
showMessage('Commande exécutée ✓', 'success', 'dashboardMessage');
loadConsoleData(); // Rafraîchir l'historique
} else {
- output.innerHTML += `
Erreur: ${data.error}
`;
+ output.textContent += `Erreur: ${data.error}\n`;
showMessage(data.error, 'error', 'dashboardMessage');
}
output.scrollTop = output.scrollHeight;
} catch (e) {
console.error('Erreur envoi commande:', e);
- output.innerHTML += `
Erreur serveur: ${e.message}
`;
+ output.textContent += `Erreur serveur: ${e.message}\n`;
showMessage('Erreur serveur', 'error', 'dashboardMessage');
+ output.scrollTop = output.scrollHeight;
}
}
+// Variables globales pour gérer l'arrêt du serveur
+let shutdownInProgress = false;
+let shutdownCancelToken = null;
+
+window.openSayModal = function() {
+ document.getElementById('sayModal').style.display = 'flex';
+};
+
+window.sendSayCommand = async function() {
+ const message = document.getElementById('sayInput').value.trim();
+ if (!message) {
+ alert('Entrez un message');
+ return;
+ }
+
+ try {
+ const response = await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: `say ${message}` })
+ });
+
+ if (response.ok) {
+ showMessage('Message envoyé ✓', 'success', 'dashboardMessage');
+ document.getElementById('sayInput').value = '';
+ document.getElementById('sayModal').style.display = 'none';
+ loadConsoleData();
+ } else {
+ showMessage('Erreur lors de l\'envoi du message', 'error', 'dashboardMessage');
+ }
+ } catch (e) {
+ console.error('Erreur envoi message:', e);
+ showMessage('Erreur serveur', 'error', 'dashboardMessage');
+ }
+};
+
+window.openShutdownModal = function() {
+ document.getElementById('shutdownModal').style.display = 'flex';
+};
+
+window.shutdownServer = async function() {
+ const cooldown = parseInt(document.getElementById('shutdownCooldown').value);
+ const message = document.getElementById('shutdownMessage').value.trim();
+
+ if (cooldown < 10 || cooldown > 600) {
+ alert('Le cooldown doit être entre 10 et 600 secondes');
+ return;
+ }
+
+ if (!message) {
+ alert('Entrez un message d\'avertissement');
+ return;
+ }
+
+ if (!confirm(`Êtes-vous sûr de vouloir arrêter le serveur dans ${cooldown} secondes?`)) {
+ return;
+ }
+
+ try {
+ shutdownInProgress = true;
+ shutdownCancelToken = {};
+ document.getElementById('cancelShutdownBtn').style.display = 'block';
+ document.getElementById('shutdownModal').style.display = 'none';
+
+ showMessage(`⏳ Arrêt du serveur dans ${cooldown} secondes...`, 'warning', 'dashboardMessage');
+
+ let secondsRemaining = cooldown;
+
+ while (secondsRemaining > 0 && shutdownInProgress && shutdownCancelToken) {
+ if (secondsRemaining % 10 === 0 || secondsRemaining <= 10) {
+ // Envoyer un avertissement tous les 10 secondes (ou chaque seconde dans les 10 dernières)
+ const warningMsg = message.replace('{cooldown}', secondsRemaining);
+ await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: `say ${warningMsg}` })
+ }).catch(() => {});
+ }
+
+ await new Promise(resolve => setTimeout(resolve, 1000));
+ secondsRemaining--;
+ }
+
+ if (!shutdownInProgress || !shutdownCancelToken) {
+ // Envoyer un message dans le chat pour informer de l'annulation
+ await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: 'say Arrêt du serveur annulé!' })
+ }).catch(() => {});
+
+ showMessage('❌ Arrêt annulé', 'warning', 'dashboardMessage');
+ document.getElementById('cancelShutdownBtn').style.display = 'none';
+ document.getElementById('cancelShutdownBtnDash').style.display = 'none';
+ return;
+ }
+
+ // Envoyer la commande d'arrêt
+ const response = await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: 'stop' })
+ });
+
+ if (response.ok) {
+ showMessage('✓ Serveur arrêté', 'success', 'dashboardMessage');
+ } else {
+ showMessage('Erreur lors de l\'arrêt du serveur', 'error', 'dashboardMessage');
+ }
+
+ shutdownInProgress = false;
+ shutdownCancelToken = null;
+ document.getElementById('cancelShutdownBtn').style.display = 'none';
+ document.getElementById('cancelShutdownBtnDash').style.display = 'none';
+ loadConsoleData();
+ } catch (e) {
+ console.error('Erreur arrêt serveur:', e);
+ showMessage('Erreur serveur', 'error', 'dashboardMessage');
+ shutdownInProgress = false;
+ shutdownCancelToken = null;
+ document.getElementById('cancelShutdownBtn').style.display = 'none';
+ }
+};
+
+window.cancelShutdown = function() {
+ if (shutdownInProgress) {
+ shutdownInProgress = false;
+ shutdownCancelToken = null;
+ document.getElementById('cancelShutdownBtn').style.display = 'none';
+ document.getElementById('cancelShutdownBtnDash').style.display = 'none';
+ showMessage('❌ Arrêt annulé', 'warning', 'dashboardMessage');
+ }
+};
+
+// Variables globales pour gérer le redémarrage du serveur
+let restartInProgress = false;
+let restartCancelToken = null;
+
+window.openRestartModal = function() {
+ document.getElementById('restartModal').style.display = 'flex';
+};
+
+window.restartServer = async function() {
+ const cooldown = parseInt(document.getElementById('restartCooldown').value);
+ const message = document.getElementById('restartMessage').value.trim();
+
+ if (cooldown < 10 || cooldown > 600) {
+ alert('Le cooldown doit être entre 10 et 600 secondes');
+ return;
+ }
+
+ if (!message) {
+ alert('Entrez un message d\'avertissement');
+ return;
+ }
+
+ if (!confirm(`Êtes-vous sûr de vouloir redémarrer le serveur dans ${cooldown} secondes?`)) {
+ return;
+ }
+
+ try {
+ restartInProgress = true;
+ restartCancelToken = {};
+ document.getElementById('cancelRestartBtn').style.display = 'block';
+ document.getElementById('restartModal').style.display = 'none';
+
+ showMessage(`⏳ Redémarrage du serveur dans ${cooldown} secondes...`, 'warning', 'dashboardMessage');
+
+ let secondsRemaining = cooldown;
+
+ while (secondsRemaining > 0 && restartInProgress && restartCancelToken) {
+ if (secondsRemaining % 10 === 0 || secondsRemaining <= 10) {
+ // Envoyer un avertissement tous les 10 secondes (ou chaque seconde dans les 10 dernières)
+ const warningMsg = message.replace('{cooldown}', secondsRemaining);
+ await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: `say ${warningMsg}` })
+ }).catch(() => {});
+ }
+
+ await new Promise(resolve => setTimeout(resolve, 1000));
+ secondsRemaining--;
+ }
+
+ if (!restartInProgress || !restartCancelToken) {
+ // Envoyer un message dans le chat pour informer de l'annulation
+ await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: 'say Redémarrage du serveur annulé!' })
+ }).catch(() => {});
+
+ showMessage('❌ Redémarrage annulé', 'warning', 'dashboardMessage');
+ document.getElementById('cancelRestartBtn').style.display = 'none';
+ return;
+ }
+
+ // Envoyer la commande de redémarrage
+ const response = await fetch(`${API_URL}/rcon/command`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ command: 'stop' })
+ });
+
+ if (response.ok) {
+ showMessage('✓ Serveur redémarré', 'success', 'dashboardMessage');
+ } else {
+ showMessage('Erreur lors du redémarrage du serveur', 'error', 'dashboardMessage');
+ }
+
+ restartInProgress = false;
+ restartCancelToken = null;
+ document.getElementById('cancelRestartBtn').style.display = 'none';
+ loadDashboardData();
+ } catch (e) {
+ console.error('Erreur redémarrage serveur:', e);
+ showMessage('Erreur serveur', 'error', 'dashboardMessage');
+ restartInProgress = false;
+ restartCancelToken = null;
+ document.getElementById('cancelRestartBtn').style.display = 'none';
+ }
+};
+
+window.cancelRestart = function() {
+ if (restartInProgress) {
+ restartInProgress = false;
+ restartCancelToken = null;
+ document.getElementById('cancelRestartBtn').style.display = 'none';
+ showMessage('❌ Redémarrage annulé', 'warning', 'dashboardMessage');
+ }
+};
+
// ========== LOGS ==========
function getLogsHTML() {
return `
@@ -934,15 +1264,19 @@ function getSettingsHTML() {
return `
⚙️ Paramètres du Serveur
-
+ Modifiez les paramètres du serveur en temps réel
+
+
+
+
- | Paramètre |
- Valeur |
+ Paramètre |
+ Valeur |
- | Chargement... |
+ | Chargement... |
@@ -961,18 +1295,57 @@ async function loadSettingsData() {
if (data.properties) {
const keys = Object.keys(data.properties).sort();
- tbody.innerHTML = keys.map(k => `
-
- | ${k} |
- ${escapeHtml(data.properties[k])} |
-
- `).join('');
+ tbody.innerHTML = keys.map(k => {
+ const isPassword = k.toLowerCase().includes('password') || k.toLowerCase().includes('rcon');
+ const inputType = isPassword ? 'password' : 'text';
+ const value = data.properties[k];
+
+ return `
+
+ | ${k} |
+
+
+ |
+
+ `;
+ }).join('');
}
} catch (e) {
console.error('Erreur paramètres:', e);
}
}
+async function updateSetting(input) {
+ const key = input.getAttribute('data-key');
+ const newValue = input.value;
+
+ try {
+ const response = await fetch(`${API_URL}/server/settings`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ key, value: newValue })
+ });
+
+ if (response.ok) {
+ showMessage(`✓ Paramètre ${key} modifié`, 'success', 'dashboardMessage');
+ } else {
+ const error = await response.json();
+ showMessage(`Erreur: ${error.error}`, 'error', 'dashboardMessage');
+ await loadSettingsData(); // Recharger pour annuler la modification
+ }
+ } catch (e) {
+ console.error('Erreur modification paramètre:', e);
+ showMessage('Erreur serveur', 'error', 'dashboardMessage');
+ }
+}
+
// ========== ACTIONS ==========
async function restartServer() {
diff --git a/install.sh b/install.sh
deleted file mode 100755
index ca10b55..0000000
--- a/install.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-# Configuration pour l'interface web du serveur Minecraft NationsGlory
-# ====================================================================
-
-echo "🚀 Installation de l'interface web NationsGlory Admin..."
-
-# Vérifier que Node.js est installé
-if ! command -v node &> /dev/null; then
- echo "❌ Node.js n'est pas installé. Veuillez l'installer d'abord."
- exit 1
-fi
-
-echo "✓ Node.js détecté: $(node --version)"
-
-# Créer le fichier .env
-if [ ! -f backend/.env ]; then
- echo "Création du fichier .env..."
- cp backend/.env.example backend/.env
- echo "✓ Fichier .env créé. À personnaliser dans backend/.env"
-fi
-
-# Installer les dépendances du backend
-echo ""
-echo "📦 Installation des dépendances backend..."
-cd backend
-npm install
-cd ..
-
-echo ""
-echo "✅ Installation terminée!"
-echo ""
-echo "📝 Prochaines étapes:"
-echo "1. Modifiez backend/.env avec la bonne configuration"
-echo "2. Lancez le serveur: cd backend && npm start"
-echo "3. Accédez à l'interface: http://localhost:4001"
-echo ""
-echo "ℹ️ IMPORTANT: Activez RCON dans le server.properties du serveur MC:"
-echo " - enable-rcon=true"
-echo " - rcon.port=25575"
-echo " - rcon.password=votre_mdp"
diff --git a/setup.sh b/setup.sh
deleted file mode 100755
index 8446792..0000000
--- a/setup.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-# Rendre les scripts exécutables
-chmod +x install.sh
-chmod +x start.sh
-
-# Créer les dossiers de data s'ils n'existent pas
-mkdir -p backend/data
-
-echo "✅ Préparation complète!"
-echo ""
-echo "📖 Documentation:"
-echo " - README.md - Vue d'ensemble"
-echo " - CONFIGURATION.md - Guide de configuration détaillé"
-echo " - DEPLOYMENT.md - Déploiement en production"
-echo ""
-echo "🚀 Pour démarrer:"
-echo " 1. ./install.sh"
-echo " 2. Éditer backend/.env"
-echo " 3. ./start.sh"
-echo ""
diff --git a/start.sh b/start.sh
deleted file mode 100755
index c2050f7..0000000
--- a/start.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-
-# Script de démarrage pour le serveur et l'interface web
-# =========================================================
-
-# Couleurs
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-NC='\033[0m' # No Color
-
-echo -e "${GREEN}🎮 NationsGlory Admin Panel - Démarrage${NC}"
-echo ""
-
-# Vérifier que le backend existe
-if [ ! -d "backend" ]; then
- echo -e "${RED}❌ Dossier backend non trouvé!${NC}"
- exit 1
-fi
-
-# Vérifier le fichier .env
-if [ ! -f "backend/.env" ]; then
- echo -e "${RED}❌ Fichier backend/.env non trouvé!${NC}"
- echo -e "${YELLOW}Copiez d'abord: cp backend/.env.example backend/.env${NC}"
- exit 1
-fi
-
-# Charger les variables d'environnement
-source backend/.env
-
-echo -e "${GREEN}✓ Variables d'environnement chargées${NC}"
-echo " - Port: $PORT"
-echo " - Serveur MC: $SERVER_DIR"
-echo ""
-
-# Démarrer le backend
-echo -e "${YELLOW}⏳ Démarrage du backend...${NC}"
-cd backend
-npm start