2014-12-30 21:50:46 +03:00
|
|
|
---
|
|
|
|
title: Lua Scripts
|
|
|
|
layout: default
|
2017-08-26 18:40:30 +03:00
|
|
|
root: ../../
|
2018-07-15 17:28:10 +03:00
|
|
|
idx: 1.2
|
|
|
|
description: A basic introduction to Lua, including a guide on global/local scope.
|
2018-07-15 21:13:16 +03:00
|
|
|
redirect_from: /en/chapters/lua.html
|
2014-12-30 21:50:46 +03:00
|
|
|
---
|
|
|
|
|
2015-02-22 13:28:37 +03:00
|
|
|
## Introduction
|
2014-12-30 21:50:46 +03:00
|
|
|
|
|
|
|
In this chapter we will talk about scripting in Lua, the tools required,
|
|
|
|
and go over some techniques which you will probably find useful.
|
|
|
|
|
2014-12-30 22:24:41 +03:00
|
|
|
* Tools
|
2017-08-26 21:01:51 +03:00
|
|
|
* Recommended Editors
|
|
|
|
* Integrated Programming Environments
|
2015-02-22 14:43:58 +03:00
|
|
|
* Coding in Lua
|
2017-08-26 21:01:51 +03:00
|
|
|
* Selection
|
2015-02-22 14:43:58 +03:00
|
|
|
* Programming
|
2014-12-30 22:24:41 +03:00
|
|
|
* Local and Global
|
|
|
|
* Including other Lua Scripts
|
|
|
|
|
2015-02-22 13:28:37 +03:00
|
|
|
## Tools
|
2014-12-30 21:50:46 +03:00
|
|
|
|
|
|
|
A text editor with code highlighting is sufficient for writing scripts in Lua.
|
2015-02-22 13:15:37 +03:00
|
|
|
Code highlighting gives different colors to different words and characters
|
|
|
|
depending on what they mean. This allows you to spot mistakes.
|
2014-12-30 21:50:46 +03:00
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
function ctf.post(team,msg)
|
2017-08-26 21:01:51 +03:00
|
|
|
if not ctf.team(team) then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
if not ctf.team(team).log then
|
|
|
|
ctf.team(team).log = {}
|
|
|
|
end
|
2014-12-30 21:50:46 +03:00
|
|
|
|
2017-08-26 21:01:51 +03:00
|
|
|
table.insert(ctf.team(team).log,1,msg)
|
|
|
|
ctf.save()
|
2014-12-30 21:50:46 +03:00
|
|
|
|
2017-08-26 21:01:51 +03:00
|
|
|
return true
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
2015-11-08 18:57:40 +03:00
|
|
|
For example, keywords in the above snippet are highlighted such as if, then, end, return.
|
2014-12-30 21:50:46 +03:00
|
|
|
table.insert is a function which comes with Lua by default.
|
|
|
|
|
2014-12-31 20:23:15 +03:00
|
|
|
### Recommended Editors
|
|
|
|
|
|
|
|
Other editors are available, of course.
|
|
|
|
|
|
|
|
* Windows: [Notepad++](http://notepad-plus-plus.org/), [Atom](http://atom.io/)
|
|
|
|
* Linux: Kate, Gedit, [Atom](http://atom.io/)
|
|
|
|
* OSX: [Atom](http://atom.io/)
|
|
|
|
|
2014-12-30 21:50:46 +03:00
|
|
|
### Integrated Programming Environments
|
|
|
|
|
|
|
|
IDEs allow you to debug code like a native application.
|
|
|
|
These are harder to set up than just a text editor.
|
|
|
|
|
|
|
|
One such IDE is Eclipse with the Koneki Lua plugin:
|
|
|
|
|
|
|
|
* Install Eclipse + Koneki.
|
|
|
|
* Create a new Lua project from existing source (specify Minetest's base directory).
|
|
|
|
* Follow instructions from Koneki wiki how to do "Attach to remote Application" debugging (just a few steps).
|
|
|
|
* It is suggested to add those lines from wiki at beginning of builtin.lua.
|
|
|
|
* Start the debugger (set "Break on first line" in debugger configuration to see if it is working).
|
|
|
|
* Start Minetest.
|
|
|
|
* Enter the game to startup Lua.
|
|
|
|
|
2015-02-22 14:43:58 +03:00
|
|
|
## Coding in Lua
|
|
|
|
|
|
|
|
<div class="notice">
|
2017-08-26 21:01:51 +03:00
|
|
|
This section is a Work in Progress. May be unclear.
|
2015-02-22 14:43:58 +03:00
|
|
|
</div>
|
|
|
|
|
|
|
|
Programs are a series of commands that run one after another.
|
|
|
|
We call these commands "statements."
|
|
|
|
|
|
|
|
Program flow is important, it allows you to direct or skip over
|
|
|
|
statements. There are three main types of flow:
|
|
|
|
|
|
|
|
* Sequence: Just run one statement after another, no skipping.
|
|
|
|
* Selected: Skip over statements depending on conditions.
|
|
|
|
* Iteration: Repeating, looping. Keep running the same
|
|
|
|
statements until a condition is met.
|
|
|
|
|
|
|
|
So, what do statements in Lua look like?
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
local a = 2 -- Set 'a' to 2
|
|
|
|
local b = 2 -- Set 'b' to 2
|
|
|
|
local result = a + b -- Set 'result' to a + b, which is 4
|
|
|
|
a = a + 10
|
|
|
|
print("Sum is "..result)
|
|
|
|
{% endhighlight %}
|
|
|
|
|
2015-11-08 18:57:40 +03:00
|
|
|
Woah, what happened there? a, b, and result are **variables**. They're like what
|
2015-02-22 14:43:58 +03:00
|
|
|
you get in mathematics, A = w * h. The equals signs are **assignments**, so
|
|
|
|
"result" is set to a + b. Variable names can be longer than one character
|
2015-11-08 18:57:40 +03:00
|
|
|
unlike in mathematics, as seen with the "result" variable. Lua is **case sensitive**.
|
|
|
|
A is a different variable than a.
|
2015-02-22 14:43:58 +03:00
|
|
|
|
|
|
|
The word "local" before they are first used means that they have local scope,
|
|
|
|
I'll discuss that shortly.
|
|
|
|
|
|
|
|
### Variable Types
|
|
|
|
|
|
|
|
| Type | Description | Example |
|
|
|
|
|----------|----------------------------------------------------|-------------------------------------------|
|
|
|
|
| Integer | Whole number | local A = 4 |
|
|
|
|
| Float | Decimal | local B = 3.2, local C = 5 / 2 |
|
|
|
|
| String | A piece of text | local D = "one two three" |
|
|
|
|
| Boolean | True or False | local is_true = false, local E = (1 == 1) |
|
|
|
|
| Table | Lists | Explained below |
|
|
|
|
| Function | Can run. May require inputs and may return a value | local result = func(1, 2, 3) |
|
|
|
|
|
|
|
|
Not an exhaustive list. Doesn't contain every possible type.
|
|
|
|
|
|
|
|
### Arithmetic Operators
|
|
|
|
|
|
|
|
| Symbol | Purpose | Example |
|
|
|
|
|--------|----------------|---------------------------|
|
|
|
|
| A + B | Addition | 2 + 2 = 4 |
|
|
|
|
| A - B | Subtraction | 2 - 10 = -8 |
|
|
|
|
| A * B | Multiplication | 2 * 2 = 4 |
|
|
|
|
| A / B | Division | 100 / 50 = 2 |
|
|
|
|
| A ^ B | Powers | 2 ^ 2 = 2<sup>2</sup> = 4 |
|
|
|
|
| A .. B | Join strings | "foo" .. "bar" = "foobar" |
|
|
|
|
|
|
|
|
A string in programming terms is a piece of text.
|
|
|
|
|
|
|
|
Not an exhaustive list. Doesn't contain every possible operator.
|
|
|
|
|
|
|
|
### Selection
|
|
|
|
|
|
|
|
The most basic selection is the if statement. It looks like this:
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
local random_number = math.random(1, 100) -- Between 1 and 100.
|
|
|
|
|
|
|
|
if random_number > 50 then
|
2017-08-26 21:01:51 +03:00
|
|
|
print("Woohoo!")
|
2015-02-22 14:43:58 +03:00
|
|
|
else
|
2017-08-26 21:01:51 +03:00
|
|
|
print("No!")
|
2015-02-22 14:43:58 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
That example generates a random number between 1 and 100. It then prints
|
2015-04-13 21:58:06 +03:00
|
|
|
"Woohoo!" if that number is bigger than 50, otherwise it prints "No!".
|
2015-02-22 14:43:58 +03:00
|
|
|
What else can you get apart from '>'?
|
|
|
|
|
|
|
|
### Logical Operators
|
|
|
|
|
|
|
|
| Symbol | Purpose | Example |
|
|
|
|
|---------|--------------------------------------|-------------------------------------------------------------|
|
|
|
|
| A == B | Equals | 1 == 1 (true), 1 == 2 (false) |
|
|
|
|
| A ~= B | Doesn't equal | 1 ~= 1 (false), 1 ~= 2 (true) |
|
|
|
|
| A > B | Greater than | 5 > 2 (true), 1 > 2 (false), 1 > 1 (false) |
|
|
|
|
| A < B | Less than | 1 < 3 (true), 3 < 1 (false), 1 < 1 (false) |
|
|
|
|
| A >= B | Greater than or equals | 5 >= 5 (true), 5 >= 3 (true), 5 >= 6 (false) |
|
|
|
|
| A <= B | Less than or equals | 3 <= 6 (true), 3 <= 3 (true) |
|
|
|
|
| A and B | And (both must be correct) | (2 > 1) and (1 == 1) (true), (2 > 3) and (1 == 1) (false) |
|
|
|
|
| A or B | either or. One or both must be true. | (2 > 1) or (1 == 2) (true), (2 > 4) or (1 == 3) (false) |
|
|
|
|
| not A | not true | not (1 == 2) (true), not (1 == 1) (false) |
|
|
|
|
|
|
|
|
That doesn't contain every possible operator, and you can combine operators like this:
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
if not A and B then
|
2017-08-26 21:01:51 +03:00
|
|
|
print("Yay!")
|
2015-02-22 14:43:58 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
Which prints "Yay!" if A is false and B is true.
|
|
|
|
|
|
|
|
Logical and arithmetic operators work exactly the same, they both accept inputs
|
|
|
|
and return a value which can be stored.
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
local A = 5
|
|
|
|
local is_equal = (A == 5)
|
|
|
|
|
|
|
|
if is_equal then
|
2017-08-26 21:01:51 +03:00
|
|
|
print("Is equal!")
|
2015-02-22 14:43:58 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
## Programming
|
|
|
|
|
|
|
|
Programming is the action of talking a problem, such as sorting a list
|
|
|
|
of items, and then turning it into steps that a computer can understand.
|
|
|
|
|
2015-11-08 18:57:40 +03:00
|
|
|
Teaching you the logical process of programming is beyond the scope of this book;
|
|
|
|
however, the following websites are quite useful in developing this:
|
2015-02-22 14:43:58 +03:00
|
|
|
|
|
|
|
### Codecademy
|
|
|
|
[Codecademy](http://www.codecademy.com/) is one of the best resources for learning to 'code',
|
|
|
|
it provides an interactive tutorial experience.
|
|
|
|
|
|
|
|
### Scratch
|
|
|
|
[Scratch](https://scratch.mit.edu) is a good resource when starting from absolute basics,
|
|
|
|
learning the problem solving techniques required to program.\\
|
|
|
|
Scratch is **designed to teach children** how to program, it isn't a serious programming language.
|
|
|
|
|
2015-02-22 13:28:37 +03:00
|
|
|
## Local and Global
|
2014-12-30 21:50:46 +03:00
|
|
|
|
2014-12-30 22:24:41 +03:00
|
|
|
Whether a variable is local or global determines where it can be written to or read to.
|
|
|
|
A local variable is only accessible from where it is defined. Here are some examples:
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
-- Accessible from within this script file
|
|
|
|
local one = 1
|
|
|
|
|
|
|
|
function myfunc()
|
2017-08-26 21:01:51 +03:00
|
|
|
-- Accessible from within this function
|
|
|
|
local two = one + one
|
2014-12-30 22:24:41 +03:00
|
|
|
|
2017-08-26 21:01:51 +03:00
|
|
|
if two == one then
|
|
|
|
-- Accessible from within this if statement
|
|
|
|
local three = one + two
|
|
|
|
end
|
2014-12-30 22:24:41 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
Whereas global variables can be accessed from anywhere in the script file, and from any other mod.
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
my_global_variable = "blah"
|
|
|
|
|
|
|
|
function one()
|
2017-08-26 21:01:51 +03:00
|
|
|
my_global_variable = "three"
|
2014-12-30 22:24:41 +03:00
|
|
|
end
|
|
|
|
|
2015-02-24 12:53:25 +03:00
|
|
|
print(my_global_variable) -- Output: "blah"
|
|
|
|
one()
|
|
|
|
print(my_global_variable) -- Output: "three"
|
2014-12-30 22:24:41 +03:00
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
|
|
|
|
### Locals should be used as much as possible
|
|
|
|
|
|
|
|
Lua is global by default (unlike most other programming languages).
|
|
|
|
Local variables must be identified as such.
|
2014-12-30 21:50:46 +03:00
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
function one()
|
2017-08-26 21:01:51 +03:00
|
|
|
foo = "bar"
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
function two()
|
2017-08-26 21:01:51 +03:00
|
|
|
print(dump(foo)) -- Output: "bar"
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
2015-02-24 12:53:25 +03:00
|
|
|
|
|
|
|
one()
|
|
|
|
two()
|
2014-12-30 21:50:46 +03:00
|
|
|
{% endhighlight %}
|
|
|
|
|
2015-02-24 12:53:25 +03:00
|
|
|
dump() is a function that can turn any variable into a string so the programmer can
|
|
|
|
see what it is. The foo variable will be printed as "bar", including the quotes
|
|
|
|
which show it is a string.
|
|
|
|
|
2014-12-30 22:24:41 +03:00
|
|
|
This is sloppy coding, and Minetest will in fact warn you about this:
|
|
|
|
|
2017-08-26 21:01:51 +03:00
|
|
|
[WARNING] Assigment to undeclared global 'foo' inside function at init.lua:2
|
2014-12-30 22:24:41 +03:00
|
|
|
|
2014-12-30 21:50:46 +03:00
|
|
|
To correct this, use "local":
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
function one()
|
2017-08-26 21:01:51 +03:00
|
|
|
local foo = "bar"
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
function two()
|
2017-08-26 21:01:51 +03:00
|
|
|
print(dump(foo)) -- Output: nil
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
2015-02-24 12:53:25 +03:00
|
|
|
|
|
|
|
one()
|
|
|
|
two()
|
2014-12-30 21:50:46 +03:00
|
|
|
{% endhighlight %}
|
|
|
|
|
2015-11-08 18:57:40 +03:00
|
|
|
Nil means **not initalised**. The variable hasn't been assigned a value yet,
|
|
|
|
doesn't exist, or has been uninitialised. (ie: set to nil)
|
2015-02-24 12:53:25 +03:00
|
|
|
|
2014-12-30 22:24:41 +03:00
|
|
|
The same goes for functions. Functions are variables of a special type.
|
|
|
|
You should make functions as local as much as possible,
|
2014-12-30 21:50:46 +03:00
|
|
|
as other mods could have functions of the same name.
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
local function foo(bar)
|
2017-08-26 21:01:51 +03:00
|
|
|
return bar * 2
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
If you want your functions to be accessible from other scripts or mods, it is recommended that
|
|
|
|
you add them all into a table with the same name as the mod:
|
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
mymod = {}
|
|
|
|
|
|
|
|
function mymod.foo(bar)
|
2017-08-26 21:01:51 +03:00
|
|
|
return "foo" .. bar
|
2014-12-30 21:50:46 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
-- In another mod, or script:
|
|
|
|
mymod.foo("foobar")
|
|
|
|
{% endhighlight %}
|
|
|
|
|
2015-02-22 13:28:37 +03:00
|
|
|
## Including other Lua Scripts
|
2014-12-30 21:50:46 +03:00
|
|
|
|
2015-11-08 18:57:40 +03:00
|
|
|
You can include Lua scripts from your mod or another mod like this:
|
2014-12-30 21:50:46 +03:00
|
|
|
|
|
|
|
{% highlight lua %}
|
|
|
|
dofile(minetest.get_modpath("modname") .. "/script.lua")
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
"local" variables declared outside of any functions in a script file will be local to that script.
|
|
|
|
You won't be able to access them from any other scripts.
|
|
|
|
|
2014-12-31 20:13:28 +03:00
|
|
|
As for how you divide code up into files, it doesn't matter that much.
|
2015-11-08 18:57:40 +03:00
|
|
|
The most important thing is that your code is easy to read and edit.
|
2014-12-31 20:13:28 +03:00
|
|
|
You won't need to use it for smaller projects.
|