全站通知:

插件编写:Lua

阅读

    

2022-04-17更新

    

最新编辑:七年mark

阅读:

  

更新日期:2022-04-17

  

最新编辑:七年mark

来自MinetestWIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
七年mark
pevernow

在这一章节中,我们将会学习用Lua写脚本,并且复习一些你可能会发现的实用技巧。

代码编辑器

只需要一个带语法高亮的编辑器就足以使用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

例如,上面代码片段中的关键字将突出显示,例如if、then、end和return。默认情况下,table.insert是Lua附带的函数。<br/>
这里有一些常见的适合Lua的常见编辑器。其他编辑器可以。<br/>
以下是个人推荐的编辑器:

  • Windows:AtomVS Code,Sublime Text,notepad++,GVIM
  • Linux:Kate,Gedit,AtomVS Code,Sublime Text,GVIM,notepadqq
  • OSX:AtomVS Code
  • Android:Dcoder,Quoda,DroidEdit,QuickEdit

用Lua写代码

程序流

程序是由一行行的命令组成的。我们称这些为“语句”。程序流是这些语句的执行方式。不同类型的流可以让你跳过或跳到命令集。这里有三种类型流:

  • 顺序:只需运行一条接一条的语句,不跳过。
  • 选择:根据条件跳过序列。
  • 迭代(重复):重复,继续运行相同的语句,直到满足条件为止。

让我们来看看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)

这里发生了什么?
a和b,和result是变量。使用local声明局部变量,并且给他们初始变量。局部将在稍后讨论,因为它是一个非常重要概念的一部分,叫做范围。<br/>
“=”意思是赋值,所以,result = a + b 也就意味着“result”这个变量的值为 a + b。与数学不同的是,变量名可以变得更长(至少一个字母),就像“result”这个变量名一样。另外值得注意的是,Lua是区分大小写的;“A”与“a”是不同的变量。

变量类型

变量只能是以下类型之一,并且可以在赋值后更改类型。这是一个很好的实践,确保一个变量永远是nil(零)或者是一个单一的非nil(零)类型。<br/>

Type Description Example
Nil(零) 没有初始化,这是个值是空的 local A, D = nil
Number(数字) 一个整数或小数 local A = 4
String(字符串) 一段文字 local D = "one two three"
Boolean(布尔值) 真或假 local is_true = false, local E = (1 == 1)
Table(列表) 列表 后面会提到的
Function(函数) 可执行,可能需要输入几个值(至少一个)或者输出一个值 local result = func(1, 2, 3)

算术运算符

这不是一个详尽的清单,不包含所有可能的运算符。<br/>

符号 意义 例子
A + B 2 + 2 = 4
A - B 2 - 10 = -8
A * B 2 * 2 = 4
A / B 100 / 50 = 2
A ^ B 平方 2 ^ 2 = 22 = 4
A .. B 拼字符串 "foo" .. "bar" = "foobar"

判断

最基本的判断就是if语句。它看起来像这样:

local random_number = math.random(1, 100) -- Between 1 and 100.
if random_number > 50 then
    print("Woohoo!")
else
    print("No!")
end

这个例子是生成1-100的随机数。如果这个数字大于50,他就会打出“Woohoo!”,否则就会打出“No!”。除了“>”你还能得到什么?

逻辑运算符

它不包含所有可能的运算符,您可以组合如下运算符:

符号 意义 例子
A == B 等于 1 == 1 (true), 1 == 2 (false)
A ~= B 不等于 1 ~= 1 (false), 1 ~= 2 (true)
A > B 大于 5 > 2 (true), 1 > 2 (false), 1 > 1 (false)
A < B 小于 1 < 3 (true), 3 < 1 (false), 1 < 1 (false)
A >= B 大于等于 5 >= 5 (true), 5 >= 3 (true), 5 >= 6 (false)
A <= B 小于等于 3 <= 6 (true), 3 <= 3 (true)
A and B 和(两者都必须要符合) (2 > 1) and (1 == 1) (true), (2 > 3) and (1 == 1) (false)
A or B 二选一,只要符合一个条件即可 (2 > 1) or (1 == 2) (true), (2 > 4) or (1 == 3) (false)
not A 相反 not (1 == 2) (true), not (1 == 1) (false)
if not A and B then
    print("Yay!")
