minetest_modding_book/_de/basics/lua.md

284 lines
12 KiB
Markdown
Raw Normal View History

---
title: Lua-Skripting
layout: default
root: ../..
idx: 1.2
description: Eine grundlegende Einführung in Lua, einschließlich eines Leitfadens zum globalen/lokalen Geltungsbereich.
redirect_from: /de/chapters/lua.html
---
## Einleitung <!-- omit in toc -->
In diesem Kapitel geht es um die Skripterstellung in Lua, die dazu benötigten Werkzeuge und einige Techniken, die Sie vielleicht nützlich finden.
- [Code-Editoren](#code-editoren)
- [Programmieren in Lua](#programmieren-in-lua)
- [Programmablauf](#programmablauf)
- [Typen von Variablen](#typen-von-variablen)
- [Arithmetische, also Mathematische, Operatoren](#arithmetische-also-mathematische-operatoren)
- [Auswahl](#auswahl)
- [Logische Operatorens](#logische-operatoren)
- [Programmierung](#programmierung)
- [Lokale und globale Reichweite](#lokale-und-globale-reichweite)
- [Es sollte so viel wie möglich auf lokale Variablen zurückgegriffen werden.](#es-sollte-so-viel-wie-möglich-auf-lokale-variablen-zurückgegriffen-werden)
- [Einbindung anderer Lua-Skripte](#einbindung-anderer-lua-skripte)
## Code-Editoren
Für das Schreiben von Skripten in Lua reicht ein Code-Editor mit Code-Hervorhebung aus.
Die Codehervorhebung verwendet unterschiedliche Farben für Wörter und Zeichen je nachdem, wofür sie stehen. Auf diese Weise können Sie leicht Fehler und Ungereimtheiten erkennen.
Zum Beispiel:
```lua
function ctf.post(team,msg)
if not ctf.team(team) then
return false
end
if not ctf.team(team).log then
ctf.team(team).log = {}
end
table.insert(ctf.team(team).log,1,msg)
ctf.save()
return true
end
```
Die Schlüsselwörter in diesem Beispiel sind hervorgehoben, einschließlich `if`, `then`, `end` und `return`. Funktionen, die standardmäßig mit Lua ausgeliefert werden, wie z.B. `table.insert`, sind ebenfalls hervorgehoben.
Zu den häufig verwendeten Editoren, die sich gut für Lua eignen, gehören:
* [VSCode 🇬🇧](https://code.visualstudio.com/) - quelloffen (als Code-OSS oder VSCodium), populär, und hat [Plugins für Minetest Modding 🇬🇧](https://marketplace.visualstudio.com/items?itemName=GreenXenith.minetest-tools).
* [Notepad++ 🇬🇧](http://notepad-plus-plus.org/) - nur für Windows
Andere geeignete Editoren sind ebenfalls verfügbar.
## Programmieren in Lua
### Programmablauf
Programme sind eine Reihe von Befehlen, die nacheinander ausgeführt werden. Wir nennen diese Befehle "Anweisungen". Der Programmablauf gibt an, wie diese Anweisungen ausgeführt werden. Verschiedene Arten des Ablaufs ermöglichen es Ihnen, Befehlsreihen zu überspringen.
Es gibt drei Haupttypen von Abläufen:
* Sequenz: führt eine Anweisung nach der anderen aus, ohne zu überspringen.
* Auswahl: Überspringt Sequenzen in Abhängigkeit von Bedingungen.
* Iteration: Wiederholung der gleichen Anweisungen, bis eine Bedingung erfüllt ist.
Wie sehen also die Anweisungen in Lua aus?
```lua
local a = 2 -- Setzt 'a' auf 2
local b = 2 -- Setzt 'b' auf 2
local result = a + b -- Setzt 'result' (Deutsch: Ergebnis) auf a + b, was 4 ergibt
a = a + 10
print("Die Summe aus a und b ist "..result)
```
In diesem Beispiel sind `a`, `b` und `result` *Variablen*. Lokale Variablen werden
mit dem Schlüsselwort `local` deklariert und erhalten dann einen Anfangswert. `local`
wird später besprochen, denn es ist Teil eines sehr wichtigen Konzepts namens
*scope* (Deutsch: Geltungsbereich).
Das `=`-Zeichen bedeutet *assignment* (Deutsch: Zuweisung), also bedeutet `result = a + b`, dass der Wert von `result` auf den Wert von `a + b` gesetzt wird. Variablennamen können länger als ein Zeichen lang sein, wie bei der Variable `result` zu sehen ist. Es ist auch erwähnenswert, dass, wie wie die meisten Sprachen die Groß- und Kleinschreibung beachtet wird; `A` ist eine andere Variable als `a`.
### Typen von Variablen
Eine Variable hat nur einen der folgenden Typen und kann nach einer Zuweisung den Typ wechseln. Es ist gute Praxis, sicherzustellen, dass eine Variable immer nur nil oder einen einzigen Nicht-Nil-Typ hat.
| Typ | Beschreibung | Beispiel |
|----------|-----------------------------------------------------------------|----------------|
| Nil | Nicht initialisiert. Die Variable ist leer, sie hat keinen Wert | `local A`, `D = nil` |
| Number | Eine ganze oder dezimale Zahl. | `local A = 4` |
| String | Ein Stück Text. | `local D = "one two three"` |
| Boolean | True oder False. (Wahr oder Falsch) | `local is_true = false`, `local E = (1 == 1)` |
| Table | Listen. | Unten erklärt. |
| Function | Kann ausgeführt werden. Kann Eingaben erfordern und einen Wert zurückgeben. | `local result = func(1, 2, 3)` |
### Arithmetische, also Mathematische, Operatoren
Zu den Operatoren in Lua gehören:
| Symbol | Zweck | Beispiel |
|--------|-------------------------------------------|---------------------------|
| A + B | Addition | 2 + 2 = 4 |
| A - B | Subtraktion | 2 - 10 = -8 |
| A * B | Multiplikation | 2 * 2 = 4 |
| A / B | Division | 100 / 50 = 2 |
| A ^ B | Potenzieren | 2 ^ 2 = 2<sup>2</sup> = 4 |
| A .. B | Konkatenation (Zeichenketten verbinden) | "foo" .. "bar" = "foobar" |
Bitte beachten Sie, dass diese Liste nicht vollständig ist; sie enthält nicht alle möglichen Operatoren.
### Auswahl
Die einfachste Methode der Auswahl ist die if-Anweisung. Zum Beispiel:
```lua
local random_number = math.random(1, 100) -- Zwischen 1 und 100.
if random_number > 50 then
print("Woohoo!")
else
print("Oh nein!")
end
```
Dies erzeugt eine Zufallszahl zwischen 1 und 100. Es gibt dann "Woohoo!" aus, wenn diese Zahl größer als 50 ist, andernfalls wird "Oh nein!" ausgegeben.
### Logische Operatoren
Zu den logischen Operatoren in Lua gehören:
| Symbol | Zweck | Beispiel |
|---------|-----------------------------------------------------|-------------------------------------------------------------|
| A == B | Gleich | 1 == 1 (true), 1 == 2 (false) |
| A ~= B | nicht gleich | 1 ~= 1 (false), 1 ~= 2 (true) |
| A > B | Größer als | 5 > 2 (true), 1 > 2 (false), 1 > 1 (false) |
| A < B | Kleiner als | 1 < 3 (true), 3 < 1 (false), 1 < 1 (false) |
| A >= B | Größer als oder gleich | 5 >= 5 (true), 5 >= 3 (true), 5 >= 6 (false) |
| A <= B | Kleiner als oder gleich | 3 <= 6 (true), 3 <= 3 (true) |
| A and B | Und (beides muss `true`, also wahr sein) | (2 > 1) and (1 == 1) (true), (2 > 3) and (1 == 1) (false) |
| A or B | Entweder oder. Eines oder mehrere müssen wahr sein. | (2 > 1) or (1 == 2) (true), (2 > 4) or (1 == 3) (false) |
| not A | Nicht `true`, also nicht wahr | not (1 == 2) (true), not (1 == 1) (false) |
Bitte beachten Sie, dass dies nicht alle möglichen Operatoren enthält.
Es ist auch möglich, Operatoren zu kombinieren. Zum Beispiel:
```lua
if not A and B then
print("Juhu!")
end
```
Dies gibt "Juhu!" aus, wenn A `False`, also falsch, und B `True`, also wahr, ist.
Logische und arithmetische Operatoren funktionieren auf die gleiche Weise; beide akzeptieren Eingaben und geben einen Wert zurück, der gespeichert werden kann. Zum Beispiel:
```lua
local A = 5
local ist_gleich = (A == 5)
if ist_gleich then
print("Ist gleich!")
end
```
## Programmierung
Beim Programmieren geht es darum, ein Problem, z. B. das Sortieren einer Liste
und in Schritte umzuwandeln, die ein Computer verstehen kann.
Ihnen den logischen Prozess des Programmierens beizubringen, würde den Rahmen dieses Buches sprengen. Die folgenden Websites sind jedoch sehr nützlich, um dies zu entwickeln:
* [Codecademy 🇬🇧](http://www.codecademy.com/) ist eines der besten Quellen, um zu
Lernen, wie man Code schreibt. Sie bietet ein interaktives Lernprogramm an.
* [Scratch](https://scratch.mit.edu) ist eine gute Quelle, um mit den
absoluten Grundlagen zu beginnen und die zum Programmieren erforderlichen Problemlösungstechniken zu erlernen.\\
Scratch *wurde konzipiert, um Kindern das Programmieren beizubringen* und ist keine ernsthafte, sondern eine Block basierte Programmiersprache.
## Lokale und globale Reichweite
Ob eine Variable lokal oder global ist, bestimmt, wohin sie geschrieben oder gelesen werden kann. Auf eine lokale Variable kann nur von dort aus zugegriffen werden, wo sie definiert ist. Hier sind einige Beispiele:
```lua
-- Von dieser Skriptdatei aus zugänglich
local one = 1
function myfunc()
-- Von dieser Funktion aus zugänglich
local two = one + one
if two == one then
-- Zugänglich aus dieser if-Anweisung
local three = one + two
end
end
```
Im Gegensatz dazu, kann auf globale Variablen von jeder Stelle in der Skriptdatei aus zugegriffen werden und von jeder anderen Mod aus.
```lua
function one()
foo = "bar"
end
function two()
print(dump(foo)) -- Gibt "bar" aus
end
one()
two()
```
### Es sollte so viel wie möglich auf lokale Variablen zurückgegriffen werden.
Wann immer möglich, sollten lokale Variablen verwendet werden. Mods sollten nur eine globale variable mit dem gleichen Namen wie die Mod haben. Das Erstellen weiterer globaler Variablen ist unsaubere
Kodierung, und Minetest wird davor warnen:
Assignment to undeclared global 'foo' inside function at init.lua:2
Auf Deutsch: Zuweisung an eine nicht deklarierte globale Variable 'foo' innerhalb der Funktion in init.lua:2
Um dies zu korrigieren, verwenden Sie "local":
```lua
function one()
local foo = "bar"
end
function two()
print(dump(foo)) -- Gibt "nil" aus
end
one()
two()
```
Denken Sie daran, dass nil **nicht initialisiert** bedeutet. Die Variable wurde noch nicht mit einem Wert zugewiesen, existiert nicht oder wurde nicht initialisiert (d.h. auf null gesetzt).
Funktionen sind Variablen eines besonderen Typs sollten aber auch lokal gemacht werden, weil andere Mods Funktionen mit demselben Namen haben könnten.
```lua
local function foo(bar)
return bar * 2
end
```
Damit Mods Ihre Funktionen aufrufen können, sollten Sie eine Tabelle mit dem gleichen Namen wie die Mod erstellen und darin ihre Funktion einfügen. Diese Tabelle wird oft als "API table" (Deutsch: API-Tabelle) oder Namespace bezeichnet.
```lua
mymod = {}
function mymod.foo(bar)
return "foo" .. bar
end
-- In einer anderen Mod oder einem anderen Skript:
mymod.foo("foobar")
```
## Einbindung anderer Lua-Skripte
Der empfohlene Weg, um andere Lua-Skripte in eine Mod einzubinden, ist die Verwendung von *dofile*.
```lua
dofile(minetest.get_modpath("modname") .. "/script.lua")
```
Ein Skript kann einen Wert zurückgeben, der für die gemeinsame Nutzung privater locals nützlich ist:
```lua
-- script.lua
return "Hallo Welt!"
-- init.lua
local ret = dofile(minetest.get_modpath("modname") .. "/script.lua")
print(ret) -- Hallo Welt!
```
[In späteren Kapiteln](../quality/clean_arch.html) wird erklärt, wie man den Code einer Mod am besten aufteilt.