Skript: Scripting-Grundlagen für Minecraft-Server-Admins (2026)
Mit Skript bringst du Serverlogik live, ohne eine Zeile Java zu schreiben. Du tippst nahezu englischen Text in eine .sk-Datei, legst sie nach plugins/Skript/scripts/, machst /sk reload, fertig. Für Admins, die ein Join-Welcome, ein eigenes /heal, einen Killcounter oder eine kleine Wirtschaft brauchen, ohne erst einen Java-Entwickler zu finden, ist das der schnellste Weg von Idee zur funktionierenden Mechanik.
Stand 2026 ist die aktive Linie Skript 2.9.x und höher vom SkriptLang-Team (github.com/SkriptLang/Skript), unterstützt Paper 1.21+, Folia nur in experimentellen Branches. Hier kommen Installation, .sk-Aufbau, Syntax, Addons (skBee, skript-yaml, skript-reflect, skquery) und die typischen Performance-Stolperfallen.
Was Skript wirklich ist und wem es hilft
Skript ist ein Interpreter-Plugin. Es liest .sk-Textdateien, parst sie als DSL, die wie Englisch aussieht, und übersetzt das in Bukkit/Paper-Events, Commands und Effekte. Für dich als Admin heißt das: eine Mechanik, für die du sonst ein Custom-Plugin brauchen würdest, sitzt nach einem Abend.
Wer am meisten profitiert:
- Kleine SMP-Admins, die 3 bis 5 eigene Commands und ein paar Trigger brauchen.
- Public-Server-Admins, die Events schnell ausrollen wollen (Doppel-XP-Wochenende, Killstreaks, Easter-Eggs).
- Entwickler, die eine Idee testen, bevor ein vollwertiges Java-Plugin entsteht.
Wer woanders schauen sollte: Bauer von MMORPG-Kampfsystemen mit Tausenden gleichzeitigen Spielern und dichter Tick-Logik. Skript hält ganz normale SMP- und Minigame-Last problemlos aus, aber heiße Pfade gehören in Java.
Installation und das erste /sk reload
Hol dir die letzte stabile Version von GitHub-Releases auf github.com/SkriptLang/Skript/releases oder Modrinth auf modrinth.com/plugin/skript. 2026 heißt das Skript 2.9.x für Paper 1.21+.
JAR ins plugins/-Verzeichnis legen, Server einmal starten, damit das Plugin seinen Ordner anlegt. Layout nach dem ersten Boot:
plugins/Skript/
├── config.sk # globale Config
├── aliases-english.sk # Item-Namen
├── scripts/
│ ├── -disabled-script.sk # Bindestrich vorne = deaktiviert
│ └── examples/
└── lang/
Erste Datei plugins/Skript/scripts/welcome.sk:
on join:
send "&aWelcome %player% to the server!" to player
add 1 to {joins::%player's uuid%}
In Konsole oder ingame mit Permission skript.admin:
/sk reload welcome
Skript meldet, wie viele Trigger geladen wurden und ob Fehler kamen. Joinst du auf den Server, siehst du die grüne Begrüßung. Das ist dein erstes funktionierendes Skript.
Aufbau einer .sk-Datei: Events, Commands, Functions
Eine .sk-Datei ist ein Stack von Top-Level-Blöcken. Jeder Block beginnt in Spalte 0, alles drinnen ist mit exakt 4 Leerzeichen oder 1 Tab eingerückt. Skript ist da kompromisslos: Tabs und Leerzeichen mischen führt zu inconsistent indentation und die Datei lädt nicht.
Die drei Block-Typen:
1. Event-Handler. Reagiert auf ein Server-Event.
on death of a player:
broadcast "&c%victim% died at %location of victim%"
2. Command. Registriert einen eigenen Command.
command /fly [<player>]:
permission: server.fly
permission message: &cYou cannot fly here.
trigger:
if arg-1 is set:
set {_target} to arg-1
else:
set {_target} to player
if {_target} is flying:
set flight mode of {_target} to false
send "&7Flight disabled for &e%{_target}%" to player
else:
set flight mode of {_target} to true
send "&aFlight enabled for &e%{_target}%" to player
3. Function. Wiederverwendbare Logik wie eine Prozedur.
function welcomeMessage(p: player):
send "&aWelcome back, %{_p}%!" to {_p}
if difference between {lastSeen::%{_p}'s uuid%} and now is greater than 7 days:
send "&7You were gone for a while. Server is on Paper 1.21.4 now." to {_p}
set {lastSeen::%{_p}'s uuid%} to now
on join:
welcomeMessage(player)
Der Dateiname ändert nichts am Verhalten, nur wie bequem /sk reload <file> ist. Bindestrich vorn deaktiviert das Skript ohne Löschen.
Datentypen: player, item, location, block, vector, number, text
Skript ist typisiert, aber Inferenz erledigt fast alles. Das Wichtigste:
| Typ | Beispielwert | Wo es auftaucht |
|---|---|---|
player | player, arg-1, victim | Event-Handler, Command-Ziele |
item | 1 diamond, player's tool | Inventar, Drops |
location | location of player, block's location | Teleport, Mob-Spawn |
block | targeted block, event-block | Place, Break |
vector | vector(0, 1, 0) | Velocity, Knockback |
number | 42, player's health | Counter, Koordinaten |
text | "hello", "&a%player%" | Nachrichten, Namen |
entity | attacker, loop-entity | Mobs, NPCs |
world | world "world_nether" | Welt-Checks |
timespan | 5 seconds, 2 minutes | Delays, Cooldowns |
chatcolor | red, &c | Formatierung |
Konvertierung läuft über Ausdrücke wie block at location, location of entity, name of item. Kein explizites Casting nötig.
Realistischer on join Handler
Welcome-Skript mit Erstkontakt-Erkennung, VIP-Variante und Online-Zähler:
on first join:
broadcast "&6%player% &ejoined for the first time! Welcome!"
give 1 stone pickaxe of efficiency 1 to player
give 16 cooked beef to player
teleport player to {spawn}
on join:
if player has permission "server.vip":
send "&6&l[VIP] &eWelcome back, %player%" to player
else:
send "&aWelcome back, %player%" to player
add 1 to {stats::joins::%player's uuid%}
set {stats::lastjoin::%player's uuid%} to now
wait 2 ticks
set tab list header "&aServer Online" and footer "&7Players: %size of all players%" for player
on quit:
set {stats::lastquit::%player's uuid%} to now
first join feuert einmal pro UUID, join bei jedem Login. Kein Konflikt, beide laufen für einen brandneuen Spieler.
Custom Commands: /heal mit Permissions und Argumenten
Skript registriert Commands automatisch beim Laden, du fasst keine plugin.yml an.
command /heal [<player>] [<integer>]:
description: Heals a player to full or to a specific amount
aliases: /h
permission: server.heal
permission message: &cMissing permission &7server.heal
cooldown: 30 seconds
cooldown message: &cWait %remaining time% before using /heal again.
cooldown bypass: server.heal.bypass
trigger:
if arg-1 is set:
if sender does not have permission "server.heal.others":
send "&cYou cannot heal others." to sender
stop
set {_target} to arg-1
else:
if sender is not a player:
send "&cConsole must specify a player." to sender
stop
set {_target} to sender
if arg-2 is set:
set health of {_target} to arg-2
else:
heal {_target}
feed {_target}
send "&aHealed %{_target}%" to sender
if {_target} is not sender:
send "&aYou were healed by &e%sender%" to {_target}
Wichtig: cooldown ist eingebaut, permission message zeigt sich bei fehlender Permission, aliases legt /h an, stop bricht den Trigger ab. Argumente kommen über arg-1, arg-2.
Variablen: lokal, Liste, persistent
Drei Sorten:
Lokal ({_name}) lebt nur im aktuellen Trigger oder der Function:
on damage:
set {_dmg} to damage
set {_attacker} to attacker
if {_dmg} is greater than 10:
send "Big hit by %{_attacker}%" to victim
Global ({name}) wird in variables.csv persistiert und überlebt Restarts:
set {spawn} to location of player
set {server.motd} to "&aPaper 1.21.4"
List/indexed ({name::%key%} oder {name::*}) ist effektiv ein Dict:
add 1 to {kills::%attacker's uuid%}
loop {kills::*}:
send "%loop-index%: %loop-value%" to player
clear {kills::%player's uuid%}
delete {kills::%player's uuid%}
Pflicht-Gewohnheit: immer uuid als Key, niemals den Namen. Spieler tauschen ihren Nick und du verlierst die Daten. Schwere Objekte wie ganze Inventare gehören nicht ohne Grund in persistente Vars, die Datei wird sonst riesig.
Für ernsthafte Projekte: persistenten State über skript-db in SQL oder über skript-yaml in YAML auslagern. Die CSV trägt 50k bis 100k Einträge, danach werden Ladezeiten unangenehm.
Nützliche Addons: skBee, skript-yaml, skript-reflect, skquery
Vanilla-Skript deckt vielleicht 70% ab. Den Rest machen Addons.
| Addon | Zweck | Link |
|---|---|---|
| skBee | NBT, Scoreboards, Worldborder, Recipes, Fastboards, Particles | github.com/ShaneBeee/skBee |
| skript-yaml | YAML lesen und schreiben | github.com/SkriptLang/skript-yaml |
| skript-reflect | Direkte Java-Reflection (Bukkit-API roh) | github.com/TPGamesNL/skript-reflect |
| skquery | Ältere Erweiterungen, überschneidet sich mit skBee | github.com/Tuke-Nuke/SkQuery |
| skript-placeholders | Brücke zu PlaceholderAPI | github.com/APickledWalrus/skript-placeholders |
| skript-db | MySQL/SQLite-Queries | github.com/btk5h/skript-db |
2026 ersetzt skBee 3.x das meiste, was früher skquery konnte, plus moderne Paper-APIs. Nur ein Addon? Dann skBee.
skBee-Scoreboard-Beispiel:
on join:
create new scoreboard named "stats_%player's uuid%"
set line 1 of player's scoreboard to "&7&m-----------"
set line 2 of player's scoreboard to "&aKills: &f%{kills::%player's uuid%} ? 0%"
set line 3 of player's scoreboard to "&cDeaths: &f%{deaths::%player's uuid%} ? 0%"
set line 4 of player's scoreboard to "&7&m-----------"
set title of player's scoreboard to "&6Server Stats"
set player's displayed scoreboard to player's scoreboard
Typische Patterns: Killcounter, Mini-Wirtschaft, Welcome
Killcounter mit Topliste.
on death of a player:
if attacker is a player:
add 1 to {kills::%attacker's uuid%}
add 1 to {deaths::%victim's uuid%}
send "&a+1 kill &7(total: %{kills::%attacker's uuid%}%)" to attacker
command /killtop:
trigger:
send "&6&l=== Top 10 Killers ===" to player
set {_sorted::*} to sorted indexes of {kills::*} in descending order
loop {_sorted::*}:
if loop-iteration > 10:
stop loop
set {_uuid} to loop-value
set {_name} to name of offline player from uuid {_uuid}
send "&e%loop-iteration%. &f%{_name}% &7- &c%{kills::%{_uuid}%}% kills" to player
Mini-Wirtschaft ohne Vault.
on join:
if {money::%player's uuid%} is not set:
set {money::%player's uuid%} to 100
command /balance [<player>]:
aliases: /bal, /money
trigger:
if arg-1 is set:
set {_t} to arg-1
else:
set {_t} to player
send "&aBalance of &e%{_t}%&a: &6%{money::%{_t}'s uuid%} ? 0%$" to player
command /pay <player> <integer>:
trigger:
if arg-1 is sender:
send "&cYou cannot pay yourself." to sender
stop
if arg-2 is less than 1:
send "&cAmount must be positive." to sender
stop
if {money::%sender's uuid%} is less than arg-2:
send "&cNot enough money." to sender
stop
remove arg-2 from {money::%sender's uuid%}
add arg-2 to {money::%arg-1's uuid%}
send "&aPaid &6%arg-2%$ &ato &e%arg-1%" to sender
send "&aReceived &6%arg-2%$ &afrom &e%sender%" to arg-1
Performance und Stolperfallen
Skript ist mächtig, naiver Code zerlegt aber TPS. Harte Regeln:
1. Kein Loop über alle Spieler pro Tick.
Schlecht:
every tick:
loop all players:
set action bar of loop-player to "&aServer"
Gut:
every 5 seconds:
loop all players:
set action bar of loop-player to "&aServer"
Ein Tick sind 20 mal pro Sekunde. Action Bars bei 2 bis 4 Hz sehen identisch aus und kosten eine Größenordnung weniger.
2. Async, wenn möglich.
Schwere Sachen (HTTP-Calls, große YAML-Reads, SQL) gehören in async:
command /lookup <text>:
trigger:
send "&7Looking up..." to player
set {_p} to player
execute async:
set {_data} to text from "https://api.example.com/lookup/%arg-1%"
execute sync:
send "&aResult: &f%{_data}%" to {_p}
Ohne async friert der Server für die volle Request-Zeit ein.
3. Pack keine Items oder Inventare in persistente Vars, wenn nicht nötig. Serialisierung ist teuer und bläst variables.csv auf. Lootboxen lieber als Rezept (Type plus Menge plus Meta) speichern, nicht als ItemStack.
4. wait statt geschachtelter every-Blöcke. Schlecht: every 1 second: in on join:. Gut: wait 1 second oder ein Timer per Variable.
5. Profilieren mit spark. /spark profiler --thread server zeigt, ob Skript deinen Tick frisst. Viele Trigger.execute-Frames im Stack heißt schwerer Event-Handler, fast immer ein every tick oder ein fettes on damage.
Debugging: /sk reload, /sk debug
Admin-Commands, Permission skript.admin:
/sk reload alllädt alle Skripte neu./sk reload <name>lädt eine Datei (ohne.sk)./sk reload configziehtconfig.skneu, ohne das Plugin zu restarten./sk disable <name>setzt einen Bindestrich vor und lädt aus./sk enable <name>macht das rückgängig./sk infozeigt Version und Addon-Liste./sk update checkprüft auf Updates.
Lädt ein Skript nicht, kommen die Fehler in die Konsole mit genauer Zeile. Klassiker: gemischte Einrückung, Tippfehler im Event, fehlendes Addon für eine Syntax aus dem Forum.
Für tieferes Debug: Telemetrie streuen.
on damage:
broadcast "DEBUG: %attacker% hit %victim% for %damage% (final: %final damage%)"
if attacker is a player:
broadcast "DEBUG: weapon = %attacker's tool%, projectile = %projectile%"
In Production broadcast durch send to console ersetzen oder rausnehmen. Es gibt auch den skUnity Parser für Syntax-Checks ohne Live-Reload.
FAQ
Eignet sich Skript für einen großen Public-Server?
Für typisches PvP/SMP/Minigame mit 100 bis 300 gleichzeitigen Spielern absolut, solange die Performance-Regeln stehen. Bei 1000+ gleichzeitig mit Tausenden Events pro Sekunde portierst du die heißen Pfade nach Java und behältst Skript für seltene Events und Custom-Commands.
Wo finde ich fertige Skripte?
skUnity Forums, SkriptHub, GitHub. Vor dem Deploy lesen. Forenfunde verstecken oft ein every tick über alle Spieler, das deine TPS halbiert.
Warum schreit Skript inconsistent indentation?
Tabs und Leerzeichen gemischt. Datei in einem Editor mit Whitespace-Anzeige öffnen (VS Code: View > Render Whitespace) und auf einen Stil zwingen. 4 Leerzeichen sind Standard.
Was passiert mit Variablen bei einem Hard-Crash?
Skript flusht variables.csv periodisch, Default 5 Minuten (in config.sk als save interval). 1 Minute geht, kostet aber IO. Wirklich kritischen State über skript-db in SQL pumpen oder die CSV per rsync alle 10 Minuten sichern.
Läuft Skript auf Folia?
Stand 2026 unterstützt der Mainline SkriptLang/Skript Folia nicht voll, nur experimentelle Branches. Region-Aware-Server gehen mit Einschränkungen (kein Cross-Region-Zugriff ohne den richtigen Scheduler). Aktuellen Stand vor dem Umstieg in github.com/SkriptLang/Skript/issues prüfen.
Wie schütze ich einen Skript-lastigen Server vor DDoS?
Skript läuft auf Game-Event-Ebene und macht gegen L4-Floods nichts. Davor gehört ein Netzwerkfilter, zum Beispiel MineGuard. Skript ist Ingame-Logik, nicht Paket-Klempnerei.
Skript bleibt der schnellste Weg, eine Idee in eine echte Mechanik zu verwandeln, ohne ein Java-Projekt aufzusetzen. Installier es, schreib dein erstes welcome.sk, dann /heal, dann den Killcounter, und nach einer Woche hast du einen Stack eigener Logik, exakt zugeschnitten auf deinen Server. Halte nur every tick von schweren Loops fern und vergiss async nicht, sobald Disk oder Netz im Spiel sind.
Schützen Sie Ihren Server vor DDoS-Angriffen
Kostenloser Schutz mit 5-Minuten-Einrichtung. 1 TB Traffic inklusive.
Kostenlos testenWeitere Artikel
Chunky: Minecraft-Chunks vorgenerieren und Generierungs-Lag eliminieren
Das Chunky-Plugin erzeugt Chunks im Voraus, damit der Server beim Spielen nur fertige Regionen von der Disk liest. Befehle, Mathematik und reale Timings.
Minecraft-Server Regeln und Moderation: Kompletter Admin-Guide
Wie man Serverregeln erstellt, eine Moderationshierarchie aufbaut, Bestrafungs-Plugins und Anti-Cheat einrichtet. Praktische Erfahrung und fertige Vorlagen.
ViaVersion + ViaBackwards: Multi-Version-Support auf einem Minecraft-Server
Kompletter Guide zu ViaVersion, ViaBackwards und ViaRewind: 1.21-Server mit Clients ab 1.8, Support-Matrix, Installation auf Paper und Velocity, Performance und haeufige Fehler.