Minecraft Script Dokumentation

Update 0.1.5: Alle Änderungen

Minecraft Script ist eine Programmiersprache für Entwickler der mcfunctions, sowie für die Minecraft Map und Package Erschaffer. Die .mcscript Dateien werden dabei zu mcfunction compiled und generiert. Dies bietet dem Entwickler erweiterte Möglichkeiten, wie zum Beispiel Modals, Loops, Variablen, Konstanten und Command-Wrapping.

Wer das ausprobieren möchte oder Beispiele anschauen möchte, kann meinen online Editor stevertus.ga/mcscript/code besuchen und etwas herumspielen.

English documentation here

Table of Contents

  1. Installation
  2. Cli Commands
  3. file system
  4. Syntax
  5. IDEs und Syntax Highlighting

1) Installation

Der Compiler wird auch als Node.js/ Package angeboten, das lokal auf dem PC installiert wird und viele Features mehr hat: als die Online-Version hat.
z.B: Alle Dateien in einem Ordner gleichzeitig compilen, direkter Output in neuen Dateien, auf Dateiänderungen “watchen”, uvm.

1.1 Installation von Node.js

Für die Installation wird die Node.js Umgebung und der Node Package Manager benötigt.

Diese installiert man am besten über den Installer: nodejs.org/en/download/
Den einfach ausführen und installieren lassen.

1.2 Installation von Minecraft Script

Öffne nun die Konsole deines PCs (Am besten über Suche unter CMD zu erreichen).

Hier muss nun dieser Command eingegeben werden:

npm install -g mcscript

Bei einer erfolgreichen Antwort hast du alles richtig gemacht und kannst durchstarten.

2) CLI Commands

Das Tool kannst du nun anwenden, indem du die Command Line in deinen Datapacks Ordner startest
(über Shift + Rechtsklick auf Ordner -> Eingabeaufforderung hier öffnen)
Nun kannst du die Kommandos benutzen:

2.1 mcscript new

Dieser Command generiert dir ein vorgefertigtes Datapack mit allen basic Dateien und einem Scripts-Ordner. Als Argument muss die Id des Packs angegeben werden!

2.2 mcscript compile

Dieser Command wandelt alle .mcscript Dateien in .mcfunction Format um. Was in den mcscript Dateien möglich ist, kannst du hier nachlesen.
In der Konsole werden alle generierten Dateien angezeigt oder ein Fehler ausgeworfen, falls etwas nicht korrekt war.

Alternativ kannst mit mcscript compile *filepath* einen speziellen Pfad oder spezielle Datei angeben.

2.3 mcscript watch

Hiermit wird dein Code automatisch compiled, wenn du irgendwelche Änderungen machst (speicherst). So musst du nicht bei jeder Änderung den obigen Command eingeben.

Auch hier kann ein Pfad angegeben werden.

2.4 mcscript add [url or package]

Dieser Conmmand kann ein datapack zu deiner Welt hinzufügen.
Als Argument kann entweder eine Url direkt zur Datei oder der Name einer mcScript Extension genutzt werden.

Eine Liste aller McScript Extensions kann bekommen werden mit mcscript add

2.4 Dev: mcscript modals

!!Dieser Command ist nur für Entwicker gedacht, die ihre Modals in den Compiler einbauen wollen.
Es muss eine Datei angegeben werden und die Modals aus dieser Datei werden dann in eine Konfigurationsdatei geschrieben.

3) File system

3.1 File setup

In einem Minecraft Datapack können alle Datein in ein scripts Ordner gepackt werden, um dann in /functions den Output zu generieren.
Es werden immer Dateien mit gleichem Namen, wie ihr Root generiert.

Ein benutzerdefinierter Name kann mit #file: *name* gesetzt werden.
Bitte ohne .mcfunction!!

Statt des Namen kann auch gleich ein ganzer Pfad, an dem die neue Datei sein soll, angegeben werden:

Es können auch mehrere Dateien spezifiziert werden:

