init
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
data/*
|
||||
backups/*.tar.gz
|
||||
17
README.md
Normal file
17
README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
**Struktura**
|
||||
|
||||
mc-server/
|
||||
├── data/ # Svět a soubory serveru (svázané přes Docker volume)
|
||||
├── backups/ # Automatické zálohy
|
||||
├── docker-compose.yml # Minecraft server v Dockeru
|
||||
├── backup.sh # 🔁 Pravidelné zálohy světa
|
||||
├── restore.sh # ♻️ Obnova zálohy podle výběru
|
||||
├── start.sh # ▶️ Spuštění serveru
|
||||
├── stop.sh # ⛔ Zastavení serveru (volitelné)
|
||||
└── restart.sh # 🔄 Restart serveru (volitelné)
|
||||
|
||||
|
||||
|
||||
**cron job:**
|
||||
|
||||
*/15 * * * * /cesta/mc-server/backup.sh >> /cesta/mc-server/backup.log 2>&1
|
||||
39
backup.sh
Normal file
39
backup.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Absolutní cesta ke skriptu
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
CONTAINER="mc-vanilla"
|
||||
BACKUP_DIR="/mnt/backups/minecraft_backups/frankstein"
|
||||
WORLD_DIR="$DIR/data/world"
|
||||
|
||||
DATE_FULL=$(date +%F_%H-%M)
|
||||
DATE_HOUR=$(date +%F_%H)
|
||||
DATE_DAY=$(date +%F)
|
||||
|
||||
ARCHIVE_NAME="$BACKUP_DIR/world_$DATE_FULL.tar.gz"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Zakázání ukládání ve hře
|
||||
docker exec -i $CONTAINER rcon-cli save-off
|
||||
docker exec -i $CONTAINER rcon-cli save-all
|
||||
sleep 3
|
||||
|
||||
# Vytvoření zálohy
|
||||
tar -czf "$ARCHIVE_NAME" "$WORLD_DIR"
|
||||
|
||||
# Znovupovolení ukládání
|
||||
docker exec -i $CONTAINER rcon-cli save-on
|
||||
|
||||
# Smazání všech záloh ze stejné hodiny, kromě nejnovější
|
||||
find "$BACKUP_DIR" -name "world_${DATE_HOUR}_*.tar.gz" ! -newer "$ARCHIVE_NAME" -delete
|
||||
|
||||
# Zachování pouze nejnovější zálohy z každého předchozího dne
|
||||
find "$BACKUP_DIR" -name "world_*.tar.gz" | while read file; do
|
||||
file_day=$(basename "$file" | cut -d'_' -f2)
|
||||
newest=$(find "$BACKUP_DIR" -name "world_${file_day}_*.tar.gz" | sort | tail -n 1)
|
||||
if [ "$file" != "$newest" ]; then
|
||||
rm "$file"
|
||||
fi
|
||||
done
|
||||
1
backups/poznamka.md
Normal file
1
backups/poznamka.md
Normal file
@@ -0,0 +1 @@
|
||||
tady se budou nacházet zálohy serveru až se spustí!
|
||||
5
discord-bot/.env-bot
Normal file
5
discord-bot/.env-bot
Normal file
@@ -0,0 +1,5 @@
|
||||
TOKEN='MTI1ODE0NDgxODk3OTE0Nzg5Ng.GKTl0Q.4vzvSFiPs8tl93B42R7PcqpM70C2Ov0YXHQdVU'
|
||||
GUILD_ID=938745671870185482
|
||||
CHANNEL_ID=1382456524009640057
|
||||
MC_HOST='147.185.221.29'
|
||||
MC_PORT=7272
|
||||
11
discord-bot/Dockerfile
Normal file
11
discord-bot/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
# discord-bot/Dockerfile
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /discord-bot
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD ["python", "frankstein-bot.py"]
|
||||
52
discord-bot/frankstein-bot.py
Normal file
52
discord-bot/frankstein-bot.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import discord
|
||||
from discord.ext import tasks, commands
|
||||
from mcstatus import JavaServer
|
||||
|
||||
import os
|
||||
|
||||
TOKEN = os.environ['TOKEN']
|
||||
MC_HOST = os.environ.get('MC_HOST', 'localhost')
|
||||
MC_PORT = int(os.environ.get('MC_PORT', 7272))
|
||||
CHANNEL_ID = int(os.environ['CHANNEL_ID'])
|
||||
|
||||
|
||||
|
||||
intents = discord.Intents.default()
|
||||
bot = commands.Bot(command_prefix='!', intents=intents)
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
print(f'Přihlášen jako {bot.user}')
|
||||
update_status.start()
|
||||
|
||||
@tasks.loop(seconds=5)
|
||||
async def update_status():
|
||||
channel = bot.get_channel(CHANNEL_ID)
|
||||
if channel is None:
|
||||
print("Kanál nenalezen.")
|
||||
return
|
||||
|
||||
try:
|
||||
server = JavaServer(MC_HOST, MC_PORT)
|
||||
status = server.status()
|
||||
|
||||
player_count = status.players.online
|
||||
name = f'🟢|online|👤:{player_count}'
|
||||
|
||||
except Exception as e:
|
||||
print("Server offline nebo nelze připojit:", e)
|
||||
name = '🔴|server down!!!'
|
||||
|
||||
try:
|
||||
if name != channel.name:
|
||||
await channel.edit(name=name)
|
||||
|
||||
|
||||
except discord.Forbidden:
|
||||
|
||||
print("Bot nemá oprávnění měnit název kanálu.")
|
||||
|
||||
except discord.HTTPException as e:
|
||||
print("HTTP chyba:", e)
|
||||
|
||||
bot.run(TOKEN)
|
||||
3
discord-bot/requirements.txt
Normal file
3
discord-bot/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
discord.py
|
||||
mcstatus
|
||||
python-dotenv
|
||||
37
docker-compose.yml
Normal file
37
docker-compose.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
services:
|
||||
mc-vanilla:
|
||||
image: itzg/minecraft-server
|
||||
container_name: mc-vanilla
|
||||
ports:
|
||||
- "25565:25565"
|
||||
environment:
|
||||
TZ: "Europe/Prague"
|
||||
#TYPE: "PAPER"
|
||||
VERSION: "1.21.6"
|
||||
EULA: "TRUE"
|
||||
ENABLE_RCON: "true"
|
||||
RCON_PASSWORD: "Revoluce@1989"
|
||||
RCON_PORT: 25575
|
||||
MAX_PLAYERS: 6
|
||||
VIEW_DISTANCE: 20
|
||||
SIMULATION_DISTANCE: 10
|
||||
OVERRIDE_ICON: true
|
||||
ICON: /icon.png
|
||||
DIFFICULTY: hard
|
||||
MEMORY: 10G
|
||||
INIT_MEMORY: 10G
|
||||
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./icon.png:/icon.png
|
||||
restart: unless-stopped
|
||||
|
||||
frankstein-discord-bot:
|
||||
image: python:3.11-slim
|
||||
build:
|
||||
context: ./discord-bot
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ./discord-bot:/discord-bot
|
||||
env_file:
|
||||
- discord-bot/.env-bot
|
||||
70
minecraft_env_vars.md
Normal file
70
minecraft_env_vars.md
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
Minecraft Server Docker Environment Variables (itzg/minecraft-server)
|
||||
=====================================================================
|
||||
|
||||
🧩 Server Configuration
|
||||
-----------------------
|
||||
EULA: Must be set to "TRUE" to accept the Minecraft EULA.
|
||||
VERSION: Specify the Minecraft server version, e.g., "1.20.4".
|
||||
TYPE: Server type, such as "VANILLA", "FORGE", "FABRIC", "PAPER", etc.
|
||||
MOTD: Message of the day displayed in the server list.
|
||||
DIFFICULTY: Game difficulty; options: "peaceful", "easy", "normal", "hard".
|
||||
MAX_PLAYERS: Max number of players allowed.
|
||||
VIEW_DISTANCE: Number of chunks sent to players around them.
|
||||
ALLOW_NETHER: Enable or disable the Nether.
|
||||
ENABLE_COMMAND_BLOCK: Enable or disable command blocks.
|
||||
FORCE_GAMEMODE: Force players to join in the default game mode.
|
||||
GENERATE_STRUCTURES: Enable or disable structure generation.
|
||||
HARDCORE: Enable or disable hardcore mode.
|
||||
MAX_BUILD_HEIGHT: Max build height.
|
||||
SPAWN_ANIMALS: Enable or disable animal spawning.
|
||||
SPAWN_MONSTERS: Enable or disable monster spawning.
|
||||
SPAWN_NPCS: Enable or disable NPC spawning.
|
||||
SPAWN_PROTECTION: Radius of spawn protection for non-ops.
|
||||
LEVEL_NAME: Name of the world folder.
|
||||
LEVEL_TYPE: "DEFAULT", "FLAT", "LARGEBIOMES", "AMPLIFIED", "CUSTOMIZED".
|
||||
LEVEL_SEED: World seed.
|
||||
PVP: Enable or disable player combat.
|
||||
ONLINE_MODE: Enable/disable Mojang authentication.
|
||||
ALLOW_FLIGHT: Allow/disallow flight.
|
||||
|
||||
🛡️ Access Control
|
||||
-----------------
|
||||
WHITELIST: Comma-separated list of usernames.
|
||||
OPS: Comma-separated list of operators.
|
||||
ENABLE_WHITELIST: Enable/disable whitelist.
|
||||
ENFORCE_WHITELIST: Always enforce whitelist.
|
||||
|
||||
⚙️ Advanced Settings
|
||||
--------------------
|
||||
ICON: URL or file path to server icon.
|
||||
OVERRIDE_ICON: TRUE to override existing icon.
|
||||
ENABLE_RCON: Enable/disable RCON.
|
||||
RCON_PASSWORD: RCON password.
|
||||
RCON_PORT: Default is 25575.
|
||||
ENABLE_QUERY: Enable/disable GameSpy4 query.
|
||||
QUERY_PORT: Default is 25565.
|
||||
ENABLE_JMX: Enable/disable JMX.
|
||||
JMX_PORT: Default is 7091.
|
||||
USE_AIKAR_FLAGS: Use Aikar's JVM flags.
|
||||
JVM_OPTS, JVM_XX_OPTS, JVM_DD_OPTS: JVM tuning.
|
||||
EXTRA_ARGS: Extra server args.
|
||||
LOG_TIMESTAMP: Include timestamps in logs.
|
||||
ENABLE_ROLLING_LOGS: Enable rolling logs.
|
||||
|
||||
🧪 Experimental/Modding
|
||||
------------------------
|
||||
MODPACK, MODPACK_VERSION: Modpack configs.
|
||||
MODRINTH_PROJECT, MODRINTH_VERSION: Modrinth config.
|
||||
CURSEFORGE_PROJECT, CURSEFORGE_FILE_ID: CurseForge config.
|
||||
AUTODOWNLOAD: Automatically download mods.
|
||||
|
||||
🕒 Time and Locale
|
||||
------------------
|
||||
TZ: Timezone, e.g., "Europe/Prague".
|
||||
|
||||
🧰 Custom Properties
|
||||
--------------------
|
||||
CUSTOM_SERVER_PROPERTIES: Newline-separated key=value for custom settings.
|
||||
|
||||
See: https://github.com/itzg/docker-minecraft-server
|
||||
8
restart.sh
Normal file
8
restart.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
SERVICE_NAME="mc-vanilla"
|
||||
|
||||
echo "🔄 Restartuji server..."
|
||||
docker compose up -d --force-recreate --build "$SERVICE_NAME"
|
||||
|
||||
|
||||
34
restore.sh
Normal file
34
restore.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
#relative path
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
|
||||
CONTAINER="mc-vanilla"
|
||||
BACKUP_DIR="/mnt/backups/minecraft_backups/frankstein"
|
||||
WORLD_DIR="$DIR/data/world"
|
||||
|
||||
mapfile -t BACKUPS < <(ls -1t "$BACKUP_DIR"/world_*.tar.gz)
|
||||
if [ ${#BACKUPS[@]} -eq 0 ]; then
|
||||
echo "❌ Žádné zálohy nenalezeny!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Dostupné zálohy:"
|
||||
for i in "${!BACKUPS[@]}"; do
|
||||
echo "[$i] ${BACKUPS[$i]}"
|
||||
done
|
||||
|
||||
read -p "🔁 Zadej číslo zálohy: " INDEX
|
||||
SELECTED="${BACKUPS[$INDEX]}"
|
||||
[ -z "$SELECTED" ] && echo "❌ Neplatný výběr." && exit 1
|
||||
|
||||
read -p "⚠️ Přepsat svět? (y/N): " CONFIRM
|
||||
[[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]] && exit 0
|
||||
|
||||
docker compose stop "$CONTAINER"
|
||||
rm -rf "$WORLD_DIR"
|
||||
tar -xzf "$SELECTED" -C .
|
||||
|
||||
read -p "▶️ Spustit server? (y/N): " AUTOSTART
|
||||
[[ "$AUTOSTART" == "y" || "$AUTOSTART" == "Y" ]] && docker compose up -d --force-recreate "$CONTAINER"
|
||||
10
start.sh
Normal file
10
start.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
SERVICE_NAME="mc-vanilla"
|
||||
|
||||
if docker ps --format '{{.Names}}' | grep -q "$SERVICE_NAME"; then
|
||||
echo "✅ Server už běží."
|
||||
else
|
||||
echo "▶️ Spouštím server..."
|
||||
docker compose up -d --force-recreate "$SERVICE_NAME"
|
||||
fi
|
||||
Reference in New Issue
Block a user