CLICK FOR TRANSLATION
This multipart guide was made in collaboration with @severedskullz .
It is to give you a basic overview of LUA and to allow more unique mods to flourish in the community. Fully utilizing starbound's capabilities. If you notice any mistakes, please point them out so they can be corrected.
SERIES LINKS
- PART 1: Terminology and Strings
- PART 2: Tables - Functions - Operators
- PART 3: Practicals
TABLE OF CONTENTS
[ Clickable inpage Links ]
- CHAPTER 1: STARTING OFF
- LUA and Starbound LUA References
- CHAPTER 2: TERMINOLOGY
- Exam
- CHAPTER 3: STRINGS
- String Concatenation
- String Sub
- String Find
- String Gsub
- String Capture
- Exam
.
CHAPTER - 1 STARTING OFFJust like JSON - you are going to need a code based text editor.
My Recommendation are
- Windows - Notepad++
- Mac -Text Wangler
- Linux - VIM
The second most important tool is your interpreter to practice the scripts you learn.
Interpreter [lua 5.1]: http://repl.it/languages/Lua
This interpreter will let you test your code online. Simply press the play button at the top right of the left code input window to run your code.
REFERENCES:
Good places to further your education of LUA and clarify issues not covered here.STARBOUND LUA DOCUMENTATION
- http://www.lua.org/pil/contents.html
- http://www.phailed.me/2011/02/learn-lua-the-hard-way-1/
- http://lua-users.org/wiki/TutorialDirectory
- http://www.tutorialspoint.com/lua/
- http://luatut.com/crash_course.html
- http://www.dev-hq.net/lua/1--introduction-and-setup
- http://wiki.visionaire-tracker.net/wiki/Basic_lua:_Introduction
- http://lua.gts-stolberg.de/en/Programmieren.php
- < Starbound Installation Folder > \ Docs
- STARBOUNDER LUA
.
CHAPTER - 2 TERMINOLOGYIDENTIFIER -
is a fancy word for "name". It can be in reference to a variable, function, table, array. What is important to note is identifiers are case sensitive so bob, Bob, BOb, BOB are all different. It is recommended you avoid identifiers starting with an underscore followed by one or more upper-case letters. As they are reserved for special uses.Speaking of reserved there are a few words which are reserved
Code:
and break do else elseif end false for function if in local nil not or repeat return then true until while
TYPES -
The basic types in Lua: nil, boolean, number, string, function, and table.By using the type function you can find type of data.
By using the interpreter try each line one at a time and see the result.The last example will result in "string" no matter the value of X, because the result of type is always a string.Code:
print(type("Hello world")) print(type(10.4*3)) print(type(print)) print(type(type)) print(type(true)) print(type(nil)) print(type(type(X)))CHUNKS -
Chunks are akin to sentences, a complete statement by it self. Chunks can either be separated by a space, semi colon or line break. Ideally you should use a line break as it makes reading your code easier, as well as making it much less troublesome if an issue arises later.orCode:
a = 10 b = 11 print(a,b)orCode:
a = 11; b = 12; print(a,b)VARIABLE-Code:
a = 11 b = 11 print(a,b)
A variable is something that holds a value. Akin to what you learned in ALgebra. But in this case it holds more than a numerical value or problem. Variables in LUA can hold strings, tables and even functions.Variables do not have to be defined ahead of time. Also variables are divided into 2 major groups. Local and Global.
Now lets look at the scope of variables.Code:
local a = 45 - local variablea = 45 -- global variableA local variable can only be called within a function, and will remove it self once that function finishes. While a global variable will remain until it is manually assigned a nil value. Only use global variables as necessary, an keep it unique enough as not to cause conflict with others for example modinitials_varname. Where mod initials is the initials for your mod and varname is the variable name you wish to assign.Code:
local global = 10 -- LOCAL variable, but has global scope!function randomFunc() global = 20 -- SAME variable as above local global -- DIFFERENT than above. Both inside this function and above endvariables can also inherit values of other variables.
For exampleyou can also join evaluate variables togetherCode:
a = 10 b = 43 a = b print(a)COMMENTS -Code:
a = 10 b = 43 print(a+b) - we will cover operators in a later section.
Comment tags let you write in comments into your code to help others understand. Comments will be ignored by the interpreter. In lua the comment tags are done by using --[[ to start --]] and on a separate line to end. So everything written between these will be ignored.
You can also use -- to comment out a single line instead of a block.Comments help immensely in terms of readability. So other people looking at your code knows the purpose of the functions and variables.
NIL -
Nil is the default value to a space where nothing is mapped.BOOLEAN -
True or False value. empty string and 0 are considered true.STRINGS -
Are a collection of text encompassed in single or double quotes. You should stick to one or the other. Certain special characters cannot be used in LUA which can be used through escape sequences.One important thing to note is "10" does not equal 10. One is a number and the other is a string. You have to use the functionsCode:
\a bell \b back space \f form feed \n newline \r carriage return \t horizontal tab \v vertical tab \\ backslash --> print('a backslash inside quotes: \'\\\'') \" double quote \' single quote \[ left square bracket \] right square bracketCode:
tostring --> tostring(10) --> will turn value inside into a string tonumber --> tonumber("10") --> will turn value to a number
to convert between one and the other.TABLE -
Is an object which holds varying amounts of data.FUNCTIONS -
Are the brains of all programming languages. Essentially it is a chunk of code which contains a condition and an action and a result..
BREAK TIME
Too much at once is not ideal for learning. So it is time to take a break. After the break time to do a small review on what you have learned. Remember do not look up at the answer. Try and recall everything from memory. Mistakes are fine, answers are provided below.TRUE OR FALSE QUESTIONS
COPY FOLLOWING PROBLEMS INTO AN INTERPRETER.
- Question 1. If x = 10 and y = "10" does x = y?
- Question 2. If x = 11 y = 11 does X = y?
- Question 3. boolean value of " " = false
- Question 4. boolean value of nil = true
Question 5.
Modify print function to make the statement true.Question 6.Code:
a = 10 print(a == "10")
Change only the number in the print function to make statement true.Question 7.Code:
a = 25; b = 35; c = 10; a = b print(a-15 == c)
Would this be a true statement yes or no and why?Question 8.Code:
a = 25; b = 35; c = 10; a = b ; b = 25 print(a-15 == c)
Correct the following statement so it results in a true statement, by only modifying the comment tags.Question 9.Code:
--[[ a = 45 b = a b = 16 --]] b = b - 20 -- b = b + 9 print(b == 25)
Explain the mistake.ANSWERSCode:
"My name is Bob" = bprint(b)
Answer 1: False - one is a string one is a number
Answer 2: False - - x is not the same as X
Answer 3: True - empty strings result in true
Answer 4: False - nil value has no value so it is false. Do not confuse with 0
Answer 5: print(tostring(a) == "10") - variable replaced with value in function.
Answer 6: print(a-25 == c) - the value of a gets replaced with variable b.
Answer 7: No - values are passed sequentially, so A inherits the original value of B, so it will remain 35. Even though the value of B is changed later. Hence making the statement false.
Answer 8:
One possible answerAnswer 9: The statement tried to assign a variable to a string. Instead of a string to a variable.Code:
--[[ a = 45 b = a --]] b = 16 --b = b - 20 b = b + 9 print(b == 25).
CHAPTER - 3 STRINGSNow we have a rough idea of the basics. Lets go into a bit more detail about strings.
What we are going to learn now is the mastery of political speech. So what does politics have to do with programming you ask?............[ pause for effect ]..............................
Text manipulation! That is right we are going to learn how to manipulate words as you see fit. Just as the millions of political manipulators before us..
STRING CONCATENATIONWhat concatenation essentially means is to link something. String Concatenation means exactly that, you are essentially linking two strings together. We use the operator .. (double period) to link the strings together.
The reason the two strings are fused as one is, essentially no space character was there in the string. We can add a space through concatenation alsoCode:
a = "hello"b = "bob"print(a .. b) --> hellobobCode:
print(a .. " " .. b) --> Hello Bob.
STRING.SUB()The next thing we are going to look at is string.sub(x, #1,#2)
Where #1 is the starting number, and #2 is the ending number. So let us see an example - To the interpreter Robin! (obviously I am Batman).Now as you ran the code in your interpreter you would have noticed that "Hi" was no longer there. What happened is you told the function to start the string after the 3rd value which is the letter "m". Now plug in the following code and see what this does.Code:
x = "Hi my name is Batman" print(string.sub(x, 3))Obviously you already know what is going to happen next. For sake of disclosure the next snippet of code is not possible in starbound. It is simply there for sake of writing your first interactive program.Code:
x = "Hi my name is Batman" print(string.sub(x, 0, 14))Now if you are using our online interpreter you will notice on the output window [ right window ] it will ask for your name. Input your name on the right window ( not left) and press enter ( not play button ) to get result.Code:
x = "Hi my name is Batman" x = string.sub(x, 0, 14) io.write("Enter your name: ") name = io.read() print(x ..name)Tada you have learned your first lesson in political speech manipulation and wrote your first program to boot! Pat your self on the back slugger, or sluggess ( hmm is slugger asexual? who knows )
.
STRING.FIND()Now that you know how to truncate strings, lets move on. The next important tool in our disposal is string.find(). String find lets you search for a particular word or pattern in a string. Lets look at an example.
The first basic format is string.find(x,y, #)
Where x = the text to search, y = the word to find # = position to start (can be omitted.) A positive number starts the search from the front a negative number starts the count from the back.For example: "My name is Bob"
So lets do an exampleCode:
4 would start with [n]ame the "a" in name. -4 would start with is[ ]bob the blank space before bob.i and j are just 2 non specific variables which store the location data. i stores the location of the first character in the search and j stores the last character of the search. So you get 2 variables which each carry one part of the positional data.Code:
i, j = string.find("hello Lua user", "Lua") print(i, j)So let us throw some numbers into the mix.
i, j = string.find("hello Lua user", "Lua", 8)
In this case you are going to get nil. Because the search starts on the 8th character. The L in lua starts on the 7th. Hence there is nothing after 8th which matches.Similarly
Gives the values 7 and 9. Why? Because it starts counting from the back instead of front. so it starts the count at L 8 spaces from the back.Code:
i, j = string.find("hello Lua user", "Lua", -8)One thing when you use string.find(), it finds the first instance of that word or what ever particular thing you are searching for.
Snippet of code with a practical application.
I wanted to change change a name from one type to another to spawn a vanilla item base don the name of my modded item. So the basic code I used was below. You can run the code on repl.it to see it in action.Code:
test = "reefpodH_sbno"i, j = string.find(test, "H_sbno")g = string.sub(test,0,i-1)print(g).
STRING.GSUB()The next function are going to look at is the string.gsub(). This function allow us to quickly change one character or a group of characters to another.
The format follows
string.gsub(x, y, z, #)
- Where x = the text to look through
- Where y = the text to find
- Where z = the text to replace with
- Where # - is an optional parameter which controls how many substitutions (starting from the first) can be made. If left out it will replace all.
Lets see an exampleand to control how manyCode:
x = string.gsub("I am Bob Bole", "B", "D") print(x)As you have noticed, or remembered capitalization is quite important, B does not equal b.Code:
x = string.gsub("I am Bob Bole", "B", "D", 1) print(x)Character classes are the next best thing since sliced bread. They help refine your search efforts with a bit more prowess by using generic character code to search for a wide swathe of a particular type of information.
. all characters
An upper case version of any of those classes represents the complement of the class. For instance, '%A' represents all non-letter characters:Code:
%a letters%c control characters%d digits%l lower case letters%p punctuation characters%s space characters%u upper case letters%w alphanumeric characters%x hexadecimal digits%z the character with representation 0The character `%´ works as an escape for those magic characters. So, '%.' matches a dot; '%%' matches the character `%´ itself. You can use the escape `%´ not only for the magic characters, but also for all other non-alphanumeric characters. When in doubt, play safe and put an escape.Code:
( ) . % + - * ? [ ^ $You can make patterns more useful by using modifiers for repetitions and optional parts. Patterns in Lua offer four modifiers:
- + 1 or more repetitions
- * 0 or more repetitions
- - also 0 or more repetitions
- ? optional (0 or 1 occurrence)
Using these with string.find() or string.gsub() it will refine your search to a much more higher degree.Lets look at an example.
%a looks for a letter to replace. $a+ looks for 1 or more letters in sequenceCode:
print(string.gsub("one, and two; and 3e", "%a+", "word"))By removing the "+" from our search it would replace each letter with the word, word. By keeping it, it would replace each word as well as each individual letter by it self not associated other group of letters with the word, word.
Now lets add another character class
now the search is going to look for at least a group of letters with at least 2 letters .So as you can see 3e remains untouched as "e" is only a single letter.Code:
print(string.gsub("one, and two; and 3e", "%a+%a+", "word"))A character class is essentially a refined version of the asterisk (*) used as a generic search operator in windows and various other software.
Let us look at another example.in this case "better" was replaced with word.Code:
text = "To make a bit more better example, lets look at a proper piece of text to start mucking around."print(string.gsub(text, "be%a+%a+", "word")).
STRING CAPTUREThe final part for strings we will be focusing on is captures.
Captures unlike the previous points is a lot more problem solving oriented.So let us go back to our old friend string.find(). Now as you remember find helps you "find" words. But it can also retrieve them. The first 2 variables which are given by find are positional variables. After that it produce results. Let us take a look at the following example
In this problem we want to find out how cool bob is.Code:
text = "bob is cool 'to cool for school'"
So we know he is too cool for school.
So we are going to need reference points. We notice the statement is in single quotes. so lets start with thatNow when we place a piece of information within parenthesis inside a find parameter. It returns the first result into the first non positional variable (3rd) in our case "x". If we used the character class %a+ it would have only returned the first word. Since we don't know how many words were in that phrase we instead want to use the single quotes as end points to copy everything in-between.Code:
text = "bob is cool 'to cool for school'" _, _, x= string.find(text, "'(.+)'") print(x)If you want to read up more on strings go here
http://www.lua.org/pil/20.htmlPRACTICAL EXAMPLE FOR STRINGS
So for sake of example where this would be useful.
When making my Purchasable Pets Mod - I needed a way for the pet to recognize its own Pet House.
There were multiple problems involved. The biggest issue was the naming convention used by Chucklefish.
Some pets were called petcat ( uses the word pet ) some pets were called crasberry ( does not use the word pet )
an inconsistent naming convention is always a pain to deal with.
Now my Spawner is called petHouseName, where "Name" is the monster type.
So not only did I need to remove the word pet in some, but also had to capitalize the first letter.My solution
.
BREAK TIMEI am sure at this point you are pretty much exhausted. You probably thinking to your self you are about to become a Shaolin lua master. Unfortunately you haven't even gotten in the car let alone started driving to even crash!
But lets see how well you crash this test!
Question 1:
What is the value of x?Code:
x = y y = z z = 2
*Hint print the value in the interpreter if you need help.Question 2:
Correct the mistake if anyQuestion 3:Code:
text = "itemname: bob; rarity: rare; amount: 10" i, j = string.find(text, "rarity") print(i,J)
Using only control characters replace AAAe with apples. Do not change the replacement word apple to apples.Question 4:Code:
print(string.gsub("one, and AAEes; and three", "%%%%%", "apple"))
Find the rarity of the following item
Since you have not learned functions, you may only use what is taught.Code:
text = "itemname: bob; rarity: rare; amount: 10"
ANSWERSAnswer 1: nil - y has no value when x is assigned the value of y.
Answer 2: print(i,j) j is not the same as J. hence nil value.
Answer 3:%u+ will search for instance of capital letters which is more then 1 and which ends in a lower case letter.Code:
print(string.gsub("one, and AAEes; and three", "%u+%a", "apple"))Answer 4:
In the first operation the positional values were kept so we can have a reference to start. In the 2nd operation we no longer needed the positional values so they were instead stored in a dummy variable. Which is why I narrowed our search to the point after rarity. Next we knew a semicolon was after rarity so that is where we begun our search. The command .- meant the least amount of characters to our main subject which is enclosed parenthesis, and since we were looking for an entire word and not letter we used $a+. This result was sent to variable rarity.Code:
text = "itemname: bob; rarity: rare; amount: 10" i, j = string.find(text, "rarity") _, _, rarity = string.find(text, ":.-(%a+)", j) print(rarity)For bonus points you could have saved a step by just using rarity with character classes directly instead of using positional values to narrow the search. "rarity:.-(%a+)"
Code:
text = "itemname: bob; rarity: rare; amount: 10" _, _, rarity = string.find(text, "rarity:.-(%a+)") print(rarity)
This seems like a good stopping point for the first part. It gives you a general over view of one of the major components of LUA. In the next part we will look at Tables and Functions. Or the Meat and Potatoes of programming.
Now don't forget to give a big hand to @severedskullz - he helped make the guide possible.
Troll-farente, viRUSv2, foxtails and 13 others like this.