#file: neu
//commands hier
#file: zwei
//Commands für zwei hier

Auch sehr gut mit for-loops kombinierbar:

#file: neu
//commands hier
for(1,5){
	#file: test$(i)
	//Commands für jede Datei hier
}

3.2 Dateien erweitern

Eine bereits bestehende Datei, vorher mit #file:, kann nun auch aus anderen Dateien erweitert werden und neuer Code einfach hinten drangehängt werden:

#extend: ./test
/commands kommen hier.

3.3 Globale Dateien

Variablen, Konstanten und Modals werden für jede Datei seperat gespeichert.
Jetzt kann man eine globale Datei mit der Endung .gl.mcscript erstellen. Der Compiler erkennt diese automatisch und verwendet die deklarierten Objekte auch in anderen Dateien.
So kann man die Modals zum Beispiel in eine eigende Datei schreiben.

Minecraft Script Syntax

Der Code wird in Dateien mit der Endung .mcscript geschrieben. Es wird ein Code-Editor(IDE) empfohlen, um die Dateien zu verwalten und den Syntax farbig zu markieren. Mehr hier

Anders als bei mcfunction wird jeder Command mit einem “/” oder "run: " injektiert.

Kommentare werden mit “//” angekündigt, falls Kommentare auch in der neuen Datei auftauchen sollen mit "#"
Ein Kommentar über mehrere Zeilen muss mit

