@ -320,7 +320,7 @@ ul.auto-toc {
< div class = "contents topic" id = "contents" >
< p class = "topic-title first" > Contents< / p >
< ul class = "simple" >
< li > < a class = "reference internal" href = "#df- structure-wrapper" id = "id1" > DF structure wrapper< / a > < ul >
< li > < a class = "reference internal" href = "#df- data- structure-wrapper" id = "id1" > DF data structure wrapper< / a > < ul >
< li > < a class = "reference internal" href = "#typed-object-references" id = "id2" > Typed object references< / a > < ul >
< li > < a class = "reference internal" href = "#primitive-references" id = "id3" > Primitive references< / a > < / li >
< li > < a class = "reference internal" href = "#struct-references" id = "id4" > Struct references< / a > < / li >
@ -333,36 +333,63 @@ ul.auto-toc {
< li > < a class = "reference internal" href = "#recursive-table-assignment" id = "id9" > Recursive table assignment< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#dfhack-utilities" id = "id10" > DFHack utilities< / a > < ul >
< li > < a class = "reference internal" href = "#persistent-configuration-storage" id = "id11" > Persistent configuration storage< / a > < / li >
< li > < a class = "reference internal" href = "#material-info-lookup" id = "id12" > Material info lookup< / a > < / li >
< li > < a class = "reference internal" href = "#c-function-wrappers" id = "id13" > C++ function wrappers< / a > < ul >
< li > < a class = "reference internal" href = "#gui-module" id = "id14" > Gui module< / a > < / li >
< li > < a class = "reference internal" href = "#job-module" id = "id15" > Job module< / a > < / li >
< li > < a class = "reference internal" href = "#units-module" id = "id16" > Units module< / a > < / li >
< li > < a class = "reference internal" href = "#items-module" id = "id17" > Items module< / a > < / li >
< li > < a class = "reference internal" href = "#maps-module" id = "id18" > Maps module< / a > < / li >
< li > < a class = "reference internal" href = "#burrows-module" id = "id19" > Burrows module< / a > < / li >
< li > < a class = "reference internal" href = "#buildings-module" id = "id20" > Buildings module< / a > < / li >
< li > < a class = "reference internal" href = "#constructions-module" id = "id21" > Constructions module< / a > < / li >
< li > < a class = "reference internal" href = "#internal-api" id = "id22" > Internal API< / a > < / li >
< li > < a class = "reference internal" href = "#dfhack-api" id = "id10" > DFHack API< / a > < ul >
< li > < a class = "reference internal" href = "#native-utilities" id = "id11" > Native utilities< / a > < ul >
< li > < a class = "reference internal" href = "#input-output" id = "id12" > Input & Output< / a > < / li >
< li > < a class = "reference internal" href = "#exception-handling" id = "id13" > Exception handling< / a > < / li >
< li > < a class = "reference internal" href = "#locking-and-finalization" id = "id14" > Locking and finalization< / a > < / li >
< li > < a class = "reference internal" href = "#persistent-configuration-storage" id = "id15" > Persistent configuration storage< / a > < / li >
< li > < a class = "reference internal" href = "#material-info-lookup" id = "id16" > Material info lookup< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#core-interpreter-context" id = "id23" > Core interpreter context< / a > < ul >
< li > < a class = "reference internal" href = "#event-type" id = "id24" > Event type< / a > < / li >
< li > < a class = "reference internal" href = "#c-function-wrappers" id = "id17" > C++ function wrappers< / a > < ul >
< li > < a class = "reference internal" href = "#gui-module" id = "id18" > Gui module< / a > < / li >
< li > < a class = "reference internal" href = "#job-module" id = "id19" > Job module< / a > < / li >
< li > < a class = "reference internal" href = "#units-module" id = "id20" > Units module< / a > < / li >
< li > < a class = "reference internal" href = "#items-module" id = "id21" > Items module< / a > < / li >
< li > < a class = "reference internal" href = "#maps-module" id = "id22" > Maps module< / a > < / li >
< li > < a class = "reference internal" href = "#burrows-module" id = "id23" > Burrows module< / a > < / li >
< li > < a class = "reference internal" href = "#buildings-module" id = "id24" > Buildings module< / a > < / li >
< li > < a class = "reference internal" href = "#constructions-module" id = "id25" > Constructions module< / a > < / li >
< li > < a class = "reference internal" href = "#internal-api" id = "id26" > Internal API< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#core-interpreter-context" id = "id27" > Core interpreter context< / a > < ul >
< li > < a class = "reference internal" href = "#event-type" id = "id28" > Event type< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#plugins" id = "id25" > Plugins< / a > < ul >
< li > < a class = "reference internal" href = "#burrows" id = "id26" > burrows< / a > < / li >
< li > < a class = "reference internal" href = "#sort" id = "id27" > sort< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#lua-modules" id = "id29" > Lua Modules< / a > < ul >
< li > < a class = "reference internal" href = "#global-environment" id = "id30" > Global environment< / a > < / li >
< li > < a class = "reference internal" href = "#utils" id = "id31" > utils< / a > < / li >
< li > < a class = "reference internal" href = "#dumper" id = "id32" > dumper< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#plugins" id = "id33" > Plugins< / a > < ul >
< li > < a class = "reference internal" href = "#burrows" id = "id34" > burrows< / a > < / li >
< li > < a class = "reference internal" href = "#sort" id = "id35" > sort< / a > < / li >
< / ul >
< / li >
< li > < a class = "reference internal" href = "#scripts" id = "id36" > Scripts< / a > < / li >
< / ul >
< / div >
< div class = "section" id = "df-structure-wrapper" >
< h1 > < a class = "toc-backref" href = "#id1" > DF structure wrapper< / a > < / h1 >
< p > The current version of DFHack has extensive support for
the Lua scripting language, providing access to:< / p >
< ol class = "arabic simple" >
< li > Raw data structures used by the game.< / li >
< li > Many C++ functions for high-level access to these
structures, and interaction with dfhack itself.< / li >
< li > Some functions exported by C++ plugins.< / li >
< / ol >
< p > Lua code can be used both for writing scripts, which
are treated by DFHack command line prompt almost as
native C++ commands, and invoked by plugins written in c++.< / p >
< p > This document describes native API available to Lua in detail.
It does not describe all of the utility functions
implemented by Lua files located in hack/lua/...< / p >
< div class = "section" id = "df-data-structure-wrapper" >
< h1 > < a class = "toc-backref" href = "#id1" > DF data structure wrapper< / a > < / h1 >
< p > DF structures described by the xml files in library/xml are exported
to lua code as a tree of objects and functions under the < tt class = "docutils literal" > df< / tt > global,
which broadly maps to the < tt class = "docutils literal" > df< / tt > namespace in C++.< / p >
@ -717,10 +744,13 @@ should be prepared to catch the error and do the necessary
cleanup.< / p >
< / div >
< / div >
< div class = "section" id = "dfhack- utilities ">
< h1 > < a class = "toc-backref" href = "#id10" > DFHack utilities < / a > < / h1 >
< div class = "section" id = "dfhack- api ">
< h1 > < a class = "toc-backref" href = "#id10" > DFHack API < / a > < / h1 >
< p > DFHack utility functions are placed in the < tt class = "docutils literal" > dfhack< / tt > global tree.< / p >
< p > Currently it defines the following features:< / p >
< div class = "section" id = "native-utilities" >
< h2 > < a class = "toc-backref" href = "#id11" > Native utilities< / a > < / h2 >
< div class = "section" id = "input-output" >
< h3 > < a class = "toc-backref" href = "#id12" > Input & Output< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.print(args...)< / span > < / tt > < / p >
< p > Output tab-separated args as standard lua print would do,
@ -734,7 +764,8 @@ works with DFHack output infrastructure.</p>
< p > Same as println; intended for errors. Uses red color and logs to stderr.log.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.color([color])< / span > < / tt > < / p >
< p > Sets the current output color. If color is < em > nil< / em > or < em > -1< / em > , resets to default.< / p >
< p > Sets the current output color. If color is < em > nil< / em > or < em > -1< / em > , resets to default.
Returns the previous color value.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.is_interactive()< / tt > < / p >
< p > Checks if the thread can access the interactive console and returns < em > true< / em > or < em > false< / em > .< / p >
@ -752,12 +783,24 @@ this, forcing the function to block on input with lock held.</p>
string, global environment and command-line history file.< / p >
< p > If the interactive console is not accessible, returns < em > nil, error< / em > .< / p >
< / li >
< / ul >
< / div >
< div class = "section" id = "exception-handling" >
< h3 > < a class = "toc-backref" href = "#id13" > Exception handling< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.error(msg[,level[,verbose]])< / span > < / tt > < / p >
< p > Throws a dfhack exception object with location and stack trace.
The verbose parameter controls whether the trace is printed by default.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > qerror(msg[,level])< / span > < / tt > < / p >
< p > Calls < tt class = "docutils literal" > dfhack.error()< / tt > with < tt class = "docutils literal" > verbose< / tt > being < em > false< / em > . Intended to
be used for user-caused errors in scripts, where stack traces are not
desirable.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.pcall(f[,args...])< / span > < / tt > < / p >
< p > Invokes f via xpcall, using an error function that attaches
a stack trace to the error. The same function is used by SafeCall
in C++, and dfhack.safecall.< / p >
< p > The returned error is a table with separate < tt class = "docutils literal" > message< / tt > and
< tt class = "docutils literal" > stacktrace< / tt > string fields; it implements < tt class = "docutils literal" > __tostring< / tt > .< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > safecall(f[,args...])< / span > < / tt > , < tt class = "docutils literal" > < span class = "pre" > dfhack.safecall(f[,args...])< / span > < / tt > < / p >
< p > Just like pcall, but also prints the error using printerr before
@ -766,12 +809,41 @@ returning. Intended as a convenience function.</p>
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.saferesume(coroutine[,args...])< / span > < / tt > < / p >
< p > Compares to coroutine.resume like dfhack.safecall vs pcall.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.run_script(name[,args...])< / span > < / tt > < / p >
< p > Run a lua script in hack/scripts/, as if it was started from dfhack command-line.
The < tt class = "docutils literal" > name< / tt > argument should be the name stem, as would be used on the command line.
Note that the script is re-read from the file every time it is called, and errors
are propagated to the caller.< / p >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.exception< / tt > < / p >
< p > Metatable of error objects used by dfhack. The objects have the
following properties:< / p >
< dl class = "docutils" >
< dt > < tt class = "docutils literal" > err.where< / tt > < / dt >
< dd > < p class = "first last" > The location prefix string, or < em > nil< / em > .< / p >
< / dd >
< dt > < tt class = "docutils literal" > err.message< / tt > < / dt >
< dd > < p class = "first last" > The base message string.< / p >
< / dd >
< dt > < tt class = "docutils literal" > err.stacktrace< / tt > < / dt >
< dd > < p class = "first last" > The stack trace string, or < em > nil< / em > .< / p >
< / dd >
< dt > < tt class = "docutils literal" > err.cause< / tt > < / dt >
< dd > < p class = "first last" > A different exception object, or < em > nil< / em > .< / p >
< / dd >
< dt > < tt class = "docutils literal" > err.thread< / tt > < / dt >
< dd > < p class = "first last" > The coroutine that has thrown the exception.< / p >
< / dd >
< dt > < tt class = "docutils literal" > err.verbose< / tt > < / dt >
< dd > < p class = "first last" > Boolean, or < em > nil< / em > ; specifies if where and stacktrace should be printed.< / p >
< / dd >
< dt > < tt class = "docutils literal" > tostring(err)< / tt > , or < tt class = "docutils literal" > < span class = "pre" > err:tostring([verbose])< / span > < / tt > < / dt >
< dd > < p class = "first last" > Converts the exception to string.< / p >
< / dd >
< / dl >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.exception.verbose< / tt > < / p >
< p > The default value of the < tt class = "docutils literal" > verbose< / tt > argument of < tt class = "docutils literal" > err:tostring()< / tt > .< / p >
< / li >
< / ul >
< / div >
< div class = "section" id = "locking-and-finalization" >
< h3 > < a class = "toc-backref" href = "#id14" > Locking and finalization< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.with_suspend(f[,args...])< / span > < / tt > < / p >
< p > Calls < tt class = "docutils literal" > f< / tt > with arguments after grabbing the DF core suspend lock.
Suspending is necessary for accessing a consistent state of DF memory.< / p >
@ -801,8 +873,9 @@ Implemented using <tt class="docutils literal"><span class="pre">call_with_final
< p > Calls < tt class = "docutils literal" > < span class = "pre" > fn(obj,args...)< / span > < / tt > , then finalizes with < tt class = "docutils literal" > obj:delete()< / tt > .< / p >
< / li >
< / ul >
< / div >
< div class = "section" id = "persistent-configuration-storage" >
< h 2 > < a class = "toc-backref" href = "#id1 1 "> Persistent configuration storage< / a > < / h 2 >
< h 3 > < a class = "toc-backref" href = "#id1 5 "> Persistent configuration storage< / a > < / h 3 >
< p > This api is intended for storing configuration options in the world itself.
It probably should be restricted to data that is world-dependent.< / p >
< p > Entries are identified by a string < tt class = "docutils literal" > key< / tt > , but it is also possible to manage
@ -837,7 +910,7 @@ functions can just copy values in memory without doing any actual I/O.
However, currently every entry has a 180+-byte dead-weight overhead.< / p >
< / div >
< div class = "section" id = "material-info-lookup" >
< h 2 > < a class = "toc-backref" href = "#id1 2 "> Material info lookup< / a > < / h 2 >
< h 3 > < a class = "toc-backref" href = "#id1 6 "> Material info lookup< / a > < / h 3 >
< p > A material info record has fields:< / p >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > type< / tt > , < tt class = "docutils literal" > index< / tt > , < tt class = "docutils literal" > material< / tt > < / p >
@ -880,8 +953,9 @@ Accept dfhack_material_category auto-assign table.</p>
< / li >
< / ul >
< / div >
< / div >
< div class = "section" id = "c-function-wrappers" >
< h2 > < a class = "toc-backref" href = "#id1 3 "> C++ function wrappers< / a > < / h2 >
< h2 > < a class = "toc-backref" href = "#id1 7 "> C++ function wrappers< / a > < / h2 >
< p > Thin wrappers around C++ functions, similar to the ones for virtual methods.
One notable difference is that these explicit wrappers allow argument count
adjustment according to the usual lua rules, so trailing false/nil arguments
@ -910,7 +984,7 @@ can be omitted.</p>
< / li >
< / ul >
< div class = "section" id = "gui-module" >
< h3 > < a class = "toc-backref" href = "#id1 4 "> Gui module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id1 8 "> Gui module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.gui.getCurViewscreen()< / tt > < / p >
< p > Returns the viewscreen that is current in the core.< / p >
@ -946,7 +1020,7 @@ The is_bright boolean actually seems to invert the brightness.</p>
< / ul >
< / div >
< div class = "section" id = "job-module" >
< h3 > < a class = "toc-backref" href = "#id1 5 "> Job module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id1 9 "> Job module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.job.cloneJobStruct(job)< / tt > < / p >
< p > Creates a deep copy of the given job.< / p >
@ -983,7 +1057,7 @@ a lua list containing them.</p>
< / ul >
< / div >
< div class = "section" id = "units-module" >
< h3 > < a class = "toc-backref" href = "#id 16 "> Units module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id 20 "> Units module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.units.getPosition(unit)< / tt > < / p >
< p > Returns true < em > x,y,z< / em > of the unit, or < em > nil< / em > if invalid; may be not equal to unit.pos if caged.< / p >
@ -1037,7 +1111,7 @@ or raws. The <tt class="docutils literal">ignore_noble</tt> boolean disables the
< / ul >
< / div >
< div class = "section" id = "items-module" >
< h3 > < a class = "toc-backref" href = "#id 17 "> Items module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id 2 1"> Items module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.items.getPosition(item)< / tt > < / p >
< p > Returns true < em > x,y,z< / em > of the item, or < em > nil< / em > if invalid; may be not equal to item.pos if in inventory.< / p >
@ -1080,7 +1154,7 @@ Returns <em>false</em> in case of error.</p>
< / ul >
< / div >
< div class = "section" id = "maps-module" >
< h3 > < a class = "toc-backref" href = "#id 18 "> Maps module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id 22 "> Maps module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.maps.getSize()< / tt > < / p >
< p > Returns map size in blocks: < em > x, y, z< / em > < / p >
@ -1121,7 +1195,7 @@ burrows, or the presence of invaders.</p>
< / ul >
< / div >
< div class = "section" id = "burrows-module" >
< h3 > < a class = "toc-backref" href = "#id 19 "> Burrows module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id 23 "> Burrows module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.burrows.findByName(name)< / tt > < / p >
< p > Returns the burrow pointer or < em > nil< / em > .< / p >
@ -1156,7 +1230,7 @@ burrows, or the presence of invaders.</p>
< / ul >
< / div >
< div class = "section" id = "buildings-module" >
< h3 > < a class = "toc-backref" href = "#id2 0 "> Buildings module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id2 4 "> Buildings module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.buildings.getSize(building)< / tt > < / p >
< p > Returns < em > width, height, centerx, centery< / em > .< / p >
@ -1296,7 +1370,7 @@ can be determined this way, <tt class="docutils literal">constructBuilding</tt>
< / ul >
< / div >
< div class = "section" id = "constructions-module" >
< h3 > < a class = "toc-backref" href = "#id2 1 "> Constructions module< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id2 5 "> Constructions module< / a > < / h3 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.constructions.designateNew(pos,type,item_type,mat_index)< / tt > < / p >
< p > Designates a new construction at given position. If there already is
@ -1312,7 +1386,7 @@ Returns <em>true, was_only_planned</em> if removed; or <em>false</em> if none fo
< / ul >
< / div >
< div class = "section" id = "internal-api" >
< h3 > < a class = "toc-backref" href = "#id2 2 "> Internal API< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id2 6 "> Internal API< / a > < / h3 >
< p > These functions are intended for the use by dfhack developers,
and are only documented here for completeness:< / p >
< ul >
@ -1326,17 +1400,36 @@ global environment, persistent between calls to the script.</p>
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.setAddress(name, value)< / tt > < / p >
< p > Sets the global address < tt class = "docutils literal" > name< / tt > . Returns the value of < tt class = "docutils literal" > getAddress< / tt > before the change.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.getBase()< / tt > < / p >
< p > Returns the base address of the process.< / p >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.getVTable(name)< / tt > < / p >
< p > Returns the pre-extracted vtable address < tt class = "docutils literal" > name< / tt > , or < em > nil< / em > .< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.getRebaseDelta()< / tt > < / p >
< p > Returns the ASLR rebase offset of the DF executable.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.getMemRanges()< / tt > < / p >
< p > Returns a sequence of tables describing virtual memory ranges of the process.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.memmove(dest,src,count)< / tt > < / p >
< p > Wraps the standard memmove function. Accepts both numbers and refs as pointers.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.memcmp(ptr1,ptr2,count)< / tt > < / p >
< p > Wraps the standard memcmp function.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.memscan(haystack,count,step,needle,nsize)< / tt > < / p >
< p > Searches for < tt class = "docutils literal" > needle< / tt > of < tt class = "docutils literal" > nsize< / tt > bytes in < tt class = "docutils literal" > haystack< / tt > ,
using < tt class = "docutils literal" > count< / tt > steps of < tt class = "docutils literal" > step< / tt > bytes.
Returns: < em > step_idx, sum_idx, found_ptr< / em > , or < em > nil< / em > if not found.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])< / tt > < / p >
< p > Searches for differences between buffers at ptr1 and ptr2, as integers of size eltsize.
The oldval, newval or delta arguments may be used to specify additional constraints.
Returns: < em > found_index< / em > , or < em > nil< / em > if end reached.< / p >
< / li >
< / ul >
< / div >
< / div >
< div class = "section" id = "core-interpreter-context" >
< h2 > < a class = "toc-backref" href = "#id23" > Core interpreter context< / a > < / h2 >
< h2 > < a class = "toc-backref" href = "#id2 7 "> Core interpreter context< / a > < / h2 >
< p > While plugins can create any number of interpreter instances,
there is one special context managed by dfhack core. It is the
only context that can receive events from DF and plugins.< / p >
@ -1367,7 +1460,7 @@ Using <tt class="docutils literal">timeout_active(id,nil)</tt> cancels the timer
< / li >
< / ul >
< div class = "section" id = "event-type" >
< h3 > < a class = "toc-backref" href = "#id2 4 "> Event type< / a > < / h3 >
< h3 > < a class = "toc-backref" href = "#id2 8 "> Event type< / a > < / h3 >
< p > An event is just a lua table with a predefined metatable that
contains a __call metamethod. When it is invoked, it loops
through the table with next and calls all contained values.
@ -1392,15 +1485,201 @@ order using <tt class="docutils literal">dfhack.safecall</tt>.</p>
< / div >
< / div >
< / div >
< div class = "section" id = "lua-modules" >
< h1 > < a class = "toc-backref" href = "#id29" > Lua Modules< / a > < / h1 >
< p > DFHack sets up the lua interpreter so that the built-in < tt class = "docutils literal" > require< / tt >
function can be used to load shared lua code from hack/lua/.
The < tt class = "docutils literal" > dfhack< / tt > namespace reference itself may be obtained via
< tt class = "docutils literal" > < span class = "pre" > require('dfhack')< / span > < / tt > , although it is initially created as a
global by C++ bootstrap code.< / p >
< p > The following module management functions are provided:< / p >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > mkmodule(name)< / tt > < / p >
< p > Creates an environment table for the module. Intended to be used as:< / p >
< pre class = "literal-block" >
local _ENV = mkmodule('foo')
...
return _ENV
< / pre >
< p > If called the second time, returns the same table; thus providing reload support.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > reload(name)< / tt > < / p >
< p > Reloads a previously < tt class = "docutils literal" > require< / tt > -d module < em > " name" < / em > from the file.
Intended as a help for module development.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.BASE_G< / tt > < / p >
< p > This variable contains the root global environment table, which is
used as a base for all module and script environments. Its contents
should be kept limited to the standard Lua library and API described
in this document.< / p >
< / li >
< / ul >
< div class = "section" id = "global-environment" >
< h2 > < a class = "toc-backref" href = "#id30" > Global environment< / a > < / h2 >
< p > A number of variables and functions are provided in the base global
environment by the mandatory init file dfhack.lua:< / p >
< ul >
< li > < p class = "first" > Color constants< / p >
< p > These are applicable both for < tt class = "docutils literal" > dfhack.color()< / tt > and color fields
in DF functions or structures:< / p >
< p > COLOR_RESET, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_GREY, COLOR_DARKGREY,
COLOR_LIGHTBLUE, COLOR_LIGHTGREEN, COLOR_LIGHTCYAN, COLOR_LIGHTRED,
COLOR_LIGHTMAGENTA, COLOR_YELLOW, COLOR_WHITE< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > dfhack.onStateChange< / tt > event codes< / p >
< p > Available only in the core context, as is the event itself:< / p >
< p > SC_WORLD_LOADED, SC_WORLD_UNLOADED, SC_MAP_LOADED,
SC_MAP_UNLOADED, SC_VIEWSCREEN_CHANGED, SC_CORE_INITIALIZED< / p >
< / li >
< li > < p class = "first" > Functions already described above< / p >
< p > safecall, qerror, mkmodule, reload< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > printall(obj)< / tt > < / p >
< p > If the argument is a lua table or DF object reference, prints all fields.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > copyall(obj)< / tt > < / p >
< p > Returns a shallow copy of the table or reference as a lua table.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > pos2xyz(obj)< / tt > < / p >
< p > The object must have fields x, y and z. Returns them as 3 values.
If obj is < em > nil< / em > , or x is -30000 (the usual marker for undefined
coordinates), returns < em > nil< / em > .< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > xyz2pos(x,y,z)< / tt > < / p >
< p > Returns a table with x, y and z as fields.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > safe_index(obj,index...)< / span > < / tt > < / p >
< p > Walks a sequence of dereferences, which may be represented by numbers or strings.
Returns < em > nil< / em > if any of obj or indices is < em > nil< / em > , or a numeric index is out of array bounds.< / p >
< / li >
< / ul >
< / div >
< div class = "section" id = "utils" >
< h2 > < a class = "toc-backref" href = "#id31" > utils< / a > < / h2 >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > utils.compare(a,b)< / tt > < / p >
< p > Comparator function; returns < em > -1< / em > if a< b, < em > 1< / em > if a> b, < em > 0< / em > otherwise.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.compare_name(a,b)< / tt > < / p >
< p > Comparator for names; compares empty string last.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.is_container(obj)< / tt > < / p >
< p > Checks if obj is a container ref.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.make_index_sequence(start,end)< / tt > < / p >
< p > Returns a lua sequence of numbers in start..end.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.make_sort_order(data, ordering)< / tt > < / p >
< p > Computes an ordering of objects in data, as a table of integer
indices into the data sequence. Uses < tt class = "docutils literal" > data.n< / tt > as input length
if present.< / p >
< p > The ordering argument is a sequence of ordering specs, represented
as lua tables with following possible fields:< / p >
< dl class = "docutils" >
< dt > ord.key = < em > function(value)< / em > < / dt >
< dd > < p class = "first last" > Computes comparison key from a data value. Not called on nil.
If omitted, the comparison key is the value itself.< / p >
< / dd >
< dt > ord.key_table = < em > function(data)< / em > < / dt >
< dd > < p class = "first last" > Computes a key table from the data table in one go.< / p >
< / dd >
< dt > ord.compare = < em > function(a,b)< / em > < / dt >
< dd > < p class = "first last" > Comparison function. Defaults to < tt class = "docutils literal" > utils.compare< / tt > above.
Called on non-nil keys; nil sorts last.< / p >
< / dd >
< dt > ord.nil_first = < em > true/false< / em > < / dt >
< dd > < p class = "first last" > If true, nil keys are sorted first instead of last.< / p >
< / dd >
< dt > ord.reverse = < em > true/false< / em > < / dt >
< dd > < p class = "first last" > If true, sort non-nil keys in descending order.< / p >
< / dd >
< / dl >
< p > This function is used by the sort plugin.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.assign(tgt, src)< / tt > < / p >
< p > Does a recursive assignment of src into tgt.
Uses < tt class = "docutils literal" > df.assign< / tt > if tgt is a native object ref; otherwise
recurses into lua tables.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.clone(obj, deep)< / tt > < / p >
< p > Performs a shallow, or semi-deep copy of the object as a lua table tree.
The deep mode recurses into lua tables and subobjects, except pointers
to other heap objects.
Null pointers are represented as df.NULL. Zero-based native containers
are converted to 1-based lua sequences.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.clone_with_default(obj, default, force)< / tt > < / p >
< p > Copies the object, using the < tt class = "docutils literal" > default< / tt > lua table tree
as a guide to which values should be skipped as uninteresting.
The < tt class = "docutils literal" > force< / tt > argument makes it always return a non-< em > nil< / em > value.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.sort_vector(vector,field,cmpfun)< / tt > < / p >
< p > Sorts a native vector or lua sequence using the comparator function.
If < tt class = "docutils literal" > field< / tt > is not < em > nil< / em > , applies the comparator to the field instead
of the whole object.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.binsearch(vector,key,field,cmpfun,min,max)< / tt > < / p >
< p > Does a binary search in a native vector or lua sequence for
< tt class = "docutils literal" > key< / tt > , using < tt class = "docutils literal" > cmpfun< / tt > and < tt class = "docutils literal" > field< / tt > like sort_vector.
If < tt class = "docutils literal" > min< / tt > and < tt class = "docutils literal" > max< / tt > are specified, they are used as the
search subrange bounds.< / p >
< p > If found, returns < em > item, true, idx< / em > . Otherwise returns
< em > nil, false, insert_idx< / em > , where < em > insert_idx< / em > is the correct
insertion point.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.insert_sorted(vector,item,field,cmpfun)< / tt > < / p >
< p > Does a binary search, and inserts item if not found.
Returns < em > did_insert, vector[idx], idx< / em > .< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.insert_or_update(vector,item,field,cmpfun)< / tt > < / p >
< p > Like < tt class = "docutils literal" > insert_sorted< / tt > , but also assigns the item into
the vector cell if insertion didn't happen.< / p >
< p > As an example, you can use this to set skill values:< / p >
< pre class = "literal-block" >
utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id')
< / pre >
< p > (For an explanation of < tt class = "docutils literal" > new=true< / tt > , see table assignment in the wrapper section)< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.prompt_yes_no(prompt, default)< / tt > < / p >
< p > Presents a yes/no prompt to the user. If < tt class = "docutils literal" > default< / tt > is not < em > nil< / em > ,
allows just pressing Enter to submit the default choice.
If the user enters < tt class = "docutils literal" > 'abort'< / tt > , throws an error.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.prompt_input(prompt, checkfun, quit_str)< / tt > < / p >
< p > Presents a prompt to input data, until a valid string is entered.
Once < tt class = "docutils literal" > checkfun(input)< / tt > returns < em > true, ...< / em > , passes the values
through. If the user enters the quit_str (defaults to < tt class = "docutils literal" > < span class = "pre" > '~~~'< / span > < / tt > ),
throws an error.< / p >
< / li >
< li > < p class = "first" > < tt class = "docutils literal" > utils.check_number(text)< / tt > < / p >
< p > A < tt class = "docutils literal" > prompt_input< / tt > < tt class = "docutils literal" > checkfun< / tt > that verifies a number input.< / p >
< / li >
< / ul >
< / div >
< div class = "section" id = "dumper" >
< h2 > < a class = "toc-backref" href = "#id32" > dumper< / a > < / h2 >
< p > A third-party lua table dumper module from
< a class = "reference external" href = "http://lua-users.org/wiki/DataDumper" > http://lua-users.org/wiki/DataDumper< / a > . Defines one
function:< / p >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > dumper.DataDumper(value, varname, fastmode, ident, indent_step)< / tt > < / p >
< p > Returns < tt class = "docutils literal" > value< / tt > converted to a string. The < tt class = "docutils literal" > indent_step< / tt >
argument specifies the indentation step size in spaces. For
the other arguments see the original documentation link above.< / p >
< / li >
< / ul >
< / div >
< / div >
< div class = "section" id = "plugins" >
< h1 > < a class = "toc-backref" href = "#id25" > Plugins< / a > < / h1 >
< h1 > < a class = "toc-backref" href = "#id 33 "> Plugins< / a > < / h1 >
< p > DFHack plugins may export native functions and events
to lua contexts. They are automatically imported by
< tt class = "docutils literal" > < span class = "pre" > mkmodule('plugins.< name> ')< / span > < / tt > ; this means that a lua
module file is still necessary for < tt class = "docutils literal" > require< / tt > to read.< / p >
< p > The following plugins have lua support.< / p >
< div class = "section" id = "burrows" >
< h2 > < a class = "toc-backref" href = "#id26" > burrows< / a > < / h2 >
< h2 > < a class = "toc-backref" href = "#id 34 "> burrows< / a > < / h2 >
< p > Implements extended burrow manipulations.< / p >
< p > Events:< / p >
< ul >
@ -1438,11 +1717,41 @@ set is the same as used by the command line.</p>
< p > The lua module file also re-exports functions from < tt class = "docutils literal" > dfhack.burrows< / tt > .< / p >
< / div >
< div class = "section" id = "sort" >
< h2 > < a class = "toc-backref" href = "#id 27 "> sort< / a > < / h2 >
< h2 > < a class = "toc-backref" href = "#id 35 "> sort< / a > < / h2 >
< p > Does not export any native functions as of now. Instead, it
calls lua code to perform the actual ordering of list items.< / p >
< / div >
< / div >
< div class = "section" id = "scripts" >
< h1 > < a class = "toc-backref" href = "#id36" > Scripts< / a > < / h1 >
< p > Any files with the .lua extension placed into hack/scripts/*
are automatically used by the DFHack core as commands. The
matching command name consists of the name of the file sans
the extension.< / p >
< p > < strong > NOTE:< / strong > Scripts placed in subdirectories still can be accessed, but
do not clutter the < tt class = "docutils literal" > ls< / tt > command list; thus it is preferred
for obscure developer-oriented scripts and scripts used by tools.
When calling such scripts, always use '/' as the separator for
directories, e.g. < tt class = "docutils literal" > < span class = "pre" > devel/lua-example< / span > < / tt > .< / p >
< p > Scripts are re-read from disk every time they are used
(this may be changed later to check the file change time); however
the global variable values persist in memory between calls.
Every script gets its own separate environment for global
variables.< / p >
< p > Arguments are passed in to the scripts via the < strong > ...< / strong > built-in
quasi-variable; when the script is called by the DFHack core,
they are all guaranteed to be non-nil strings.< / p >
< p > DFHack core invokes the scripts in the < em > core context< / em > (see above);
however it is possible to call them from any lua code (including
from other scripts) in any context, via the same function the core uses:< / p >
< ul >
< li > < p class = "first" > < tt class = "docutils literal" > < span class = "pre" > dfhack.run_script(name[,args...])< / span > < / tt > < / p >
< p > Run a lua script in hack/scripts/, as if it was started from dfhack command-line.
The < tt class = "docutils literal" > name< / tt > argument should be the name stem, as would be used on the command line.< / p >
< / li >
< / ul >
< p > Note that this function lets errors propagate to the caller.< / p >
< / div >
< / div >
< / body >
< / html >