end

当A和B的值为真为时,就会输出“Yay!”<br/>
逻辑运算符和算术运算符的工作原理完全相同;它们都接受输入并返回一个可以存储的值。

local A = 5
local is_equal = (A == 5)
if is_equal then
    print("Is equal!")
end

编程

编程是一种处理问题的动作,如对项目列表进行排序,然后将其转换为计算机可以理解的步骤。<br/>
教你编程的逻辑过程超出了本书的范围;但是,以下网站在开发这个过程中非常有用(当然如果你有一定的Lua编程基础,你可以直接看下一部分的内容。当然如果你有其他编程语言的基础,译者本人建议建议也学一下Lua。):

  • Codecademy是学习“编码”的最佳资源之一,提供了交互式教程体验。
  • Scratch是一个很好的资源,当从绝对的基础开始,学习解决问题所需的编程技巧。

Scratch的目的是教孩子们如何编程,而不是一种严肃的编程语言。

  • 菜鸟教程(译者自己补充上去的):个人极力推荐,提供了大量的在线实例。该网站致力于推广各种编程语言技术,所有资源是完全免费的,并且会根据当前互联网的变化实时更新本站内容。

本地和全局范围

变量是局部变量还是全局变量决定了它可以写入或读取的位置。局部变量只能从定义它的位置访问。举个例子:

-- Accessible from within this script file
local one = 1

function myfunc()
    -- Accessible from within this function
    local two = one + one

    if two == one then
        -- Accessible from within this if statement
        local three = one + two
    end
end

而全局变量可以从脚本文件中的任何位置访问,也可以从任何其他模组访问。

my_global_variable = "blah"

function one()
    my_global_variable = "three"
end

print(my_global_variable) -- Output: "blah"
one()
print(my_global_variable) -- Output: "three"

尽量使用本地变量

Lua在默认情况下是全局的(与大多数其他编程语言不同)。局部变量必须这样标识。

function one()
    foo = "bar"
end

function two()
    print(dump(foo))  -- Output: "bar"
end

one()
two()

dump()是一个函数,它可以将任何变量转换为字符串,以便程序员可以看到它是什么。foo变量将被打印为“bar”,包括显示它是字符串的引号。<br/>
这是草率的编码,事实上,Minetest将对此发出警告:

Assignment to undeclared global 'foo' inside function at init.lua:2

要更正此问题,请使用“local”:

function one()
    local foo = "bar"
end

function two()
    print(dump(foo))  -- Output: nil
end

one()
two()

请记住,nil表示不初始化。变量尚未赋值、不存在或未初始化(即:设置为零)。<br/>
函数也是如此。函数是一种特殊类型的变量,应该设置为局部的,因为其他模组可以有同名的函数

local function foo(bar)
    return bar * 2
end

应该使用API表来允许其他mod调用函数,例如:

mymod = {}

function mymod.foo(bar)
    return "foo" .. bar
end

-- In another mod, or script:
mymod.foo("foobar")

包含其他Lua脚本

如果要在模组中包含其他Lua脚本,推荐使用dofile。

dofile(minetest.get_modpath("modname") .. "/script.lua")

在脚本文件的任何函数之外声明的“local”变量将是该脚本的本地变量。脚本可以返回一个值,该值对于共享私有局部变量非常有用:

-- script.lua
return "Hello world!"

-- init.lua
local ret = dofile(minetest.get_modpath("modname") .. "/script.lua")
print(ret) -- Hello world!

后面的章节将详细讨论如何分割mod的代码。不过,目前最简单的方法是为不同类型的事物(nodes.lua、crafts.lua、craftitems.lua等)创建不同的文件。


回城链接(目录)