*/
angegeben werden
/*

Leerzeilen und Zeilensprünge werden nicht beachtet.
Falls eine Leerzeile aus Struktur in der mcfunction gewünscht ist,drücke dies mit einem # ohne Kommentar aus.
Zwei Leerzeilen können mit “##” erreicht werden.

4.1 Command Gruppen / Wrapping

[subcommand]([argument]){ [wrapped actions] }

“as, at, positioned,align,dimension,rotated,anchored” können zusammengefasst werden:

as('@a'){
	/commands 	=> /execute positioned ~ ~ ~ run command
}

In den Klammern muss das jeweilige Argument als String, sprich " " oder ’ ’ stehen!
Auch ist der eigende asat() möglich

asat(@s){
    /commands => execute as @s at @s run commands
}

"Gruppen können auch aufgelistet werden:

as('@p'), at('@s'), positioned('~ ~1 ~'){
	/say command
}
==> /execute as @p at @s positioned ~ ~-1 ~ run say command

// also with if
as('@p'), at('@s'), positioned('~ ~1 ~'), if(entity @s[tag=mytag]){
	/say command
}
==> /execute as @p at @s positioned ~ ~-1 ~ if entity @s[tag=mytag] run say command

4.2 Variablen

Wie jede Programmiersprache hat auch Minecraft Script Variablen. Sie müssen wiefolgt initialisiert werden:
var test
Der Variablen kann ein Wert hinzugewiesen werden:

var test = 5
# oder
var test
test = 6

Dieser Wert kann beliebig oft wieder verändert werden.

var test
test @s = 10

So können Werte auch nur speziellen Minecraft Selektoren zugewiesen werden.
Auch mit Spielernamen oder Placeholdern möglich:

test Spielername = 10

Alle Werte werden in einem scoreboard mit dem Variablennamen gespeichert. Also können die Werte auch ganz standart mäßig verändert und ausgelesen werden:

var test
test @s = 10
/scoreboard players get @s test ==> 10
/scoreboard players set @s test 5
# etc

Variablen können auch mit anderen zusammen gerechnet und zusammengefügt werden:

var test = 10
var neu = 5
# Achtung: Der Einfachkeit halber starte ich immer wieder mit diesen Werten. Das Programm macht es nartürlich anders!

test += 2 ==> 12
test -= 2 ==> 8

Etwas gekürzt:

test++ ==> test += 1
test-- ==> test -= 1

test += neu ==> 15
test -= neu ==> 5
test *= neu ==> 50
test /= neu ==> 2
test %= neu ==> 0

Command Response in Variable speichern:

var res = run: command
==> execute store result score res res run command

Das Ergebnis des command wird in die Variable res geschrieben.
Beispiel mit /data get:
var varResult = run: data get entity @s Pos[0]

4.3 Boolean Variablen (Tags)

bool [name] [selector](optional) = true|false

So können Wahrheitswerte deklariert werden.
bool isCool = true => tag [global] add isCool
Eine Boolean Variable kann später noch verändert werden:
isCool = false => tag [global] remove isCool

Mit If testbar:

if(isCool){
    /commands => execute if entity [global][tag=isCool] run commands
}

4.4 Konstanten

Eine andere Art Variable ist die Konstante, so deklariert:

const [name] = [value]

Diese Art kann nicht verändert werden!
Du kannst sie mit $(var_name) irgendwo in deinem Code benutzen um lange Strings und wiederholende Phrasen zu vermeiden:

const einString = "Hier könnte sehr viel Schrott stehen."
const eineNum = 5

/say $(einString)       ==> /say Hier könnte sehr viel Schrott stehen.
var test = $(eineNum)   ==> var test = 5

Replace Konstanten
Der Wert einer Konstante kann bei der Verwendung noch umgeändert werden. Hierzu ein .repl() an die Verwendung anfügen:

$(const).repl([suchwert],[replacement])

Bei unserem Beispiel wollen wir das viel replacen:

/say $(einString).repl("viel","sehr viel") ==> /say Hier könnte sehr sehr viel Schrott stehen.

Auch kann hier ein RegEx eingefügt werden und auch auf diesen im Replacement zugegriffen werden:
$(const).repl([/regex/],["$&"])

4.5 If/Else Statements

If funktioniert ähnlich wie das Command Wrapping:

if('statement'){
	/commands 	=> /execute if statement run command
}

Mit einigen extra Features:

    if('statement'){
    	/commands 	=> /execute if statement run command
    } else {		   /execute unless statement run command2
    	/commands2
    }

Hier darauf achten das Argument nicht zu verändern!

    if('entity @s[tag=test]'){
    	/tag @s remove test
    	} else {
    	/tag @s remove test
    }

Hier werden beide ausgeführt!! Verbessert:

    if('entity @s[tag=test]'){
    	/tag @s add testIf
    }
    if('entity @s[tag=testIf]'){
    	/tag @s remove test
    	} else {
    	/tag @s remove test
    }
    if('statement'){
    	/commands 				=> /execute if statement run command
    } else if('statement2') {	   /execute unless statement if statement2 run command2
    	/commands2
    }

4.6 Logische Operatoren

In Kombination mit Command Gruppen und If-Else-Statements können zusätzlich logische Operatoren benutzt werden:

    as(@s||@p){
    	/command
    }
    ==> execute as @s run command
        execute at @p run command

    # oder als Liste
    if(@s[tag=entity1],'entity @s[tag=entity2]'){
    # hier gehen beide Varianten ^
    	/command
    }
    ==> execute if entity @s[tag=entity1] run command
        execute if entity @s[tag=entity2] @p run command
    if('entity @s'&&'entity @p'){
    	/command
    }
    ==> execute if entity @s if entity @p run command
var test = 5

# genau gleich
if(test == 5){
    /commands
}

# größer/kleiner gleich
if(test >= 5){
    /commands
}

# größer/kleiner
if(test > 5){
    /commands
}

# auch im Vergleich möglich
if(test > test2){
    /commands
}

# oder mit entity variablen
if(test @s > test2 @a){
    /commands
}

4.7 Switch-Cases

switch([var_name]){
    case <=|<|==|>|>= [other_var]|[number] {
        [actions]
    },
    default(optional) {
        [default actions]
    }
}

Switches erleichtern dem Benutzer die vielen If-Bedingungen. Es kann einfach und übersichtlich auf verschiedene Werte von Variablen getestet werden.
bsp:

var test = 10
switch(test){
    case > 10 {
        /say var ist über 10
    },
    case < 10 {
        /say var ist unter 10
    },
    default {
        /say nichts traf zu.
    }
}

Hier wird also test geprüft auf über 10, wenn das nicht zutrifft auf unter 10 und als standart default ausgegeben.
Auch abkürzbar:

var test = 10
switch(test){
    case > 10 run: say var ist über 10
    , case < 10 run: say var ist unter 10
    , default run: say nichts traf zu.
}

4.8 For-Loops

for([from],[to],[var_name](optional)){
    [actions]
}

Einer der hilfreichsten Features ist der For-Loop. Als Argumente werden ganze Zahlen angenommen.

Von erstes Argument bis zweites Argument wird optional ausgegeben als drittes Argument

for(1,5){
	/commands
	# es wird 5x command ausgegeben
}
for(1,5){
	/say $(i)
	# es wird 5x say mit 1 - 5 ausgegeben
}

Mit $(var_name) kann auf den Loopwert zugegriffen werden.

var_name ist normalerweise als “i” definiert, kann aber im 3.Argument geändert werden:

for(1,5,X){
	/say $(X)
	# es wird 5x say mit 1 - 5 ausgegeben
}

Das ist bei 2 dimensionalen Loops sinnvoll:

for(1,5,i){
	for(1,2,j){
		/say $(i).$(j)
	}
	# es wird 10x say mit 1.1 - 5.2 ausgegeben
}

4.9 Raycasting

raycast([distance](optional), [block to travel through](optional),entity | block [target](optional) ){
    [actions on hitted block or entity]
},{
    [actions for every flight step]
}
default distance = 100 Blocks
default block = air
default target = any block

Raycasting ist eine große Sache in Minecraft 1.13 und bietet viele Möglichkeiten.
Es ist allerdings bisschen schwierig, also warum nicht leichter machen?
Mit Minecraft Script ist das nun sehr sehr einfach:

raycast {
    /setblock ~ ~ ~ stone
}

Das alleine setzt überall, wo man hinschaut einen Steinblock.
Partikel und Blockbegrenzung auch noch sehr einfach:

raycast(10) {
    /setblock ~ ~ ~ stone
}, {
    /particle flame ~ ~ ~
}

Jetzt haben wir schöne Effekte und eine maximale Range von 10 Blöcken.
Das zweite optinale Argument gibt die durchlässigen Blöcke an.

raycast(10,"air") {
    /setblock ~ ~ ~ stone
}

Das Raycasting geht also nur durch Luft.
Auch kann man die durchlässigen Blöcke negieren und mit einem “!” angeben, welche Blöcke nicht durchlässig sind:

raycast(10,!"white_wool") {
    /setblock ~ ~ ~ stone
}

Das Raycasting geht also durch alle Blöcke außer weiße Wolle.

Als drittes optionales Argument kann man ein Ziel angeben:

raycast(10,"air",block "white_wool") {
    /setblock ~ ~ ~ stone
}

Jetzt weiß Mcscript, dass das Ziel ein Block ist und führt den Command nur aus, wenn der Block weiße Wolle ist.

raycast(10,"air",entity @e[type=armor_stand]) {
    /say test
}

Mcscript weiß nun, dass das Ziel eine Entity ist und führt den Command als diese aus, wenn sie getroffen wurde.
Also würde der Armor Stand test sagen.

4.10 while-Loops

Der while-Loop ist so zu definieren:

while([cond]){
    /commands
}

Die gruppierten Commands werden solange ausgeführt, wie die Bedingung[cond] war ist.

Wenn die Bedingung zum Start nicht wahr ist, wird die Gruppierung nicht ausgeführt!

Als Bedingung können hier alle Operatoren und Argumente der If-Bedingungen verwendet werden. z.B.

var test = 0
while(test < 10){
    /commands hier
    test += 1
}
# ==> Die Commands werden innerhalb eines Ticks 10mal ausgeführt.

Bei while-Loops kann auch mit stop und continue gearbeitet werden:

var test = 0
while(test < 10){
    test += 1
    if(test == 5){
        continue
        # Wenn test 5 ist werden die restlichen Commands übersprungen
    }
    /commands hier
    if(test >= 9){
        stop
        # Wenn test 9 oder über 9 ist wird die Schleife abgebrochen
    }
}

4.11 do-while-Loops

do {
    /commands
} while([cond])

Der do-while-Loop funktioniert ähnlich, wie der while-Loop mit dem kleinen Unterschied, dass der Codeblock ausgeführt wird und danach erst die Bedingung geprüft wird.
Der Loop wird also mindestens einmal durchlaufen.

4.12 forEach-Loop

forEach(var [var_name] = [startwert]; [var_name] ==|>|<|<=|>=|!= [other_var]|[number]; [varname]++){
    /commands
}

Der forEach-Loop ist ein Loop, wie man ihn in fast jeder Programmiersprache vorfindet.
Er ähnelt sich zu dem for-Loop von Minecraft Script, funktioniert aber dynamisch(d.h wird nicht beim generieren ausgeführt, sondern von Minecraft)

Bsp:

forEach(var i = 0; i < 10; i++){
    /say hey
}

Der Command wird also 10mal ausgeführt und der aktuelle Wert jeweils in dem scoreboard i gespeichert.
So kann man auch auf den Wert zugreifen. Bsp. Fakultät:

var result = 1
forEach(var i = 2; i <= 10; i++){
    result *= i
}
==> result = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10

4.13 Modals

modal [name]([arguments]){
   [actions]
}

Modals kann man wie functions oder Methoden verstehen, dass heißt man kann sie definieren:

modal newModal(argument){
	/say $(argument)
}

Ein Modal wird immer mit dem Keyword eingeleitet, gefolgt von dem Namen und in Klammern alle benötigten Argumente.

Auf diese Argumente kann dann innerhalb mit $(argument_name) Referenz genommen werden.

modal newModal(argument){
	/say $(argument)
}

newModal('test')

# => say test

Wenn man das Modal so benutzt, dann werden die Werte eingesetzt und alles ausgegeben.

modal createCommand(command,argument1,argument2){
	/$(command) $(argument1) $(argument2)
}

createCommand('say', 'hallo', 'du')

# => say hallo du

Es können so auch mehrere Argumente benutzt werden.

Auch sind optionale und vordefinierte Argumente verfügbar:

modal say(argument = "hallo"){
	/say $(argument)
}

say()
# => say hallo

say('test')
# => say test

Modals überschreiben
Bereits erstellte modals können innerhalb des Prozesses überschrieben werden:

override modal [name]([arguments]){
   [actions]
}

Dabei werden Argumente und Actions komplett getauscht und für den fortlaufenden Prozess verwendet.

Argumente ersetzen
Der Wert eines Arguments kann bei der Verwendung noch umgeändert werden. Hierzu ein .repl() an die Verwendung anfügen:

$(argument).repl([suchwert],[replacement])

Bei unserem Beispiel wollen wir ein eingegebenes test replacen:

/say $(argument).repl("test","no test") ==> /say no test

Auch kann hier ein RegEx eingefügt werden und auch auf diesen im Replacement mit $& zugegriffen werden:
$(argument).repl([/regex/],["$&"])

4.14 System Modals

Es gibt schon einige vordefinierte Modals, die hilfreich sein könnten. Bitte schaue dir dafür die spezifischen Dokumentationen hier an.

Du hast Ideen, welche Modals unbedingt als Standart-Modal aufgegriffen werden müssen? Sende mir einfach die Konfigurationsdatei zur Überprüfung.

IDEs und Syntax Highlighting

Jetzt bleibt nichts mehr übrig als: Happy Developing

Vielen Dank an alle die Minecraft Script benutzen und diese Dokumentation gelesen haben. Bei Vorschlägen, Problemen oder Fehlern bitte mich kontaktieren.