Events empfangen: Webhook-System
Event-Datenfluss
Wenn in Minecraft etwas passiert (Spieler stirbt, Login, etc.), sendet das Spiel-Plugin einen HTTP-POST-Request an dein Plugin. Das nennt sich Webhook.
Flow:
Minecraft Event (player_death)
↓
Minecraft-Plugin prüft configServerAPI.yml
↓
Sendet HTTP-POST → http://localhost:PORT/webhook
↓
Dein Plugin (@app.route("/webhook")) empfängt
↓
Dein Plugin verarbeitet & reagiert
Verfügbare Events
[!NOTE] Eine Komplette Liste aller Events findest du in der
configServerAPI.ymlim Projekt. Hier ein paar Beispiele:
player_deathplayer_respawnplayer_joinplayer_quitblock_breakentity_death
Webhook-Implementation: 3 Schritte
1. Flask Server starten (im Main Thread)
from flask import Flask, request
app = Flask(__name__)
def start_server():
app.run(host="127.0.0.1", port=8001, debug=False, threaded=True)
import threading
srv = threading.Thread(target=start_server, daemon=True)
srv.start()
2. /webhook Endpoint definieren
@app.route("/webhook", methods=['POST'])
def webhook():
try:
data = request.json
event_type = data.get("event")
if event_type == "player_death":
print(f"Spieler gestorben: {data.get('player')}")
elif event_type == "block_break":
print(f"Block abgebaut: {data.get('block')}")
return {"status": "ok"}, 200
except Exception as e:
print(f"Webhook-Fehler: {e}")
return {"status": "error"}, 500
3. In config.yaml registrieren
MyPlugin:
Enable: true
WebServerPort: 8001
und in der configServerAPI.yml:
urls:
- "http://localhost:7777/webhook"
- "http://localhost:7878/webhook"
- "http://localhost:7979/webhook"
- "http://localhost:8080/webhook"
- "http://localhost:8001/webhook" # Dein webhook
Komplettes Beispiel: DeathCounter
from flask import Flask, request
import json
from pathlib import Path
app = Flask(__name__)
DATA_DIR = Path(".") / "data"
DEATHS_FILE = DATA_DIR / "deathcount.json"
# Zähler laden
if DEATHS_FILE.exists():
with open(DEATHS_FILE) as f:
death_count = json.load(f).get("count", 0)
else:
death_count = 0
@app.route("/")
def index():
return f"<h1>Tod-Zähler: {death_count}</h1>"
@app.route("/webhook", methods=['POST'])
def webhook():
global death_count
data = request.json
if data.get("event") == "player_death":
death_count += 1
# Speichern
with open(DEATHS_FILE, "w") as f:
json.dump({"count": death_count}, f)
print(f"[+] Tode: {death_count}")
return {"status": "ok"}, 200
if __name__ == '__main__':
import threading
threading.Thread(target=lambda: app.run(port=8001), daemon=True).start()
input("Server läuft. Enter zum Stoppen...")
Webhook in dein Plugin integrieren
Um Webhooks zu empfangen, brauchst du einen HTTP-Server in deinem Plugin. Flask ist dafür perfekt geeignet:
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
event_data = request.json
event_type = event_data.get("event")
if event_type == "player_death":
print("Spieler ist gestorben!")
elif event_type == "player_respawn":
print("Spieler ist respawnt!")
return "OK", 200
Das ist das Minimum. Dein Plugin muss:
- Flask starten und auf Port X lauschen
- Den
/webhookEndpoint bereitstellen - Den POST-Request verarbeiten und reagieren
Praktisches Beispiel: Der Timer
Der Timer-Plugin reagiert auf zwei Events:
@app.route('/webhook', methods=['POST'])
def webhook():
ev = request.json.get("event")
if ev == "player_death":
window.evaluate_js("resetTimer(); setPaused(true);")
elif ev == "player_respawn":
window.evaluate_js("setPaused(false);")
return "OK"
Wenn ein Spieler stirbt:
- Timer wird zurückgesetzt
- Timer wird pausiert
Wenn ein Spieler respawnt:
- Timer läuft weiter
Die Event-Payload verstehen
Wenn ein Event ankommt, sieht der Request so aus:
{
"load_type": "INGAME_GAMEPLAY",
"event": "player_death",
"message": "Player died from fall damage"
}
Je nach load_type kannst du unterschiedliche Verhaltensweisen programmieren:
INGAME_GAMEPLAY: Das Event ist vom laufenden SpielSTARTUP: Das Event ist beim Server-Start- Andere: siehe
configServerAPI.yml
Webhook-URL konfigurieren
Dein Plugin muss in der config.yaml eine Port-Einstellung haben. Die configServerAPI.yml ruft dann diese URL auf:
# config.yaml
MinecraftServerAPI:
WebServerPortDeathCounter: 7979
WebServerPortTimer: 7878
Die Webhook-URLs werden dann so konfiguriert:
# configServerAPI.yml
webhooks:
urls:
- "http://localhost:7979/webhook" # DeathCounter
- "http://localhost:7878/webhook" # Timer
[!IMPORTANT] Der Port muss eindeutig sein! Kein anderes Plugin darf den gleichen Port nutzen.
Threading: Flask im Hintergrund starten
Ein wichtiger Punkt: Dein Plugin läuft nach der Registrierung weiter. Wenn du Flask direkt mit app.run() aufrufst, blockiert das alles danach.
Die Lösung: Flask in einem Thread starten:
import threading
def start_flask_server():
app.run(host='127.0.0.1', port=7878, debug=False)
# Im Hauptprogramm:
flask_thread = threading.Thread(target=start_flask_server, daemon=True)
flask_thread.start()
# Dein restlicher Code läuft parallel weiter...
Mit daemon=True wird der Thread automatisch beendet, wenn dein Plugin beendet wird.
Fehlerbehandlung
Nicht immer funktioniert alles. Ein paar wichtige Punkte:
-
Webhook funktioniert nicht?
- Prüf, dass dein Port in
config.yamleingestellt ist - Prüf, dass die URL in
configServerAPI.ymlkorrekt ist - Schau in deine Log-Datei
- Prüf, dass dein Port in
-
Port schon in Verwendung?
- Wähle einen anderen Port oder beende das andere Programm
Zusammenfassung
- Webhooks sind HTTP POST-Requests von Minecraft zu deinem Plugin
- Flask macht die Implementierung einfach
- Der
/webhookEndpoint verarbeitet eingehende Events - Der Port muss in
config.yamlundconfigServerAPI.ymlsynchronisiert sein - Threading ist wichtig, damit der Flask-Server nicht alles blockiert
Nächstes Kapitel: Konfiguration und Datenspeicherung