Lua in mEldritch
mEldritch embeds lua 5.3 for limited scripting capabilities. You can read the lua manual at https://www.lua.org/manual/5.3/. This file documents the mEldritch specifics.
Lua Blocks
lua blocks are enclosed in curly braces { }
and are available in
configuration files. They may appear both at the top level (empty context) or
within contexts. If a block appears at the global level, any non-local
variables or functions defined in that block will be available from lua at
the global level. It a block appears within a context, any non-local variables
or functions defined in that block will be available from lua in a table that
has the same name as the context, and will also be evaluated with this table
as their environment.
A block can appear where a name is expected, which is then evaluated within the context it appears in, when it is loaded from a config file, but does not return any values.
A block can also appear where a value is expected (i.e. on the right hand side of an assignment), which is evaluated at load time and, for the purposes of the config file, replaced by it’s return value. In this case, you actually need to return a value from the block.
Configuration values for loadable assets may have a string starting with ‘&’ and followed by lua code instead of a filename. In this case, the lua code is evaluated and expected to return a stream, from which the asset is then read.
- In the case of images, the string containing the lua code must terminate in
--.ext
(usually--.png
) so that the texture loader can recognize the image file format. For example:Image = "&DynamicallyGenerateMyImage() --.png"
- In the case of rooms, the string containing the lua code must contain a
string of the form
/
, and the dot before eldritchroom must be the last dot in the string so that the room loader may recognize theme and exits. Note that you may omit everything except for theme and exits, and the final eldritchroom is also optional, but good style as it clarifies your intentions. For example:[- ]- [- ].eldritchroom NumRoomDefs = & @ RoomDef @@& = "&DynamicallyGenerateMyRoom() --/mytheme-nwu.eldritchroom" @@& = "&AlsoDynamicallyGenerateThisRoom('/mytheme-ud.eldritchroom')"
- Note: rooms are loaded every time they are encountered during the generation
of a world, not only once.
- in the case of text files, no further requirements are placed
- no other dynamic content is currently supported.
Using require()
You can use require()
to load custom lua libraries. The standard search path
for lua libraries is "
,
meaning that require("lib")
attempts to load lib.lua
from the game data
directory (where the Mods directory resides, this is the game directory on
Windows and Linux and ~/Library/Application Support/Eldritch
on Mac), and
when that fails, from the Lua directory within the game data directory.
When loading a mod, the path is extended by "
.
This means that when within a mod, require("lib")
will first attempt to load
lib.lua from the mod directory. Regardless of where the lua code comes from,
the current directory does not change.
When using the mEldritchLua tool, the path is
"?.lua;Lua/?.lua;
,
i.e. the current directory followed by the directory the mEldritchLua
interpreter binary is in.
global variables
ARG
- contains the commmand line args passed to the script. Only available in
mEldritchLua, not in mEldritch. Currently no options (arguments starting
with
-
) are allowed.
variables per context
CONTEXT
- the name of the current context, i.e. the context in which the current lua code is loaded.
global functions
log(fmt, ...)
- logs a message. Arguments are as for string.format. The output is written to meldritch.log (and, if you have a debug build, also to stdout)
printf(fmt, ...)
- basically does print(string.format(fmt, …)). Only available in mEldritchLua, not in mEldritch. Use log() in mEldritch.
Libraries
pkg
This library provides the facility to add and inspect eldritch package files (*.cpk)
ok = pkg.add(pkg)
- adds a package file to the load path used by config.load(), texture.load(), room.load() and stream.open(). This is mainly intended for the mEldritchLua tool, as mEldritch will load all packages that are listed in it’s config files. Returns true if the package was added successfully, false if not.
table = pkg.list(pkg)
- returns a table that contains a list of all files within the package file.
The file must have been added using pkg.add(). Returns
nil
if the package was not found or had no contents. ok = pkg.fileexists(file, pkgonly = false)
- returns true if the file exists, false if not. If pkgonly is omitted or false, the file is searched for within packages and on the filesystem, otherwise it is searched for only in packages.
config
This library provides access to eldritch configuration. A handler function can be defined that is called when a configuration variable is not found at runtime.
int = config.hash(string)
- creates a hash of the string and returns it
ok = config.load(filename)
- loads a config file. This is mainly intended for the mEldritchLua tool, as mEldritch will load all config files that are listed in it’s config files. Returns true if the config file was loaded, false otherwise.
config.loadstring(string)
- loads configuration from a string. Note that this does not load the configuration into the currently active context!
config.save(filename)
- saves the current configuration to a file
val = config.getvar(name, context = "")
- gets a variable from the configuration. Returns
nil
if . config.setvar(name, context, value)
- sets a variable to a value
config.registerhash(string)
- registers a string for reverse hashing. Only available in mEldritchLua, not in mEldritch.
string = config.reversehash(hash)
- tries to reverse a has code to the original string. This only works for
strings that have been hashed before, either by using
config.registerhash()
,config.load()
of an uncompiled config file,config.loadstring()
orconfig.setvar()
. Only available in mEldritchLua, not in mEldritch.
handlers
value = GETVAR(namehash, contexthash)
- is a user defined function that gets called with the hash of the name and
the context as arguments when a config variable can’t be found in the
regular config options. This function may be present globally (in the
empty context) and per context. If a variable is not found in the context,
then first the
GETVAR
function in the context is tried. If that does not exist or returnsnil
, then the global GETVAR function is called, if it exists. If it does not exist or returnsnil
, the variable is considered unset.
stream
This library provides input/output streams. The input streams are intended to load resources from eldritch, and the output streams (in-memory only) are provided for dynamic resource loading through lua functions.
stream = stream.create()
- returns a memory stream. Write to this stream and then return it from
functions to be called from the configuration with a ‘=’ prefix. May be
written to by textures or rooms
saveto()
method. istream = stream.open(filename)
- opens an input stream to a file within a package or on the filesystem.
A stream returned from open can not be written to. Returns
nil
if the stream could not be opened. See alsopkg.add()
. stream:write(string)
- writes string to stream. The write method is not available on streams that
were opened with
stream.open()
stream:read(len = auto)
- reads data from the stream. If the len argument is omitted, we read as much
data as is present. Otherwise len bytes are read. If you attempt to read
more bytes from a stream than are present, read returns
nil
. If stream is at eof, read also returnsnil
. size = stream:size()
- returns the size of the stream
pos = stream:getpos()
- returns the current position within the stream. Only one position os maintained for both read and write.
ok = stream:setpos(pos = 0)
- sets the current position within the stream. If the pos argument is omitted, the position is reset to the beginning of the stream.
eof = stream:ateof()
- returns true if the stream is at EOF, false if not.
filesystem
This library provides a few extra functions to interact with the filesystem.
table = fs.list(path)
- returns a table with all objects in a directory. Returns
nil
if the directory was not found or could not be read or had no contents. ok = fs.isfile(path)
- returns true if the path exists and is a file, false otherwise
ok = fs.isdir(path)
- returns true if the path exists and is a directory, false otherwise
path = fs.getexecdir()
- returns the path to the current executable
name = fs.getexecname()
- returns the name of the current executable
path = fs.getmoddir()
- returns the path of the current mod, of the current working directory if not called from within a mod. Note that in the mEldritchLua tool there is no explicit support for mods so this will always return the current working directory.
path = fs.getcurrentdir()
- returns the current working directory
fs.setcurrentdir(path)
- changes the current working directory
fs.filename(path)
- returns the filename portion of a path
fs.dirname(path)
- returns the directory portion of a path
fs.extension(path)
- returns the extension of a path
fs.basename(path)
- returns the basename (filename without extension) of a path
path = fs.normalize(path)
- returns a normalized version of the path
texture
This library provides access to textures, including the ability to create or modify them.
txt = texture.load(filename)
- load a texture from a file on the filesytem or in a package. Can load bmp,
tga, png. Returns
nil
if the texture could not be loaded. See alsopkg.add()
. txt = texture.create(width, height)
- create a new empty texture size width x height
txt:copyrect(x, y, width, height, to, to_x, to_y)
- copy a rectangle of pixels from texture txt top left x, y size width x height to texture to position to_x, to_y
txt:save(filename)
- save a texture to a filename. Only png format supported.
txt:saveto(stream)
- save a texture to s stream. This is used for dynamic resources through lua functions.
r, g, b, a = txt:getpixel(x, y)
- reads rgba values from a pixel of the texture. The return values are
nil
if x, y is out of range for the texture. txt:setpixel(x, y, r, g, b, a)
- sets a pixel’s rgba values in the texture to r, g, b, a
txt.sizex, txt.sizey
- dimension of the texture
room
This library provides access to rooms, including the ability to create or modify them. Voxel coordinates are in the range 0 <= x < room.sizex, 0 <= y < room.sizey, 0 <= z < room.sizez. X coordinates are along the West-East axis with 0 being west, y coordinates are along the North-South axis where 0 is south, and z coordinates are along the Up-Down axis where 0 is Down.
room = room.create()
- creates a new, empty room with standard dimensions (12x12x8)
room = room.load(filename)
- loads a room from a file on the filesystem or in a package. Returns nil
if the room could not be loaded. See also
pkg.add()
. room:setvoxel(x, y, z, v)
- sets the voxel at position x, y, z to value v. v must be in the range 0–255, where 0 is empty and 255 is invalid.
v = room:getvoxel(x, y, z)
- returns the voxel at position x, y, z.
room:setspawner(x, y, z, name, orientation = North)
- sets a spawner at position x, y, z with name and orientation. Name must be a predefined spawner name and must be defined at game run time, orientation is one of the 4 orientations n, w, s, e or 0, 1, 2, 3 respectively. All other values for orientation default to North (i.e. standard)
name, orientation, x, y, z = room:getspawner(x, y, z)
orname, orientation, x, y, z = room:getspawner(i)
- gets name and orientation for either the spawner at position x, y, z or
the i’th spawner, if it exists. returns
nil
if no spawner exists at the given position or index, or the name of the spawner and orientation (see above), and it’s coordinates. If you use the indexed form, i starts at 0 and continues until room:getspawner(i) returnsnil
. room:setworlddef(name)
- sets the world definition for a room. Note that this is only relevant for the room editor, it is not used anywhere else (except maybe in a script?)
hash = room:getworlddef()
- returns the world definition stored in a room. For stock rooms, this will be 0, otherwise it will return a hash of the world definition name.
room:save(filename)
- saves the room to a file
room:saveto(stream)
- saves the room to a stream. This is used for dynamic resources through lua functions.
room.sizex, room.sizey, room.sizez
- the dimensions of the room, should always be 12, 12, 8 respectively.
Examples
For examples check out the contents of Extras/Examples/Mods/LuaTest
and
Extras/Examples/Lua
TODO
- from lua:
- - bind worldgen? (for simulation runs)