From bb39b2e45bdbe8fda2f99607e9ca56319a602843 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Sun, 30 Sep 2012 06:55:52 +0200 Subject: Lua API, not LUA Api. --- CMakeLists.txt | 2 +- LUA Api.html | 2104 -------------------------------------------------------- LUA Api.rst | 2020 ----------------------------------------------------- Lua API.html | 2104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Lua API.rst | 2020 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fixTexts.sh | 2 +- 6 files changed, 4126 insertions(+), 4126 deletions(-) delete mode 100644 LUA Api.html delete mode 100644 LUA Api.rst create mode 100644 Lua API.html create mode 100644 Lua API.rst diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ced670..14436dcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,7 +171,7 @@ find_package(Docutils) IF(BUILD_LIBRARY) add_subdirectory (library) ## install the default documentation files - install(FILES LICENSE "LUA Api.html" Readme.html Compile.html Contributors.html DESTINATION ${DFHACK_USERDOC_DESTINATION}) + install(FILES LICENSE "Lua API.html" Readme.html Compile.html Contributors.html DESTINATION ${DFHACK_USERDOC_DESTINATION}) endif() #build the plugins diff --git a/LUA Api.html b/LUA Api.html deleted file mode 100644 index 047ef978..00000000 --- a/LUA Api.html +++ /dev/null @@ -1,2104 +0,0 @@ - - - - - - -DFHack Lua API - - - -
-

DFHack Lua API

- -
-

Contents

- -
-

The current version of DFHack has extensive support for -the Lua scripting language, providing access to:

-
    -
  1. Raw data structures used by the game.
  2. -
  3. Many C++ functions for high-level access to these -structures, and interaction with dfhack itself.
  4. -
  5. Some functions exported by C++ plugins.
  6. -
-

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++.

-

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/...

-
-

DF data structure wrapper

-

DF structures described by the xml files in library/xml are exported -to lua code as a tree of objects and functions under the df global, -which broadly maps to the df namespace in C++.

-

WARNING: The wrapper provides almost raw access to the memory -of the game, so mistakes in manipulating objects are as likely to -crash the game as equivalent plain C++ code would be. E.g. NULL -pointer access is safely detected, but dangling pointers aren't.

-

Objects managed by the wrapper can be broadly classified into the following groups:

-
    -
  1. Typed object pointers (references).

    -

    References represent objects in DF memory with a known type.

    -

    In addition to fields and methods defined by the wrapped type, -every reference has some built-in properties and methods.

    -
  2. -
  3. Untyped pointers

    -

    Represented as lightuserdata.

    -

    In assignment to a pointer NULL can be represented either as -nil, or a NULL lightuserdata; reading a NULL pointer field -returns nil.

    -
  4. -
  5. Named types

    -

    Objects in the df tree that represent identity of struct, class, -enum and bitfield types. They host nested named types, static -methods, builtin properties & methods, and, for enums and bitfields, -the bi-directional mapping between key names and values.

    -
  6. -
  7. The global object

    -

    df.global corresponds to the df::global namespace, and -behaves as a mix between a named type and a reference, containing -both nested types and fields corresponding to global symbols.

    -
  8. -
-

In addition to the global object and top-level types the df -global also contains a few global builtin utility functions.

-
-

Typed object references

-

The underlying primitive lua object is userdata with a metatable. -Every structured field access produces a new userdata instance.

-

All typed objects have the following built-in features:

-
    -
  • ref1 == ref2, tostring(ref)

    -

    References implement equality by type & pointer value, and string conversion.

    -
  • -
  • pairs(ref)

    -

    Returns an iterator for the sequence of actual C++ field names -and values. Fields are enumerated in memory order. Methods and -lua wrapper properties are not included in the iteration.

    -

    WARNING: a few of the data structures (like ui_look_list) -contain unions with pointers to different types with vtables. -Using pairs on such structs is an almost sure way to crash with -an access violation.

    -
  • -
  • ref._kind

    -

    Returns one of: primitive, struct, container, -or bitfield, as appropriate for the referenced object.

    -
  • -
  • ref._type

    -

    Returns the named type object or a string that represents -the referenced object type.

    -
  • -
  • ref:sizeof()

    -

    Returns size, address

    -
  • -
  • ref:new()

    -

    Allocates a new instance of the same type, and copies data -from the current object.

    -
  • -
  • ref:delete()

    -

    Destroys the object with the C++ delete operator. -If destructor is not available, returns false.

    -

    WARNING: the lua reference object remains as a dangling -pointer, like a raw C++ pointer would.

    -
  • -
  • ref:assign(object)

    -

    Assigns data from object to ref. Object must either be another -ref of a compatible type, or a lua table; in the latter case -special recursive assignment rules are applied.

    -
  • -
  • ref:_displace(index[,step])

    -

    Returns a new reference with the pointer adjusted by index*step. -Step defaults to the natural object size.

    -
  • -
-
-

Primitive references

-

References of the _kind 'primitive' are used for objects -that don't fit any of the other reference types. Such -references can only appear as a value of a pointer field, -or as a result of calling the _field() method.

-

They behave as structs with one field value of the right type.

-

To make working with numeric buffers easier, they also allow -numeric indices. Note that other than excluding negative values -no bound checking is performed, since buffer length is not available. -Index 0 is equivalent to the value field.

-
-
-

Struct references

-

Struct references are used for class and struct objects.

-

They implement the following features:

-
    -
  • ref.field, ref.field = value

    -

    Valid fields of the structure may be accessed by subscript.

    -

    Primitive typed fields, i.e. numbers & strings, are converted -to/from matching lua values. The value of a pointer is a reference -to the target, or nil/NULL. Complex types are represented by -a reference to the field within the structure; unless recursive -lua table assignment is used, such fields can only be read.

    -

    NOTE: In case of inheritance, superclass fields have precedence -over the subclass, but fields shadowed in this way can still -be accessed as ref['subclasstype.field']. -This shadowing order is necessary because vtable-based classes -are automatically exposed in their exact type, and the reverse -rule would make access to superclass fields unreliable.

    -
  • -
  • ref._field(field)

    -

    Returns a reference to a valid field. That is, unlike regular -subscript, it returns a reference to the field within the structure -even for primitive typed fields and pointers.

    -
  • -
  • ref:vmethod(args...)

    -

    Named virtual methods are also exposed, subject to the same -shadowing rules.

    -
  • -
  • pairs(ref)

    -

    Enumerates all real fields (but not methods) in memory -(= declaration) order.

    -
  • -
-
-
-

Container references

-

Containers represent vectors and arrays, possibly resizable.

-

A container field can associate an enum to the container -reference, which allows accessing elements using string keys -instead of numerical indices.

-

Implemented features:

-
    -
  • ref._enum

    -

    If the container has an associated enum, returns the matching -named type object.

    -
  • -
  • #ref

    -

    Returns the length of the container.

    -
  • -
  • ref[index]

    -

    Accesses the container element, using either a 0-based numerical -index, or, if an enum is associated, a valid enum key string.

    -

    Accessing an invalid index is an error, but some container types -may return a default value, or auto-resize instead for convenience. -Currently this relaxed mode is implemented by df-flagarray aka BitArray.

    -
  • -
  • ref._field(index)

    -

    Like with structs, returns a pointer to the array element, if possible. -Flag and bit arrays cannot return such pointer, so it fails with an error.

    -
  • -
  • pairs(ref), ipairs(ref)

    -

    If the container has no associated enum, both behave identically, -iterating over numerical indices in order. Otherwise, ipairs still -uses numbers, while pairs tries to substitute enum keys whenever -possible.

    -
  • -
  • ref:resize(new_size)

    -

    Resizes the container if supported, or fails with an error.

    -
  • -
  • ref:insert(index,item)

    -

    Inserts a new item at the specified index. To add at the end, -use #ref, or just '#' as index.

    -
  • -
  • ref:erase(index)

    -

    Removes the element at the given valid index.

    -
  • -
-
-
-

Bitfield references

-

Bitfields behave like special fixed-size containers. -Consider them to be something in between structs and -fixed-size vectors.

-

The _enum property points to the bitfield type. -Numerical indices correspond to the shift value, -and if a subfield occupies multiple bits, the -ipairs order would have a gap.

-

Since currently there is no API to allocate a bitfield -object fully in GC-managed lua heap, consider using the -lua table assignment feature outlined below in order to -pass bitfield values to dfhack API functions that need -them, e.g. matinfo:matches{metal=true}.

-
-
-
-

Named types

-

Named types are exposed in the df tree with names identical -to the C++ version, except for the :: vs . difference.

-

All types and the global object have the following features:

-
    -
  • type._kind

    -

    Evaluates to one of struct-type, class-type, enum-type, -bitfield-type or global.

    -
  • -
  • type._identity

    -

    Contains a lightuserdata pointing to the underlying -DFHack::type_instance object.

    -
  • -
-

Types excluding the global object also support:

-
    -
  • type:sizeof()

    -

    Returns the size of an object of the type.

    -
  • -
  • type:new()

    -

    Creates a new instance of an object of the type.

    -
  • -
  • type:is_instance(object)

    -

    Returns true if object is same or subclass type, or a reference -to an object of same or subclass type. It is permissible to pass -nil, NULL or non-wrapper value as object; in this case the -method returns nil.

    -
  • -
-

In addition to this, enum and bitfield types contain a -bi-directional mapping between key strings and values, and -also map _first_item and _last_item to the min and -max values.

-

Struct and class types with instance-vector attribute in the -xml have a type.find(key) function that wraps the find -method provided in C++.

-
-
-

Global functions

-

The df table itself contains the following functions and values:

-
    -
  • NULL, df.NULL

    -

    Contains the NULL lightuserdata.

    -
  • -
  • df.isnull(obj)

    -

    Evaluates to true if obj is nil or NULL; false otherwise.

    -
  • -
  • df.isvalid(obj[,allow_null])

    -

    For supported objects returns one of type, voidptr, ref.

    -

    If allow_null is true, and obj is nil or NULL, returns null.

    -

    Otherwise returns nil.

    -
  • -
  • df.sizeof(obj)

    -

    For types and refs identical to obj:sizeof(). -For lightuserdata returns nil, address

    -
  • -
  • df.new(obj), df.delete(obj), df.assign(obj, obj2)

    -

    Equivalent to using the matching methods of obj.

    -
  • -
  • df._displace(obj,index[,step])

    -

    For refs equivalent to the method, but also works with -lightuserdata (step is mandatory then).

    -
  • -
  • df.is_instance(type,obj)

    -

    Equivalent to the method, but also allows a reference as proxy for its type.

    -
  • -
  • df.new(ptype[,count])

    -

    Allocate a new instance, or an array of built-in types. -The ptype argument is a string from the following list: -string, int8_t, uint8_t, int16_t, uint16_t, -int32_t, uint32_t, int64_t, uint64_t, bool, -float, double. All of these except string can be -used with the count argument to allocate an array.

    -
  • -
  • df.reinterpret_cast(type,ptr)

    -

    Converts ptr to a ref of specified type. The type may be anything -acceptable to df.is_instance. Ptr may be nil, a ref, -a lightuserdata, or a number.

    -

    Returns nil if NULL, or a ref.

    -
  • -
-
-
-

Recursive table assignment

-

Recursive assignment is invoked when a lua table is assigned -to a C++ object or field, i.e. one of:

-
    -
  • ref:assign{...}
  • -
  • ref.field = {...}
  • -
-

The general mode of operation is that all fields of the table -are assigned to the fields of the target structure, roughly -emulating the following code:

-
-function rec_assign(ref,table)
-    for key,value in pairs(table) do
-        ref[key] = value
-    end
-end
-
-

Since assigning a table to a field using = invokes the same -process, it is recursive.

-

There are however some variations to this process depending -on the type of the field being assigned to:

-
    -
  1. If the table contains an assign field, it is -applied first, using the ref:assign(value) method. -It is never assigned as a usual field.

    -
  2. -
  3. When a table is assigned to a non-NULL pointer field -using the ref.field = {...} syntax, it is applied -to the target of the pointer instead.

    -

    If the pointer is NULL, the table is checked for a new field:

    -
      -
    1. If it is nil or false, assignment fails with an error.
    2. -
    3. If it is true, the pointer is initialized with a newly -allocated object of the declared target type of the pointer.
    4. -
    5. Otherwise, table.new must be a named type, or an -object of a type compatible with the pointer. The pointer -is initialized with the result of calling table.new:new().
    6. -
    -

    After this auto-vivification process, assignment proceeds -as if the pointer wasn't NULL.

    -

    Obviously, the new field inside the table is always skipped -during the actual per-field assignment processing.

    -
  4. -
  5. If the target of the assignment is a container, a separate -rule set is used:

    -
      -
    1. If the table contains neither assign nor resize -fields, it is interpreted as an ordinary 1-based lua -array. The container is resized to the #-size of the -table, and elements are assigned in numeric order:

      -
      -ref:resize(#table);
      -for i=1,#table do ref[i-1] = table[i] end
      -
      -
    2. -
    3. Otherwise, resize must be true, false, or -an explicit number. If it is not false, the container -is resized. After that the usual struct-like 'pairs' -assignment is performed.

      -

      In case resize is true, the size is computed -by scanning the table for the largest numeric key.

      -
    4. -
    -

    This means that in order to reassign only one element of -a container using this system, it is necessary to use:

    -
    -{ resize=false, [idx]=value }
    -
    -
  6. -
-

Since nil inside a table is indistinguishable from missing key, -it is necessary to use df.NULL as a null pointer value.

-

This system is intended as a way to define a nested object -tree using pure lua data structures, and then materialize it in -C++ memory in one go. Note that if pointer auto-vivification -is used, an error in the middle of the recursive walk would -not destroy any objects allocated in this way, so the user -should be prepared to catch the error and do the necessary -cleanup.

-
-
-
-

DFHack API

-

DFHack utility functions are placed in the dfhack global tree.

-
-

Native utilities

-
-

Input & Output

-
    -
  • dfhack.print(args...)

    -

    Output tab-separated args as standard lua print would do, -but without a newline.

    -
  • -
  • print(args...), dfhack.println(args...)

    -

    A replacement of the standard library print function that -works with DFHack output infrastructure.

    -
  • -
  • dfhack.printerr(args...)

    -

    Same as println; intended for errors. Uses red color and logs to stderr.log.

    -
  • -
  • dfhack.color([color])

    -

    Sets the current output color. If color is nil or -1, resets to default. -Returns the previous color value.

    -
  • -
  • dfhack.is_interactive()

    -

    Checks if the thread can access the interactive console and returns true or false.

    -
  • -
  • dfhack.lineedit([prompt[,history_filename]])

    -

    If the thread owns the interactive console, shows a prompt -and returns the entered string. Otherwise returns nil, error.

    -

    Depending on the context, this function may actually yield the -running coroutine and let the C++ code release the core suspend -lock. Using an explicit dfhack.with_suspend will prevent -this, forcing the function to block on input with lock held.

    -
  • -
  • dfhack.interpreter([prompt[,history_filename[,env]]])

    -

    Starts an interactive lua interpreter, using the specified prompt -string, global environment and command-line history file.

    -

    If the interactive console is not accessible, returns nil, error.

    -
  • -
-
-
-

Exception handling

-
    -
  • dfhack.error(msg[,level[,verbose]])

    -

    Throws a dfhack exception object with location and stack trace. -The verbose parameter controls whether the trace is printed by default.

    -
  • -
  • qerror(msg[,level])

    -

    Calls dfhack.error() with verbose being false. Intended to -be used for user-caused errors in scripts, where stack traces are not -desirable.

    -
  • -
  • dfhack.pcall(f[,args...])

    -

    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.

    -
  • -
  • safecall(f[,args...]), dfhack.safecall(f[,args...])

    -

    Just like pcall, but also prints the error using printerr before -returning. Intended as a convenience function.

    -
  • -
  • dfhack.saferesume(coroutine[,args...])

    -

    Compares to coroutine.resume like dfhack.safecall vs pcall.

    -
  • -
  • dfhack.exception

    -

    Metatable of error objects used by dfhack. The objects have the -following properties:

    -
    -
    err.where
    -

    The location prefix string, or nil.

    -
    -
    err.message
    -

    The base message string.

    -
    -
    err.stacktrace
    -

    The stack trace string, or nil.

    -
    -
    err.cause
    -

    A different exception object, or nil.

    -
    -
    err.thread
    -

    The coroutine that has thrown the exception.

    -
    -
    err.verbose
    -

    Boolean, or nil; specifies if where and stacktrace should be printed.

    -
    -
    tostring(err), or err:tostring([verbose])
    -

    Converts the exception to string.

    -
    -
    -
  • -
  • dfhack.exception.verbose

    -

    The default value of the verbose argument of err:tostring().

    -
  • -
-
-
-

Miscellaneous

-
    -
  • dfhack.VERSION

    -

    DFHack version string constant.

    -
  • -
  • dfhack.curry(func,args...), or curry(func,args...)

    -

    Returns a closure that invokes the function with args combined -both from the curry call and the closure call itself. I.e. -curry(func,a,b)(c,d) equals func(a,b,c,d).

    -
  • -
-
-
-

Locking and finalization

-
    -
  • dfhack.with_suspend(f[,args...])

    -

    Calls f with arguments after grabbing the DF core suspend lock. -Suspending is necessary for accessing a consistent state of DF memory.

    -

    Returned values and errors are propagated through after releasing -the lock. It is safe to nest suspends.

    -

    Every thread is allowed only one suspend per DF frame, so it is best -to group operations together in one big critical section. A plugin -can choose to run all lua code inside a C++-side suspend lock.

    -
  • -
  • dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])

    -

    Invokes fn with args, and after it returns or throws an -error calls cleanup_fn with cleanup_args. Any return values from -fn are propagated, and errors are re-thrown.

    -

    The num_cleanup_args integer specifies the number of cleanup_args, -and the always boolean specifies if cleanup should be called in any case, -or only in case of an error.

    -
  • -
  • dfhack.with_finalize(cleanup_fn,fn[,args...])

    -

    Calls fn with arguments, then finalizes with cleanup_fn. -Implemented using call_with_finalizer(0,true,...).

    -
  • -
  • dfhack.with_onerror(cleanup_fn,fn[,args...])

    -

    Calls fn with arguments, then finalizes with cleanup_fn on any thrown error. -Implemented using call_with_finalizer(0,false,...).

    -
  • -
  • dfhack.with_temp_object(obj,fn[,args...])

    -

    Calls fn(obj,args...), then finalizes with obj:delete().

    -
  • -
-
-
-

Persistent configuration storage

-

This api is intended for storing configuration options in the world itself. -It probably should be restricted to data that is world-dependent.

-

Entries are identified by a string key, but it is also possible to manage -multiple entries with the same key; their identity is determined by entry_id. -Every entry has a mutable string value, and an array of 7 mutable ints.

-
    -
  • dfhack.persistent.get(key), entry:get()

    -

    Retrieves a persistent config record with the given string key, -or refreshes an already retrieved entry. If there are multiple -entries with the same key, it is undefined which one is retrieved -by the first version of the call.

    -

    Returns entry, or nil if not found.

    -
  • -
  • dfhack.persistent.delete(key), entry:delete()

    -

    Removes an existing entry. Returns true if succeeded.

    -
  • -
  • dfhack.persistent.get_all(key[,match_prefix])

    -

    Retrieves all entries with the same key, or starting with key..'/'. -Calling get_all('',true) will match all entries.

    -

    If none found, returns nil; otherwise returns an array of entries.

    -
  • -
  • dfhack.persistent.save({key=str1, ...}[,new]), entry:save([new])

    -

    Saves changes in an entry, or creates a new one. Passing true as -new forces creation of a new entry even if one already exists; -otherwise the existing one is simply updated. -Returns entry, did_create_new

    -
  • -
-

Since the data is hidden in data structures owned by the DF world, -and automatically stored in the save game, these save and retrieval -functions can just copy values in memory without doing any actual I/O. -However, currently every entry has a 180+-byte dead-weight overhead.

-
-
-

Material info lookup

-

A material info record has fields:

-
    -
  • type, index, material

    -

    DF material code pair, and a reference to the material object.

    -
  • -
  • mode

    -

    One of 'builtin', 'inorganic', 'plant', 'creature'.

    -
  • -
  • inorganic, plant, creature

    -

    If the material is of the matching type, contains a reference to the raw object.

    -
  • -
  • figure

    -

    For a specific creature material contains a ref to the historical figure.

    -
  • -
-

Functions:

-
    -
  • dfhack.matinfo.decode(type,index)

    -

    Looks up material info for the given number pair; if not found, returs nil.

    -
  • -
  • ....decode(matinfo), ....decode(item), ....decode(obj)

    -

    Uses matinfo.type/matinfo.index, item getter vmethods, -or obj.mat_type/obj.mat_index to get the code pair.

    -
  • -
  • dfhack.matinfo.find(token[,token...])

    -

    Looks up material by a token string, or a pre-split string token sequence.

    -
  • -
  • dfhack.matinfo.getToken(...), info:getToken()

    -

    Applies decode and constructs a string token.

    -
  • -
  • info:toString([temperature[,named]])

    -

    Returns the human-readable name at the given temperature.

    -
  • -
  • info:getCraftClass()

    -

    Returns the classification used for craft skills.

    -
  • -
  • info:matches(obj)

    -

    Checks if the material matches job_material_category or job_item. -Accept dfhack_material_category auto-assign table.

    -
  • -
-
-
-
-

C++ function wrappers

-

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 -can be omitted.

-
    -
  • dfhack.getOSType()

    -

    Returns the OS type string from symbols.xml.

    -
  • -
  • dfhack.getDFVersion()

    -

    Returns the DF version string from symbols.xml.

    -
  • -
  • dfhack.getDFPath()

    -

    Returns the DF directory path.

    -
  • -
  • dfhack.getHackPath()

    -

    Returns the dfhack directory path, i.e. ".../df/hack/".

    -
  • -
  • dfhack.getTickCount()

    -

    Returns the tick count in ms, exactly as DF ui uses.

    -
  • -
  • dfhack.isWorldLoaded()

    -

    Checks if the world is loaded.

    -
  • -
  • dfhack.isMapLoaded()

    -

    Checks if the world and map are loaded.

    -
  • -
  • dfhack.TranslateName(name[,in_english,only_last_name])

    -

    Convert a language_name or only the last name part to string.

    -
  • -
-
-

Gui module

-
    -
  • dfhack.gui.getCurViewscreen([skip_dismissed])

    -

    Returns the topmost viewscreen. If skip_dismissed is true, -ignores screens already marked to be removed.

    -
  • -
  • dfhack.gui.getFocusString(viewscreen)

    -

    Returns a string representation of the current focus position -in the ui. The string has a "screen/foo/bar/baz..." format.

    -
  • -
  • dfhack.gui.getCurFocus([skip_dismissed])

    -

    Returns the focus string of the current viewscreen.

    -
  • -
  • dfhack.gui.getSelectedWorkshopJob([silent])

    -

    When a job is selected in 'q' mode, returns the job, else -prints error unless silent and returns nil.

    -
  • -
  • dfhack.gui.getSelectedJob([silent])

    -

    Returns the job selected in a workshop or unit/jobs screen.

    -
  • -
  • dfhack.gui.getSelectedUnit([silent])

    -

    Returns the unit selected via 'v', 'k', unit/jobs, or -a full-screen item view of a cage or suchlike.

    -
  • -
  • dfhack.gui.getSelectedItem([silent])

    -

    Returns the item selected via 'v' ->inventory, 'k', 't', or -a full-screen item view of a container. Note that in the -last case, the highlighted contained item is returned, not -the container itself.

    -
  • -
  • dfhack.gui.getSelectedBuilding([silent])

    -

    Returns the building selected via 'q', 't', 'k' or 'i'.

    -
  • -
  • dfhack.gui.showAnnouncement(text,color[,is_bright])

    -

    Adds a regular announcement with given text, color, and brightness. -The is_bright boolean actually seems to invert the brightness.

    -
  • -
  • dfhack.gui.showZoomAnnouncement(type,pos,text,color[,is_bright])

    -

    Like above, but also specifies a position you can zoom to from the announcement menu.

    -
  • -
  • dfhack.gui.showPopupAnnouncement(text,color[,is_bright])

    -

    Pops up a titan-style modal announcement window.

    -
  • -
  • dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])

    -

    Uses the type to look up options from announcements.txt, and calls the -above operations accordingly. If enabled, pauses and zooms to position.

    -
  • -
-
-
-

Job module

-
    -
  • dfhack.job.cloneJobStruct(job)

    -

    Creates a deep copy of the given job.

    -
  • -
  • dfhack.job.printJobDetails(job)

    -

    Prints info about the job.

    -
  • -
  • dfhack.job.printItemDetails(jobitem,idx)

    -

    Prints info about the job item.

    -
  • -
  • dfhack.job.getHolder(job)

    -

    Returns the building holding the job.

    -
  • -
  • dfhack.job.getWorker(job)

    -

    Returns the unit performing the job.

    -
  • -
  • dfhack.job.checkBuildingsNow()

    -

    Instructs the game to check buildings for jobs next frame and assign workers.

    -
  • -
  • dfhack.job.checkDesignationsNow()

    -

    Instructs the game to check designations for jobs next frame and assign workers.

    -
  • -
  • dfhack.job.is_equal(job1,job2)

    -

    Compares important fields in the job and nested item structures.

    -
  • -
  • dfhack.job.is_item_equal(job_item1,job_item2)

    -

    Compares important fields in the job item structures.

    -
  • -
  • dfhack.job.listNewlyCreated(first_id)

    -

    Returns the current value of df.global.job_next_id, and -if there are any jobs with first_id <= id < job_next_id, -a lua list containing them.

    -
  • -
-
-
-

Units module

-
    -
  • dfhack.units.getPosition(unit)

    -

    Returns true x,y,z of the unit, or nil if invalid; may be not equal to unit.pos if caged.

    -
  • -
  • dfhack.units.getContainer(unit)

    -

    Returns the container (cage) item or nil.

    -
  • -
  • dfhack.units.setNickname(unit,nick)

    -

    Sets the unit's nickname properly.

    -
  • -
  • dfhack.units.getVisibleName(unit)

    -

    Returns the language_name object visible in game, accounting for false identities.

    -
  • -
  • dfhack.units.getIdentity(unit)

    -

    Returns the false identity of the unit if it has one, or nil.

    -
  • -
  • dfhack.units.getNemesis(unit)

    -

    Returns the nemesis record of the unit if it has one, or nil.

    -
  • -
  • dfhack.units.isHidingCurse(unit)

    -

    Checks if the unit hides improved attributes from its curse.

    -
  • -
  • dfhack.units.getPhysicalAttrValue(unit, attr_type)

    -
  • -
  • dfhack.units.getMentalAttrValue(unit, attr_type)

    -

    Computes the effective attribute value, including curse effect.

    -
  • -
  • dfhack.units.isCrazed(unit)

    -
  • -
  • dfhack.units.isOpposedToLife(unit)

    -
  • -
  • dfhack.units.hasExtravision(unit)

    -
  • -
  • dfhack.units.isBloodsucker(unit)

    -

    Simple checks of caste attributes that can be modified by curses.

    -
  • -
  • dfhack.units.getMiscTrait(unit, type[, create])

    -

    Finds (or creates if requested) a misc trait object with the given id.

    -
  • -
  • dfhack.units.isDead(unit)

    -

    The unit is completely dead and passive, or a ghost.

    -
  • -
  • dfhack.units.isAlive(unit)

    -

    The unit isn't dead or undead.

    -
  • -
  • dfhack.units.isSane(unit)

    -

    The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.

    -
  • -
  • dfhack.units.isDwarf(unit)

    -

    The unit is of the correct race of the fortress.

    -
  • -
  • dfhack.units.isCitizen(unit)

    -

    The unit is an alive sane citizen of the fortress; wraps the -same checks the game uses to decide game-over by extinction.

    -
  • -
  • dfhack.units.getAge(unit[,true_age])

    -

    Returns the age of the unit in years as a floating-point value. -If true_age is true, ignores false identities.

    -
  • -
  • dfhack.units.getNominalSkill(unit, skill[, use_rust])

    -

    Retrieves the nominal skill level for the given unit. If use_rust -is true, subtracts the rust penalty.

    -
  • -
  • dfhack.units.getEffectiveSkill(unit, skill)

    -

    Computes the effective rating for the given skill, taking into account exhaustion, pain etc.

    -
  • -
  • dfhack.units.computeMovementSpeed(unit)

    -

    Computes number of frames * 100 it takes the unit to move in its current state of mind and body.

    -
  • -
  • dfhack.units.getNoblePositions(unit)

    -

    Returns a list of tables describing noble position assignments, or nil. -Every table has fields entity, assignment and position.

    -
  • -
  • dfhack.units.getProfessionName(unit[,ignore_noble,plural])

    -

    Retrieves the profession name using custom profession, noble assignments -or raws. The ignore_noble boolean disables the use of noble positions.

    -
  • -
  • dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])

    -

    Retrieves the profession name for the given race/caste using raws.

    -
  • -
  • dfhack.units.getProfessionColor(unit[,ignore_noble])

    -

    Retrieves the color associated with the profession, using noble assignments -or raws. The ignore_noble boolean disables the use of noble positions.

    -
  • -
  • dfhack.units.getCasteProfessionColor(race,caste,prof_id)

    -

    Retrieves the profession color for the given race/caste using raws.

    -
  • -
-
-
-

Items module

-
    -
  • dfhack.items.getPosition(item)

    -

    Returns true x,y,z of the item, or nil if invalid; may be not equal to item.pos if in inventory.

    -
  • -
  • dfhack.items.getDescription(item, type[, decorate])

    -

    Returns the string description of the item, as produced by the getItemDescription -method. If decorate is true, also adds markings for quality and improvements.

    -
  • -
  • dfhack.items.getGeneralRef(item, type)

    -

    Searches for a general_ref with the given type.

    -
  • -
  • dfhack.items.getSpecificRef(item, type)

    -

    Searches for a specific_ref with the given type.

    -
  • -
  • dfhack.items.getOwner(item)

    -

    Returns the owner unit or nil.

    -
  • -
  • dfhack.items.setOwner(item,unit)

    -

    Replaces the owner of the item. If unit is nil, removes ownership. -Returns false in case of error.

    -
  • -
  • dfhack.items.getContainer(item)

    -

    Returns the container item or nil.

    -
  • -
  • dfhack.items.getContainedItems(item)

    -

    Returns a list of items contained in this one.

    -
  • -
  • dfhack.items.moveToGround(item,pos)

    -

    Move the item to the ground at position. Returns false if impossible.

    -
  • -
  • dfhack.items.moveToContainer(item,container)

    -

    Move the item to the container. Returns false if impossible.

    -
  • -
  • dfhack.items.moveToBuilding(item,building,use_mode)

    -

    Move the item to the building. Returns false if impossible.

    -
  • -
  • dfhack.items.moveToInventory(item,unit,use_mode,body_part)

    -

    Move the item to the unit inventory. Returns false if impossible.

    -
  • -
  • dfhack.items.remove(item[, no_uncat])

    -

    Removes the item, and marks it for garbage collection unless no_uncat is true.

    -
  • -
  • dfhack.items.makeProjectile(item)

    -

    Turns the item into a projectile, and returns the new object, or nil if impossible.

    -
  • -
-
-
-

Maps module

-
    -
  • dfhack.maps.getSize()

    -

    Returns map size in blocks: x, y, z

    -
  • -
  • dfhack.maps.getTileSize()

    -

    Returns map size in tiles: x, y, z

    -
  • -
  • dfhack.maps.getBlock(x,y,z)

    -

    Returns a map block object for given x,y,z in local block coordinates.

    -
  • -
  • dfhack.maps.isValidTilePos(coords), or isValidTilePos(x,y,z)``

    -

    Checks if the given df::coord or x,y,z in local tile coordinates are valid.

    -
  • -
  • dfhack.maps.getTileBlock(coords), or getTileBlock(x,y,z)

    -

    Returns a map block object for given df::coord or x,y,z in local tile coordinates.

    -
  • -
  • dfhack.maps.ensureTileBlock(coords), or ensureTileBlock(x,y,z)

    -

    Like getTileBlock, but if the block is not allocated, try creating it.

    -
  • -
  • dfhack.maps.getRegionBiome(region_coord2d), or getRegionBiome(x,y)

    -

    Returns the biome info struct for the given global map region.

    -
  • -
  • dfhack.maps.enableBlockUpdates(block[,flow,temperature])

    -

    Enables updates for liquid flow or temperature, unless already active.

    -
  • -
  • dfhack.maps.spawnFlow(pos,type,mat_type,mat_index,dimension)

    -

    Spawns a new flow (i.e. steam/mist/dust/etc) at the given pos, and with -the given parameters. Returns it, or nil if unsuccessful.

    -
  • -
  • dfhack.maps.getGlobalInitFeature(index)

    -

    Returns the global feature object with the given index.

    -
  • -
  • dfhack.maps.getLocalInitFeature(region_coord2d,index)

    -

    Returns the local feature object with the given region coords and index.

    -
  • -
  • dfhack.maps.getTileBiomeRgn(coords), or getTileBiomeRgn(x,y,z)

    -

    Returns x, y for use with getRegionBiome.

    -
  • -
  • dfhack.maps.canWalkBetween(pos1, pos2)

    -

    Checks if a dwarf may be able to walk between the two tiles, -using a pathfinding cache maintained by the game. Note that -this cache is only updated when the game is unpaused, and thus -can get out of date if doors are forbidden or unforbidden, or -tools like liquids or tiletypes are used. It also cannot possibly -take into account anything that depends on the actual units, like -burrows, or the presence of invaders.

    -
  • -
-
-
-

Burrows module

-
    -
  • dfhack.burrows.findByName(name)

    -

    Returns the burrow pointer or nil.

    -
  • -
  • dfhack.burrows.clearUnits(burrow)

    -

    Removes all units from the burrow.

    -
  • -
  • dfhack.burrows.isAssignedUnit(burrow,unit)

    -

    Checks if the unit is in the burrow.

    -
  • -
  • dfhack.burrows.setAssignedUnit(burrow,unit,enable)

    -

    Adds or removes the unit from the burrow.

    -
  • -
  • dfhack.burrows.clearTiles(burrow)

    -

    Removes all tiles from the burrow.

    -
  • -
  • dfhack.burrows.listBlocks(burrow)

    -

    Returns a table of map block pointers.

    -
  • -
  • dfhack.burrows.isAssignedTile(burrow,tile_coord)

    -

    Checks if the tile is in burrow.

    -
  • -
  • dfhack.burrows.setAssignedTile(burrow,tile_coord,enable)

    -

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    -
  • -
  • dfhack.burrows.isAssignedBlockTile(burrow,block,x,y)

    -

    Checks if the tile within the block is in burrow.

    -
  • -
  • dfhack.burrows.setAssignedBlockTile(burrow,block,x,y,enable)

    -

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    -
  • -
-
-
-

Buildings module

-
    -
  • dfhack.buildings.setOwner(item,unit)

    -

    Replaces the owner of the building. If unit is nil, removes ownership. -Returns false in case of error.

    -
  • -
  • dfhack.buildings.getSize(building)

    -

    Returns width, height, centerx, centery.

    -
  • -
  • dfhack.buildings.findAtTile(pos), or findAtTile(x,y,z)

    -

    Scans the buildings for the one located at the given tile. -Does not work on civzones. Warning: linear scan if the map -tile indicates there are buildings at it.

    -
  • -
  • dfhack.buildings.findCivzonesAt(pos), or findCivzonesAt(x,y,z)

    -

    Scans civzones, and returns a lua sequence of those that touch -the given tile, or nil if none.

    -
  • -
  • dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)

    -

    Computes correct dimensions for the specified building type and orientation, -using width and height for flexible dimensions. -Returns is_flexible, width, height, center_x, center_y.

    -
  • -
  • dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])

    -

    Checks if the rectangle defined by pos and size, and possibly extents, -can be used for placing a building. If change_extents is true, bad tiles -are removed from extents. If allow_occupied, the occupancy test is skipped.

    -
  • -
  • dfhack.buildings.countExtentTiles(extents,defval)

    -

    Returns the number of tiles included by extents, or defval.

    -
  • -
  • dfhack.buildings.containsTile(building, x, y[, room])

    -

    Checks if the building contains the specified tile, either directly, or as room.

    -
  • -
  • dfhack.buildings.hasSupport(pos,size)

    -

    Checks if a bridge constructed at specified position would have -support from terrain, and thus won't collapse if retracted.

    -
  • -
-

Low-level building creation functions;

-
    -
  • dfhack.buildings.allocInstance(pos, type, subtype, custom)

    -

    Creates a new building instance of given type, subtype and custom type, -at specified position. Returns the object, or nil in case of an error.

    -
  • -
  • dfhack.buildings.setSize(building, width, height, direction)

    -

    Configures an object returned by allocInstance, using specified -parameters wherever appropriate. If the building has fixed size along -any dimension, the corresponding input parameter will be ignored. -Returns false if the building cannot be placed, or true, width, -height, rect_area, true_area. Returned width and height are the -final values used by the building; true_area is less than rect_area -if any tiles were removed from designation.

    -
  • -
  • dfhack.buildings.constructAbstract(building)

    -

    Links a fully configured object created by allocInstance into the -world. The object must be an abstract building, i.e. a stockpile or civzone. -Returns true, or false if impossible.

    -
  • -
  • dfhack.buildings.constructWithItems(building, items)

    -

    Links a fully configured object created by allocInstance into the -world for construction, using a list of specific items as material. -Returns true, or false if impossible.

    -
  • -
  • dfhack.buildings.constructWithFilters(building, job_items)

    -

    Links a fully configured object created by allocInstance into the -world for construction, using a list of job_item filters as inputs. -Returns true, or false if impossible. Filter objects are claimed -and possibly destroyed in any case. -Use a negative quantity field value to auto-compute the amount -from the size of the building.

    -
  • -
  • dfhack.buildings.deconstruct(building)

    -

    Destroys the building, or queues a deconstruction job. -Returns true if the building was destroyed and deallocated immediately.

    -
  • -
-

More high-level functions are implemented in lua and can be loaded by -require('dfhack.buildings'). See hack/lua/dfhack/buildings.lua.

-

Among them are:

-
    -
  • dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)

    -

    Returns a sequence of lua structures, describing input item filters -suitable for the specified building type, or nil if unknown or invalid. -The returned sequence is suitable for use as the job_items argument -of constructWithFilters. -Uses tables defined in buildings.lua.

    -

    Argtable members material (the default name), bucket, barrel, -chain, mechanism, screw, pipe, anvil, weapon are used to -augment the basic attributes with more detailed information if the -building has input items with the matching name (see the tables for naming details). -Note that it is impossible to override any properties this way, only supply those that -are not mentioned otherwise; one exception is that flags2.non_economic -is automatically cleared if an explicit material is specified.

    -
  • -
  • dfhack.buildings.constructBuilding{...}

    -

    Creates a building in one call, using options contained -in the argument table. Returns the building, or nil, error.

    -

    NOTE: Despite the name, unless the building is abstract, -the function creates it in an 'unconstructed' stage, with -a queued in-game job that will actually construct it. I.e. -the function replicates programmatically what can be done -through the construct building menu in the game ui, except -that it does less environment constraint checking.

    -

    The following options can be used:

    -
      -
    • pos = coordinates, or x = ..., y = ..., z = ...

      -

      Mandatory. Specifies the left upper corner of the building.

      -
    • -
    • type = df.building_type.FOO, subtype = ..., custom = ...

      -

      Mandatory. Specifies the type of the building. Obviously, subtype -and custom are only expected if the type requires them.

      -
    • -
    • fields = { ... }

      -

      Initializes fields of the building object after creation with df.assign.

      -
    • -
    • width = ..., height = ..., direction = ...

      -

      Sets size and orientation of the building. If it is -fixed-size, specified dimensions are ignored.

      -
    • -
    • full_rectangle = true

      -

      For buildings like stockpiles or farm plots that can normally -accomodate individual tile exclusion, forces an error if any -tiles within the specified width*height are obstructed.

      -
    • -
    • items = { item, item ... }, or filters = { {...}, {...}... }

      -

      Specifies explicit items or item filters to use in construction. -It is the job of the user to ensure they are correct for the building type.

      -
    • -
    • abstract = true

      -

      Specifies that the building is abstract and does not require construction. -Required for stockpiles and civzones; an error otherwise.

      -
    • -
    • material = {...}, mechanism = {...}, ...

      -

      If none of items, filter, or abstract is used, -the function uses getFiltersByType to compute the input -item filters, and passes the argument table through. If no filters -can be determined this way, constructBuilding throws an error.

      -
    • -
    -
  • -
-
-
-

Constructions module

-
    -
  • dfhack.constructions.designateNew(pos,type,item_type,mat_index)

    -

    Designates a new construction at given position. If there already is -a planned but not completed construction there, changes its type. -Returns true, or false if obstructed. -Note that designated constructions are technically buildings.

    -
  • -
  • dfhack.constructions.designateRemove(pos), or designateRemove(x,y,z)

    -

    If there is a construction or a planned construction at the specified -coordinates, designates it for removal, or instantly cancels the planned one. -Returns true, was_only_planned if removed; or false if none found.

    -
  • -
-
-
-

Screen API

-

The screen module implements support for drawing to the tiled screen of the game. -Note that drawing only has any effect when done from callbacks, so it can only -be feasibly used in the core context.

-

Basic painting functions:

-
    -
  • dfhack.screen.getWindowSize()

    -

    Returns width, height of the screen.

    -
  • -
  • dfhack.screen.getMousePos()

    -

    Returns x,y of the tile the mouse is over.

    -
  • -
  • dfhack.screen.inGraphicsMode()

    -

    Checks if [GRAPHICS:YES] was specified in init.

    -
  • -
  • dfhack.screen.paintTile(pen,x,y[,char,tile])

    -

    Paints a tile using given parameters. Pen is a table with following possible fields:

    -
    -
    ch
    -

    Provides the ordinary tile character, as either a 1-character string or a number. -Can be overridden with the char function parameter.

    -
    -
    fg
    -

    Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).

    -
    -
    bg
    -

    Background color for the ordinary tile. Defaults to COLOR_BLACK (0).

    -
    -
    bold
    -

    Bright/bold text flag. If nil, computed based on (fg & 8); fg is masked to 3 bits. -Otherwise should be true/false.

    -
    -
    tile
    -

    Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.

    -
    -
    tile_color = true
    -

    Specifies that the tile should be shaded with fg/bg.

    -
    -
    tile_fg, tile_bg
    -

    If specified, overrides tile_color and supplies shading colors directly.

    -
    -
    -

    Returns false if coordinates out of bounds, or other error.

    -
  • -
  • dfhack.screen.readTile(x,y)

    -

    Retrieves the contents of the specified tile from the screen buffers. -Returns a pen, or nil if invalid or TrueType.

    -
  • -
  • dfhack.screen.paintString(pen,x,y,text)

    -

    Paints the string starting at x,y. Uses the string characters -in sequence to override the ch field of pen.

    -

    Returns true if painting at least one character succeeded.

    -
  • -
  • dfhack.screen.fillRect(pen,x1,y1,x2,y2)

    -

    Fills the rectangle specified by the coordinates with the given pen. -Returns true if painting at least one character succeeded.

    -
  • -
  • dfhack.screen.findGraphicsTile(pagename,x,y)

    -

    Finds a tile from a graphics set (i.e. the raws used for creatures), -if in graphics mode and loaded.

    -

    Returns: tile, tile_grayscale, or nil if not found. -The values can then be used for the tile field of pen structures.

    -
  • -
  • dfhack.screen.clear()

    -

    Fills the screen with blank background.

    -
  • -
  • dfhack.screen.invalidate()

    -

    Requests repaint of the screen by setting a flag. Unlike other -functions in this section, this may be used at any time.

    -
  • -
-

In order to actually be able to paint to the screen, it is necessary -to create and register a viewscreen (basically a modal dialog) with -the game.

-

NOTE: As a matter of policy, in order to avoid user confusion, all -interface screens added by dfhack should bear the "DFHack" signature.

-

Screens are managed with the following functions:

-
    -
  • dfhack.screen.show(screen[,below])

    -

    Displays the given screen, possibly placing it below a different one. -The screen must not be already shown. Returns true if success.

    -
  • -
  • dfhack.screen.dismiss(screen[,to_first])

    -

    Marks the screen to be removed when the game enters its event loop. -If to_first is true, all screens up to the first one will be deleted.

    -
  • -
  • dfhack.screen.isDismissed(screen)

    -

    Checks if the screen is already marked for removal.

    -
  • -
-

Apart from a native viewscreen object, these functions accept a table -as a screen. In this case, show creates a new native viewscreen -that delegates all processing to methods stored in that table.

-

NOTE: Lua-implemented screens are only supported in the core context.

-

Supported callbacks and fields are:

-
    -
  • screen._native

    -

    Initialized by show with a reference to the backing viewscreen -object, and removed again when the object is deleted.

    -
  • -
  • function screen:onShow()

    -

    Called by dfhack.screen.show if successful.

    -
  • -
  • function screen:onDismiss()

    -

    Called by dfhack.screen.dismiss if successful.

    -
  • -
  • function screen:onDestroy()

    -

    Called from the destructor when the viewscreen is deleted.

    -
  • -
  • function screen:onResize(w, h)

    -

    Called before onRender or onIdle when the window size has changed.

    -
  • -
  • function screen:onRender()

    -

    Called when the viewscreen should paint itself. This is the only context -where the above painting functions work correctly.

    -

    If omitted, the screen is cleared; otherwise it should do that itself. -In order to make a see-through dialog, call self._native.parent:render().

    -
  • -
  • function screen:onIdle()

    -

    Called every frame when the screen is on top of the stack.

    -
  • -
  • function screen:onHelp()

    -

    Called when the help keybinding is activated (usually '?').

    -
  • -
  • function screen:onInput(keys)

    -

    Called when keyboard or mouse events are available. -If any keys are pressed, the keys argument is a table mapping them to true. -Note that this refers to logical keybingings computed from real keys via -options; if multiple interpretations exist, the table will contain multiple keys.

    -

    The table also may contain special keys:

    -
    -
    _STRING
    -

    Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience.

    -
    -
    _MOUSE_L, _MOUSE_R
    -

    If the left or right mouse button is pressed.

    -
    -
    -

    If this method is omitted, the screen is dismissed on receival of the LEAVESCREEN key.

    -
  • -
  • function screen:onGetSelectedUnit()

    -
  • -
  • function screen:onGetSelectedItem()

    -
  • -
  • function screen:onGetSelectedJob()

    -
  • -
  • function screen:onGetSelectedBuilding()

    -

    Implement these to provide a return value for the matching -dfhack.gui.getSelected... function.

    -
  • -
-
-
-

Internal API

-

These functions are intended for the use by dfhack developers, -and are only documented here for completeness:

-
    -
  • dfhack.internal.scripts

    -

    The table used by dfhack.run_script() to give every script its own -global environment, persistent between calls to the script.

    -
  • -
  • dfhack.internal.getAddress(name)

    -

    Returns the global address name, or nil.

    -
  • -
  • dfhack.internal.setAddress(name, value)

    -

    Sets the global address name. Returns the value of getAddress before the change.

    -
  • -
  • dfhack.internal.getVTable(name)

    -

    Returns the pre-extracted vtable address name, or nil.

    -
  • -
  • dfhack.internal.getRebaseDelta()

    -

    Returns the ASLR rebase offset of the DF executable.

    -
  • -
  • dfhack.internal.getMemRanges()

    -

    Returns a sequence of tables describing virtual memory ranges of the process.

    -
  • -
  • dfhack.internal.patchMemory(dest,src,count)

    -

    Like memmove below, but works even if dest is read-only memory, e.g. code. -If destination overlaps a completely invalid memory region, or another error -occurs, returns false.

    -
  • -
  • dfhack.internal.memmove(dest,src,count)

    -

    Wraps the standard memmove function. Accepts both numbers and refs as pointers.

    -
  • -
  • dfhack.internal.memcmp(ptr1,ptr2,count)

    -

    Wraps the standard memcmp function.

    -
  • -
  • dfhack.internal.memscan(haystack,count,step,needle,nsize)

    -

    Searches for needle of nsize bytes in haystack, -using count steps of step bytes. -Returns: step_idx, sum_idx, found_ptr, or nil if not found.

    -
  • -
  • dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])

    -

    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: found_index, or nil if end reached.

    -
  • -
-
-
-
-

Core interpreter context

-

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.

-

Core context specific functions:

-
    -
  • dfhack.is_core_context

    -

    Boolean value; true in the core context.

    -
  • -
  • dfhack.timeout(time,mode,callback)

    -

    Arranges for the callback to be called once the specified -period of time passes. The mode argument specifies the -unit of time used, and may be one of 'frames' (raw FPS), -'ticks' (unpaused FPS), 'days', 'months', -'years' (in-game time). All timers other than -'frames' are cancelled when the world is unloaded, -and cannot be queued until it is loaded again. -Returns the timer id, or nil if unsuccessful due to -world being unloaded.

    -
  • -
  • dfhack.timeout_active(id[,new_callback])

    -

    Returns the active callback with the given id, or nil -if inactive or nil id. If called with 2 arguments, replaces -the current callback with the given value, if still active. -Using timeout_active(id,nil) cancels the timer.

    -
  • -
  • dfhack.onStateChange.foo = function(code)

    -

    Event. Receives the same codes as plugin_onstatechange in C++.

    -
  • -
-
-

Event type

-

An event is a native object transparently wrapping a lua table, -and implementing a __call metamethod. When it is invoked, it loops -through the table with next and calls all contained values. -This is intended as an extensible way to add listeners.

-

This type itself is available in any context, but only the -core context has the actual events defined by C++ code.

-

Features:

-
    -
  • dfhack.event.new()

    -

    Creates a new instance of an event.

    -
  • -
  • event[key] = function

    -

    Sets the function as one of the listeners. Assign nil to remove it.

    -

    NOTE: The df.NULL key is reserved for the use by -the C++ owner of the event; it is an error to try setting it.

    -
  • -
  • #event

    -

    Returns the number of non-nil listeners.

    -
  • -
  • pairs(event)

    -

    Iterates over all listeners in the table.

    -
  • -
  • event(args...)

    -

    Invokes all listeners contained in the event in an arbitrary -order using dfhack.safecall.

    -
  • -
-
-
-
-
-

Lua Modules

-

DFHack sets up the lua interpreter so that the built-in require -function can be used to load shared lua code from hack/lua/. -The dfhack namespace reference itself may be obtained via -require('dfhack'), although it is initially created as a -global by C++ bootstrap code.

-

The following module management functions are provided:

- -
-

Global environment

-

A number of variables and functions are provided in the base global -environment by the mandatory init file dfhack.lua:

-
    -
  • Color constants

    -

    These are applicable both for dfhack.color() and color fields -in DF functions or structures:

    -

    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

    -
  • -
  • dfhack.onStateChange event codes

    -

    Available only in the core context, as is the event itself:

    -

    SC_WORLD_LOADED, SC_WORLD_UNLOADED, SC_MAP_LOADED, -SC_MAP_UNLOADED, SC_VIEWSCREEN_CHANGED, SC_CORE_INITIALIZED

    -
  • -
  • Functions already described above

    -

    safecall, qerror, mkmodule, reload

    -
  • -
  • printall(obj)

    -

    If the argument is a lua table or DF object reference, prints all fields.

    -
  • -
  • copyall(obj)

    -

    Returns a shallow copy of the table or reference as a lua table.

    -
  • -
  • pos2xyz(obj)

    -

    The object must have fields x, y and z. Returns them as 3 values. -If obj is nil, or x is -30000 (the usual marker for undefined -coordinates), returns nil.

    -
  • -
  • xyz2pos(x,y,z)

    -

    Returns a table with x, y and z as fields.

    -
  • -
  • safe_index(obj,index...)

    -

    Walks a sequence of dereferences, which may be represented by numbers or strings. -Returns nil if any of obj or indices is nil, or a numeric index is out of array bounds.

    -
  • -
-
-
-

utils

-
    -
  • utils.compare(a,b)

    -

    Comparator function; returns -1 if a<b, 1 if a>b, 0 otherwise.

    -
  • -
  • utils.compare_name(a,b)

    -

    Comparator for names; compares empty string last.

    -
  • -
  • utils.is_container(obj)

    -

    Checks if obj is a container ref.

    -
  • -
  • utils.make_index_sequence(start,end)

    -

    Returns a lua sequence of numbers in start..end.

    -
  • -
  • utils.make_sort_order(data, ordering)

    -

    Computes a sorted permutation of objects in data, as a table of integer -indices into the data sequence. Uses data.n as input length -if present.

    -

    The ordering argument is a sequence of ordering specs, represented -as lua tables with following possible fields:

    -
    -
    ord.key = function(value)
    -

    Computes comparison key from input data value. Not called on nil. -If omitted, the comparison key is the value itself.

    -
    -
    ord.key_table = function(data)
    -

    Computes a key table from the data table in one go.

    -
    -
    ord.compare = function(a,b)
    -

    Comparison function. Defaults to utils.compare above. -Called on non-nil keys; nil sorts last.

    -
    -
    ord.nil_first = true/false
    -

    If true, nil keys are sorted first instead of last.

    -
    -
    ord.reverse = true/false
    -

    If true, sort non-nil keys in descending order.

    -
    -
    -

    For every comparison during sorting the specs are applied in -order until an unambiguous decision is reached. Sorting is stable.

    -

    Example of sorting a sequence by field foo:

    -
    -local spec = { key = function(v) return v.foo end }
    -local order = utils.make_sort_order(data, { spec })
    -local output = {}
    -for i = 1,#order do output[i] = data[order[i]] end
    -
    -

    Separating the actual reordering of the sequence in this -way enables applying the same permutation to multiple arrays. -This function is used by the sort plugin.

    -
  • -
  • utils.assign(tgt, src)

    -

    Does a recursive assignment of src into tgt. -Uses df.assign if tgt is a native object ref; otherwise -recurses into lua tables.

    -
  • -
  • utils.clone(obj, deep)

    -

    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.

    -
  • -
  • utils.clone_with_default(obj, default, force)

    -

    Copies the object, using the default lua table tree -as a guide to which values should be skipped as uninteresting. -The force argument makes it always return a non-nil value.

    -
  • -
  • utils.sort_vector(vector,field,cmpfun)

    -

    Sorts a native vector or lua sequence using the comparator function. -If field is not nil, applies the comparator to the field instead -of the whole object.

    -
  • -
  • utils.binsearch(vector,key,field,cmpfun,min,max)

    -

    Does a binary search in a native vector or lua sequence for -key, using cmpfun and field like sort_vector. -If min and max are specified, they are used as the -search subrange bounds.

    -

    If found, returns item, true, idx. Otherwise returns -nil, false, insert_idx, where insert_idx is the correct -insertion point.

    -
  • -
  • utils.insert_sorted(vector,item,field,cmpfun)

    -

    Does a binary search, and inserts item if not found. -Returns did_insert, vector[idx], idx.

    -
  • -
  • utils.insert_or_update(vector,item,field,cmpfun)

    -

    Like insert_sorted, but also assigns the item into -the vector cell if insertion didn't happen.

    -

    As an example, you can use this to set skill values:

    -
    -utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id')
    -
    -

    (For an explanation of new=true, see table assignment in the wrapper section)

    -
  • -
  • utils.prompt_yes_no(prompt, default)

    -

    Presents a yes/no prompt to the user. If default is not nil, -allows just pressing Enter to submit the default choice. -If the user enters 'abort', throws an error.

    -
  • -
  • utils.prompt_input(prompt, checkfun, quit_str)

    -

    Presents a prompt to input data, until a valid string is entered. -Once checkfun(input) returns true, ..., passes the values -through. If the user enters the quit_str (defaults to '~~~'), -throws an error.

    -
  • -
  • utils.check_number(text)

    -

    A prompt_input checkfun that verifies a number input.

    -
  • -
-
-
-

dumper

-

A third-party lua table dumper module from -http://lua-users.org/wiki/DataDumper. Defines one -function:

-
    -
  • dumper.DataDumper(value, varname, fastmode, ident, indent_step)

    -

    Returns value converted to a string. The indent_step -argument specifies the indentation step size in spaces. For -the other arguments see the original documentation link above.

    -
  • -
-
-
-

class

-

Implements a trivial single-inheritance class system.

-
    -
  • Foo = defclass(Foo[, ParentClass])

    -

    Defines or updates class Foo. The Foo = defclass(Foo) syntax -is needed so that when the module or script is reloaded, the -class identity will be preserved through the preservation of -global variable values.

    -

    The defclass function is defined as a stub in the global -namespace, and using it will auto-load the class module.

    -
  • -
  • Class.super

    -

    This class field is set by defclass to the parent class, and -allows a readable Class.super.method(self, ...) syntax for -calling superclass methods.

    -
  • -
  • Class.ATTRS { foo = xxx, bar = yyy }

    -

    Declares certain instance fields to be attributes, i.e. auto-initialized -from fields in the table used as the constructor argument. If omitted, -they are initialized with the default values specified in this declaration.

    -

    If the default value should be nil, use ATTRS { foo = DEFAULT_NIL }.

    -
  • -
  • new_obj = Class{ foo = arg, bar = arg, ... }

    -

    Calling the class as a function creates and initializes a new instance. -Initialization happens in this order:

    -
      -
    1. An empty instance table is created, and its metatable set.
    2. -
    3. The preinit method is called via invoke_before (see below) -with the table used as argument to the class. This method is intended -for validating and tweaking that argument table.
    4. -
    5. Declared ATTRS are initialized from the argument table or their default values.
    6. -
    7. The init method is called via invoke_after with the argument table. -This is the main constructor method.
    8. -
    9. The postinit method is called via invoke_after with the argument table. -Place code that should be called after the object is fully constructed here.
    10. -
    -
  • -
-

Predefined instance methods:

-
    -
  • instance:assign{ foo = xxx }

    -

    Assigns all values in the input table to the matching instance fields.

    -
  • -
  • instance:callback(method_name, [args...])

    -

    Returns a closure that invokes the specified method of the class, -properly passing in self, and optionally a number of initial arguments too. -The arguments given to the closure are appended to these.

    -
  • -
  • instance:invoke_before(method_name, args...)

    -

    Navigates the inheritance chain of the instance starting from the most specific -class, and invokes the specified method with the arguments if it is defined in -that specific class. Equivalent to the following definition in every class:

    -
    -function Class:invoke_before(method, ...)
    -  if rawget(Class, method) then
    -    rawget(Class, method)(self, ...)
    -  end
    -  Class.super.invoke_before(method, ...)
    -end
    -
    -
  • -
  • instance:invoke_after(method_name, args...)

    -

    Like invoke_before, only the method is called after the recursive call to super, -i.e. invocations happen in the parent to child order.

    -

    These two methods are inspired by the Common Lisp before and after methods, and -are intended for implementing similar protocols for certain things. The class -library itself uses them for constructors.

    -
  • -
-

To avoid confusion, these methods cannot be redefined.

-
-
-
-

Plugins

-

DFHack plugins may export native functions and events -to lua contexts. They are automatically imported by -mkmodule('plugins.<name>'); this means that a lua -module file is still necessary for require to read.

-

The following plugins have lua support.

-
-

burrows

-

Implements extended burrow manipulations.

-

Events:

-
    -
  • onBurrowRename.foo = function(burrow)

    -

    Emitted when a burrow might have been renamed either through -the game UI, or renameBurrow().

    -
  • -
  • onDigComplete.foo = function(job_type,pos,old_tiletype,new_tiletype,worker)

    -

    Emitted when a tile might have been dug out. Only tracked if the -auto-growing burrows feature is enabled.

    -
  • -
-

Native functions:

-
    -
  • renameBurrow(burrow,name)

    -

    Renames the burrow, emitting onBurrowRename and updating auto-grow state properly.

    -
  • -
  • findByName(burrow,name)

    -

    Finds a burrow by name, using the same rules as the plugin command line interface. -Namely, trailing '+' characters marking auto-grow burrows are ignored.

    -
  • -
  • copyUnits(target,source,enable)

    -

    Applies units from source burrow to target. The enable -parameter specifies if they are to be added or removed.

    -
  • -
  • copyTiles(target,source,enable)

    -

    Applies tiles from source burrow to target. The enable -parameter specifies if they are to be added or removed.

    -
  • -
  • setTilesByKeyword(target,keyword,enable)

    -

    Adds or removes tiles matching a predefined keyword. The keyword -set is the same as used by the command line.

    -
  • -
-

The lua module file also re-exports functions from dfhack.burrows.

-
-
-

sort

-

Does not export any native functions as of now. Instead, it -calls lua code to perform the actual ordering of list items.

-
-
-
-

Scripts

-

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.

-

If the first line of the script is a one-line comment, it is -used by the built-in ls and help commands.

-

NOTE: Scripts placed in subdirectories still can be accessed, but -do not clutter the ls 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. devel/lua-example.

-

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.

-

Arguments are passed in to the scripts via the ... built-in -quasi-variable; when the script is called by the DFHack core, -they are all guaranteed to be non-nil strings.

-

DFHack core invokes the scripts in the core context (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:

- -

Note that this function lets errors propagate to the caller.

-
-
- - diff --git a/LUA Api.rst b/LUA Api.rst deleted file mode 100644 index bf7ee45a..00000000 --- a/LUA Api.rst +++ /dev/null @@ -1,2020 +0,0 @@ -############## -DFHack Lua API -############## - -.. contents:: - -The current version of DFHack has extensive support for -the Lua scripting language, providing access to: - -1. Raw data structures used by the game. -2. Many C++ functions for high-level access to these - structures, and interaction with dfhack itself. -3. Some functions exported by C++ plugins. - -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++. - -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/... - - -========================= -DF data structure wrapper -========================= - -DF structures described by the xml files in library/xml are exported -to lua code as a tree of objects and functions under the ``df`` global, -which broadly maps to the ``df`` namespace in C++. - -**WARNING**: The wrapper provides almost raw access to the memory -of the game, so mistakes in manipulating objects are as likely to -crash the game as equivalent plain C++ code would be. E.g. NULL -pointer access is safely detected, but dangling pointers aren't. - -Objects managed by the wrapper can be broadly classified into the following groups: - -1. Typed object pointers (references). - - References represent objects in DF memory with a known type. - - In addition to fields and methods defined by the wrapped type, - every reference has some built-in properties and methods. - -2. Untyped pointers - - Represented as lightuserdata. - - In assignment to a pointer NULL can be represented either as - ``nil``, or a NULL lightuserdata; reading a NULL pointer field - returns ``nil``. - -3. Named types - - Objects in the ``df`` tree that represent identity of struct, class, - enum and bitfield types. They host nested named types, static - methods, builtin properties & methods, and, for enums and bitfields, - the bi-directional mapping between key names and values. - -4. The ``global`` object - - ``df.global`` corresponds to the ``df::global`` namespace, and - behaves as a mix between a named type and a reference, containing - both nested types and fields corresponding to global symbols. - -In addition to the ``global`` object and top-level types the ``df`` -global also contains a few global builtin utility functions. - -Typed object references -======================= - -The underlying primitive lua object is userdata with a metatable. -Every structured field access produces a new userdata instance. - -All typed objects have the following built-in features: - -* ``ref1 == ref2``, ``tostring(ref)`` - - References implement equality by type & pointer value, and string conversion. - -* ``pairs(ref)`` - - Returns an iterator for the sequence of actual C++ field names - and values. Fields are enumerated in memory order. Methods and - lua wrapper properties are not included in the iteration. - - **WARNING**: a few of the data structures (like ui_look_list) - contain unions with pointers to different types with vtables. - Using pairs on such structs is an almost sure way to crash with - an access violation. - -* ``ref._kind`` - - Returns one of: ``primitive``, ``struct``, ``container``, - or ``bitfield``, as appropriate for the referenced object. - -* ``ref._type`` - - Returns the named type object or a string that represents - the referenced object type. - -* ``ref:sizeof()`` - - Returns *size, address* - -* ``ref:new()`` - - Allocates a new instance of the same type, and copies data - from the current object. - -* ``ref:delete()`` - - Destroys the object with the C++ ``delete`` operator. - If destructor is not available, returns *false*. - - **WARNING**: the lua reference object remains as a dangling - pointer, like a raw C++ pointer would. - -* ``ref:assign(object)`` - - Assigns data from object to ref. Object must either be another - ref of a compatible type, or a lua table; in the latter case - special recursive assignment rules are applied. - -* ``ref:_displace(index[,step])`` - - Returns a new reference with the pointer adjusted by index*step. - Step defaults to the natural object size. - -Primitive references --------------------- - -References of the *_kind* ``'primitive'`` are used for objects -that don't fit any of the other reference types. Such -references can only appear as a value of a pointer field, -or as a result of calling the ``_field()`` method. - -They behave as structs with one field ``value`` of the right type. - -To make working with numeric buffers easier, they also allow -numeric indices. Note that other than excluding negative values -no bound checking is performed, since buffer length is not available. -Index 0 is equivalent to the ``value`` field. - - -Struct references ------------------ - -Struct references are used for class and struct objects. - -They implement the following features: - -* ``ref.field``, ``ref.field = value`` - - Valid fields of the structure may be accessed by subscript. - - Primitive typed fields, i.e. numbers & strings, are converted - to/from matching lua values. The value of a pointer is a reference - to the target, or nil/NULL. Complex types are represented by - a reference to the field within the structure; unless recursive - lua table assignment is used, such fields can only be read. - - **NOTE:** In case of inheritance, *superclass* fields have precedence - over the subclass, but fields shadowed in this way can still - be accessed as ``ref['subclasstype.field']``. - This shadowing order is necessary because vtable-based classes - are automatically exposed in their exact type, and the reverse - rule would make access to superclass fields unreliable. - -* ``ref._field(field)`` - - Returns a reference to a valid field. That is, unlike regular - subscript, it returns a reference to the field within the structure - even for primitive typed fields and pointers. - -* ``ref:vmethod(args...)`` - - Named virtual methods are also exposed, subject to the same - shadowing rules. - -* ``pairs(ref)`` - - Enumerates all real fields (but not methods) in memory - (= declaration) order. - -Container references --------------------- - -Containers represent vectors and arrays, possibly resizable. - -A container field can associate an enum to the container -reference, which allows accessing elements using string keys -instead of numerical indices. - -Implemented features: - -* ``ref._enum`` - - If the container has an associated enum, returns the matching - named type object. - -* ``#ref`` - - Returns the *length* of the container. - -* ``ref[index]`` - - Accesses the container element, using either a *0-based* numerical - index, or, if an enum is associated, a valid enum key string. - - Accessing an invalid index is an error, but some container types - may return a default value, or auto-resize instead for convenience. - Currently this relaxed mode is implemented by df-flagarray aka BitArray. - -* ``ref._field(index)`` - - Like with structs, returns a pointer to the array element, if possible. - Flag and bit arrays cannot return such pointer, so it fails with an error. - -* ``pairs(ref)``, ``ipairs(ref)`` - - If the container has no associated enum, both behave identically, - iterating over numerical indices in order. Otherwise, ipairs still - uses numbers, while pairs tries to substitute enum keys whenever - possible. - -* ``ref:resize(new_size)`` - - Resizes the container if supported, or fails with an error. - -* ``ref:insert(index,item)`` - - Inserts a new item at the specified index. To add at the end, - use ``#ref``, or just ``'#'`` as index. - -* ``ref:erase(index)`` - - Removes the element at the given valid index. - -Bitfield references -------------------- - -Bitfields behave like special fixed-size containers. -Consider them to be something in between structs and -fixed-size vectors. - -The ``_enum`` property points to the bitfield type. -Numerical indices correspond to the shift value, -and if a subfield occupies multiple bits, the -``ipairs`` order would have a gap. - -Since currently there is no API to allocate a bitfield -object fully in GC-managed lua heap, consider using the -lua table assignment feature outlined below in order to -pass bitfield values to dfhack API functions that need -them, e.g. ``matinfo:matches{metal=true}``. - - -Named types -=========== - -Named types are exposed in the ``df`` tree with names identical -to the C++ version, except for the ``::`` vs ``.`` difference. - -All types and the global object have the following features: - -* ``type._kind`` - - Evaluates to one of ``struct-type``, ``class-type``, ``enum-type``, - ``bitfield-type`` or ``global``. - -* ``type._identity`` - - Contains a lightuserdata pointing to the underlying - DFHack::type_instance object. - -Types excluding the global object also support: - -* ``type:sizeof()`` - - Returns the size of an object of the type. - -* ``type:new()`` - - Creates a new instance of an object of the type. - -* ``type:is_instance(object)`` - - Returns true if object is same or subclass type, or a reference - to an object of same or subclass type. It is permissible to pass - nil, NULL or non-wrapper value as object; in this case the - method returns nil. - -In addition to this, enum and bitfield types contain a -bi-directional mapping between key strings and values, and -also map ``_first_item`` and ``_last_item`` to the min and -max values. - -Struct and class types with instance-vector attribute in the -xml have a ``type.find(key)`` function that wraps the find -method provided in C++. - -Global functions -================ - -The ``df`` table itself contains the following functions and values: - -* ``NULL``, ``df.NULL`` - - Contains the NULL lightuserdata. - -* ``df.isnull(obj)`` - - Evaluates to true if obj is nil or NULL; false otherwise. - -* ``df.isvalid(obj[,allow_null])`` - - For supported objects returns one of ``type``, ``voidptr``, ``ref``. - - If *allow_null* is true, and obj is nil or NULL, returns ``null``. - - Otherwise returns *nil*. - -* ``df.sizeof(obj)`` - - For types and refs identical to ``obj:sizeof()``. - For lightuserdata returns *nil, address* - -* ``df.new(obj)``, ``df.delete(obj)``, ``df.assign(obj, obj2)`` - - Equivalent to using the matching methods of obj. - -* ``df._displace(obj,index[,step])`` - - For refs equivalent to the method, but also works with - lightuserdata (step is mandatory then). - -* ``df.is_instance(type,obj)`` - - Equivalent to the method, but also allows a reference as proxy for its type. - -* ``df.new(ptype[,count])`` - - Allocate a new instance, or an array of built-in types. - The ``ptype`` argument is a string from the following list: - ``string``, ``int8_t``, ``uint8_t``, ``int16_t``, ``uint16_t``, - ``int32_t``, ``uint32_t``, ``int64_t``, ``uint64_t``, ``bool``, - ``float``, ``double``. All of these except ``string`` can be - used with the count argument to allocate an array. - -* ``df.reinterpret_cast(type,ptr)`` - - Converts ptr to a ref of specified type. The type may be anything - acceptable to ``df.is_instance``. Ptr may be *nil*, a ref, - a lightuserdata, or a number. - - Returns *nil* if NULL, or a ref. - - -Recursive table assignment -========================== - -Recursive assignment is invoked when a lua table is assigned -to a C++ object or field, i.e. one of: - -* ``ref:assign{...}`` -* ``ref.field = {...}`` - -The general mode of operation is that all fields of the table -are assigned to the fields of the target structure, roughly -emulating the following code:: - - function rec_assign(ref,table) - for key,value in pairs(table) do - ref[key] = value - end - end - -Since assigning a table to a field using = invokes the same -process, it is recursive. - -There are however some variations to this process depending -on the type of the field being assigned to: - -1. If the table contains an ``assign`` field, it is - applied first, using the ``ref:assign(value)`` method. - It is never assigned as a usual field. - -2. When a table is assigned to a non-NULL pointer field - using the ``ref.field = {...}`` syntax, it is applied - to the target of the pointer instead. - - If the pointer is NULL, the table is checked for a ``new`` field: - - a. If it is *nil* or *false*, assignment fails with an error. - - b. If it is *true*, the pointer is initialized with a newly - allocated object of the declared target type of the pointer. - - c. Otherwise, ``table.new`` must be a named type, or an - object of a type compatible with the pointer. The pointer - is initialized with the result of calling ``table.new:new()``. - - After this auto-vivification process, assignment proceeds - as if the pointer wasn't NULL. - - Obviously, the ``new`` field inside the table is always skipped - during the actual per-field assignment processing. - -3. If the target of the assignment is a container, a separate - rule set is used: - - a. If the table contains neither ``assign`` nor ``resize`` - fields, it is interpreted as an ordinary *1-based* lua - array. The container is resized to the #-size of the - table, and elements are assigned in numeric order:: - - ref:resize(#table); - for i=1,#table do ref[i-1] = table[i] end - - b. Otherwise, ``resize`` must be *true*, *false*, or - an explicit number. If it is not false, the container - is resized. After that the usual struct-like 'pairs' - assignment is performed. - - In case ``resize`` is *true*, the size is computed - by scanning the table for the largest numeric key. - - This means that in order to reassign only one element of - a container using this system, it is necessary to use:: - - { resize=false, [idx]=value } - -Since nil inside a table is indistinguishable from missing key, -it is necessary to use ``df.NULL`` as a null pointer value. - -This system is intended as a way to define a nested object -tree using pure lua data structures, and then materialize it in -C++ memory in one go. Note that if pointer auto-vivification -is used, an error in the middle of the recursive walk would -not destroy any objects allocated in this way, so the user -should be prepared to catch the error and do the necessary -cleanup. - -========== -DFHack API -========== - -DFHack utility functions are placed in the ``dfhack`` global tree. - -Native utilities -================ - -Input & Output --------------- - -* ``dfhack.print(args...)`` - - Output tab-separated args as standard lua print would do, - but without a newline. - -* ``print(args...)``, ``dfhack.println(args...)`` - - A replacement of the standard library print function that - works with DFHack output infrastructure. - -* ``dfhack.printerr(args...)`` - - Same as println; intended for errors. Uses red color and logs to stderr.log. - -* ``dfhack.color([color])`` - - Sets the current output color. If color is *nil* or *-1*, resets to default. - Returns the previous color value. - -* ``dfhack.is_interactive()`` - - Checks if the thread can access the interactive console and returns *true* or *false*. - -* ``dfhack.lineedit([prompt[,history_filename]])`` - - If the thread owns the interactive console, shows a prompt - and returns the entered string. Otherwise returns *nil, error*. - - Depending on the context, this function may actually yield the - running coroutine and let the C++ code release the core suspend - lock. Using an explicit ``dfhack.with_suspend`` will prevent - this, forcing the function to block on input with lock held. - -* ``dfhack.interpreter([prompt[,history_filename[,env]]])`` - - Starts an interactive lua interpreter, using the specified prompt - string, global environment and command-line history file. - - If the interactive console is not accessible, returns *nil, error*. - - -Exception handling ------------------- - -* ``dfhack.error(msg[,level[,verbose]])`` - - Throws a dfhack exception object with location and stack trace. - The verbose parameter controls whether the trace is printed by default. - -* ``qerror(msg[,level])`` - - Calls ``dfhack.error()`` with ``verbose`` being *false*. Intended to - be used for user-caused errors in scripts, where stack traces are not - desirable. - -* ``dfhack.pcall(f[,args...])`` - - 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. - -* ``safecall(f[,args...])``, ``dfhack.safecall(f[,args...])`` - - Just like pcall, but also prints the error using printerr before - returning. Intended as a convenience function. - -* ``dfhack.saferesume(coroutine[,args...])`` - - Compares to coroutine.resume like dfhack.safecall vs pcall. - -* ``dfhack.exception`` - - Metatable of error objects used by dfhack. The objects have the - following properties: - - ``err.where`` - The location prefix string, or *nil*. - ``err.message`` - The base message string. - ``err.stacktrace`` - The stack trace string, or *nil*. - ``err.cause`` - A different exception object, or *nil*. - ``err.thread`` - The coroutine that has thrown the exception. - ``err.verbose`` - Boolean, or *nil*; specifies if where and stacktrace should be printed. - ``tostring(err)``, or ``err:tostring([verbose])`` - Converts the exception to string. - -* ``dfhack.exception.verbose`` - - The default value of the ``verbose`` argument of ``err:tostring()``. - - -Miscellaneous -------------- - -* ``dfhack.VERSION`` - - DFHack version string constant. - -* ``dfhack.curry(func,args...)``, or ``curry(func,args...)`` - - Returns a closure that invokes the function with args combined - both from the curry call and the closure call itself. I.e. - ``curry(func,a,b)(c,d)`` equals ``func(a,b,c,d)``. - - -Locking and finalization ------------------------- - -* ``dfhack.with_suspend(f[,args...])`` - - Calls ``f`` with arguments after grabbing the DF core suspend lock. - Suspending is necessary for accessing a consistent state of DF memory. - - Returned values and errors are propagated through after releasing - the lock. It is safe to nest suspends. - - Every thread is allowed only one suspend per DF frame, so it is best - to group operations together in one big critical section. A plugin - can choose to run all lua code inside a C++-side suspend lock. - -* ``dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])`` - - Invokes ``fn`` with ``args``, and after it returns or throws an - error calls ``cleanup_fn`` with ``cleanup_args``. Any return values from - ``fn`` are propagated, and errors are re-thrown. - - The ``num_cleanup_args`` integer specifies the number of ``cleanup_args``, - and the ``always`` boolean specifies if cleanup should be called in any case, - or only in case of an error. - -* ``dfhack.with_finalize(cleanup_fn,fn[,args...])`` - - Calls ``fn`` with arguments, then finalizes with ``cleanup_fn``. - Implemented using ``call_with_finalizer(0,true,...)``. - -* ``dfhack.with_onerror(cleanup_fn,fn[,args...])`` - - Calls ``fn`` with arguments, then finalizes with ``cleanup_fn`` on any thrown error. - Implemented using ``call_with_finalizer(0,false,...)``. - -* ``dfhack.with_temp_object(obj,fn[,args...])`` - - Calls ``fn(obj,args...)``, then finalizes with ``obj:delete()``. - - -Persistent configuration storage --------------------------------- - -This api is intended for storing configuration options in the world itself. -It probably should be restricted to data that is world-dependent. - -Entries are identified by a string ``key``, but it is also possible to manage -multiple entries with the same key; their identity is determined by ``entry_id``. -Every entry has a mutable string ``value``, and an array of 7 mutable ``ints``. - -* ``dfhack.persistent.get(key)``, ``entry:get()`` - - Retrieves a persistent config record with the given string key, - or refreshes an already retrieved entry. If there are multiple - entries with the same key, it is undefined which one is retrieved - by the first version of the call. - - Returns entry, or *nil* if not found. - -* ``dfhack.persistent.delete(key)``, ``entry:delete()`` - - Removes an existing entry. Returns *true* if succeeded. - -* ``dfhack.persistent.get_all(key[,match_prefix])`` - - Retrieves all entries with the same key, or starting with key..'/'. - Calling ``get_all('',true)`` will match all entries. - - If none found, returns nil; otherwise returns an array of entries. - -* ``dfhack.persistent.save({key=str1, ...}[,new])``, ``entry:save([new])`` - - Saves changes in an entry, or creates a new one. Passing true as - new forces creation of a new entry even if one already exists; - otherwise the existing one is simply updated. - Returns *entry, did_create_new* - -Since the data is hidden in data structures owned by the DF world, -and automatically stored in the save game, these save and retrieval -functions can just copy values in memory without doing any actual I/O. -However, currently every entry has a 180+-byte dead-weight overhead. - -Material info lookup --------------------- - -A material info record has fields: - -* ``type``, ``index``, ``material`` - - DF material code pair, and a reference to the material object. - -* ``mode`` - - One of ``'builtin'``, ``'inorganic'``, ``'plant'``, ``'creature'``. - -* ``inorganic``, ``plant``, ``creature`` - - If the material is of the matching type, contains a reference to the raw object. - -* ``figure`` - - For a specific creature material contains a ref to the historical figure. - -Functions: - -* ``dfhack.matinfo.decode(type,index)`` - - Looks up material info for the given number pair; if not found, returs *nil*. - -* ``....decode(matinfo)``, ``....decode(item)``, ``....decode(obj)`` - - Uses ``matinfo.type``/``matinfo.index``, item getter vmethods, - or ``obj.mat_type``/``obj.mat_index`` to get the code pair. - -* ``dfhack.matinfo.find(token[,token...])`` - - Looks up material by a token string, or a pre-split string token sequence. - -* ``dfhack.matinfo.getToken(...)``, ``info:getToken()`` - - Applies ``decode`` and constructs a string token. - -* ``info:toString([temperature[,named]])`` - - Returns the human-readable name at the given temperature. - -* ``info:getCraftClass()`` - - Returns the classification used for craft skills. - -* ``info:matches(obj)`` - - Checks if the material matches job_material_category or job_item. - Accept dfhack_material_category auto-assign table. - -C++ function wrappers -===================== - -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 -can be omitted. - -* ``dfhack.getOSType()`` - - Returns the OS type string from ``symbols.xml``. - -* ``dfhack.getDFVersion()`` - - Returns the DF version string from ``symbols.xml``. - -* ``dfhack.getDFPath()`` - - Returns the DF directory path. - -* ``dfhack.getHackPath()`` - - Returns the dfhack directory path, i.e. ``".../df/hack/"``. - -* ``dfhack.getTickCount()`` - - Returns the tick count in ms, exactly as DF ui uses. - -* ``dfhack.isWorldLoaded()`` - - Checks if the world is loaded. - -* ``dfhack.isMapLoaded()`` - - Checks if the world and map are loaded. - -* ``dfhack.TranslateName(name[,in_english,only_last_name])`` - - Convert a language_name or only the last name part to string. - -Gui module ----------- - -* ``dfhack.gui.getCurViewscreen([skip_dismissed])`` - - Returns the topmost viewscreen. If ``skip_dismissed`` is *true*, - ignores screens already marked to be removed. - -* ``dfhack.gui.getFocusString(viewscreen)`` - - Returns a string representation of the current focus position - in the ui. The string has a "screen/foo/bar/baz..." format. - -* ``dfhack.gui.getCurFocus([skip_dismissed])`` - - Returns the focus string of the current viewscreen. - -* ``dfhack.gui.getSelectedWorkshopJob([silent])`` - - When a job is selected in *'q'* mode, returns the job, else - prints error unless silent and returns *nil*. - -* ``dfhack.gui.getSelectedJob([silent])`` - - Returns the job selected in a workshop or unit/jobs screen. - -* ``dfhack.gui.getSelectedUnit([silent])`` - - Returns the unit selected via *'v'*, *'k'*, unit/jobs, or - a full-screen item view of a cage or suchlike. - -* ``dfhack.gui.getSelectedItem([silent])`` - - Returns the item selected via *'v'* ->inventory, *'k'*, *'t'*, or - a full-screen item view of a container. Note that in the - last case, the highlighted *contained item* is returned, not - the container itself. - -* ``dfhack.gui.getSelectedBuilding([silent])`` - - Returns the building selected via *'q'*, *'t'*, *'k'* or *'i'*. - -* ``dfhack.gui.showAnnouncement(text,color[,is_bright])`` - - Adds a regular announcement with given text, color, and brightness. - The is_bright boolean actually seems to invert the brightness. - -* ``dfhack.gui.showZoomAnnouncement(type,pos,text,color[,is_bright])`` - - Like above, but also specifies a position you can zoom to from the announcement menu. - -* ``dfhack.gui.showPopupAnnouncement(text,color[,is_bright])`` - - Pops up a titan-style modal announcement window. - -* ``dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])`` - - Uses the type to look up options from announcements.txt, and calls the - above operations accordingly. If enabled, pauses and zooms to position. - - -Job module ----------- - -* ``dfhack.job.cloneJobStruct(job)`` - - Creates a deep copy of the given job. - -* ``dfhack.job.printJobDetails(job)`` - - Prints info about the job. - -* ``dfhack.job.printItemDetails(jobitem,idx)`` - - Prints info about the job item. - -* ``dfhack.job.getHolder(job)`` - - Returns the building holding the job. - -* ``dfhack.job.getWorker(job)`` - - Returns the unit performing the job. - -* ``dfhack.job.checkBuildingsNow()`` - - Instructs the game to check buildings for jobs next frame and assign workers. - -* ``dfhack.job.checkDesignationsNow()`` - - Instructs the game to check designations for jobs next frame and assign workers. - -* ``dfhack.job.is_equal(job1,job2)`` - - Compares important fields in the job and nested item structures. - -* ``dfhack.job.is_item_equal(job_item1,job_item2)`` - - Compares important fields in the job item structures. - -* ``dfhack.job.listNewlyCreated(first_id)`` - - Returns the current value of ``df.global.job_next_id``, and - if there are any jobs with ``first_id <= id < job_next_id``, - a lua list containing them. - -Units module ------------- - -* ``dfhack.units.getPosition(unit)`` - - Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged. - -* ``dfhack.units.getContainer(unit)`` - - Returns the container (cage) item or *nil*. - -* ``dfhack.units.setNickname(unit,nick)`` - - Sets the unit's nickname properly. - -* ``dfhack.units.getVisibleName(unit)`` - - Returns the language_name object visible in game, accounting for false identities. - -* ``dfhack.units.getIdentity(unit)`` - - Returns the false identity of the unit if it has one, or *nil*. - -* ``dfhack.units.getNemesis(unit)`` - - Returns the nemesis record of the unit if it has one, or *nil*. - -* ``dfhack.units.isHidingCurse(unit)`` - - Checks if the unit hides improved attributes from its curse. - -* ``dfhack.units.getPhysicalAttrValue(unit, attr_type)`` -* ``dfhack.units.getMentalAttrValue(unit, attr_type)`` - - Computes the effective attribute value, including curse effect. - -* ``dfhack.units.isCrazed(unit)`` -* ``dfhack.units.isOpposedToLife(unit)`` -* ``dfhack.units.hasExtravision(unit)`` -* ``dfhack.units.isBloodsucker(unit)`` - - Simple checks of caste attributes that can be modified by curses. - -* ``dfhack.units.getMiscTrait(unit, type[, create])`` - - Finds (or creates if requested) a misc trait object with the given id. - -* ``dfhack.units.isDead(unit)`` - - The unit is completely dead and passive, or a ghost. - -* ``dfhack.units.isAlive(unit)`` - - The unit isn't dead or undead. - -* ``dfhack.units.isSane(unit)`` - - The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf. - -* ``dfhack.units.isDwarf(unit)`` - - The unit is of the correct race of the fortress. - -* ``dfhack.units.isCitizen(unit)`` - - The unit is an alive sane citizen of the fortress; wraps the - same checks the game uses to decide game-over by extinction. - -* ``dfhack.units.getAge(unit[,true_age])`` - - Returns the age of the unit in years as a floating-point value. - If ``true_age`` is true, ignores false identities. - -* ``dfhack.units.getNominalSkill(unit, skill[, use_rust])`` - - Retrieves the nominal skill level for the given unit. If ``use_rust`` - is *true*, subtracts the rust penalty. - -* ``dfhack.units.getEffectiveSkill(unit, skill)`` - - Computes the effective rating for the given skill, taking into account exhaustion, pain etc. - -* ``dfhack.units.computeMovementSpeed(unit)`` - - Computes number of frames * 100 it takes the unit to move in its current state of mind and body. - -* ``dfhack.units.getNoblePositions(unit)`` - - Returns a list of tables describing noble position assignments, or *nil*. - Every table has fields ``entity``, ``assignment`` and ``position``. - -* ``dfhack.units.getProfessionName(unit[,ignore_noble,plural])`` - - Retrieves the profession name using custom profession, noble assignments - or raws. The ``ignore_noble`` boolean disables the use of noble positions. - -* ``dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])`` - - Retrieves the profession name for the given race/caste using raws. - -* ``dfhack.units.getProfessionColor(unit[,ignore_noble])`` - - Retrieves the color associated with the profession, using noble assignments - or raws. The ``ignore_noble`` boolean disables the use of noble positions. - -* ``dfhack.units.getCasteProfessionColor(race,caste,prof_id)`` - - Retrieves the profession color for the given race/caste using raws. - - -Items module ------------- - -* ``dfhack.items.getPosition(item)`` - - Returns true *x,y,z* of the item, or *nil* if invalid; may be not equal to item.pos if in inventory. - -* ``dfhack.items.getDescription(item, type[, decorate])`` - - Returns the string description of the item, as produced by the getItemDescription - method. If decorate is true, also adds markings for quality and improvements. - -* ``dfhack.items.getGeneralRef(item, type)`` - - Searches for a general_ref with the given type. - -* ``dfhack.items.getSpecificRef(item, type)`` - - Searches for a specific_ref with the given type. - -* ``dfhack.items.getOwner(item)`` - - Returns the owner unit or *nil*. - -* ``dfhack.items.setOwner(item,unit)`` - - Replaces the owner of the item. If unit is *nil*, removes ownership. - Returns *false* in case of error. - -* ``dfhack.items.getContainer(item)`` - - Returns the container item or *nil*. - -* ``dfhack.items.getContainedItems(item)`` - - Returns a list of items contained in this one. - -* ``dfhack.items.moveToGround(item,pos)`` - - Move the item to the ground at position. Returns *false* if impossible. - -* ``dfhack.items.moveToContainer(item,container)`` - - Move the item to the container. Returns *false* if impossible. - -* ``dfhack.items.moveToBuilding(item,building,use_mode)`` - - Move the item to the building. Returns *false* if impossible. - -* ``dfhack.items.moveToInventory(item,unit,use_mode,body_part)`` - - Move the item to the unit inventory. Returns *false* if impossible. - -* ``dfhack.items.remove(item[, no_uncat])`` - - Removes the item, and marks it for garbage collection unless ``no_uncat`` is true. - -* ``dfhack.items.makeProjectile(item)`` - - Turns the item into a projectile, and returns the new object, or *nil* if impossible. - - -Maps module ------------ - -* ``dfhack.maps.getSize()`` - - Returns map size in blocks: *x, y, z* - -* ``dfhack.maps.getTileSize()`` - - Returns map size in tiles: *x, y, z* - -* ``dfhack.maps.getBlock(x,y,z)`` - - Returns a map block object for given x,y,z in local block coordinates. - -* ``dfhack.maps.isValidTilePos(coords)``, or isValidTilePos(x,y,z)`` - - Checks if the given df::coord or x,y,z in local tile coordinates are valid. - -* ``dfhack.maps.getTileBlock(coords)``, or ``getTileBlock(x,y,z)`` - - Returns a map block object for given df::coord or x,y,z in local tile coordinates. - -* ``dfhack.maps.ensureTileBlock(coords)``, or ``ensureTileBlock(x,y,z)`` - - Like ``getTileBlock``, but if the block is not allocated, try creating it. - -* ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)`` - - Returns the biome info struct for the given global map region. - -* ``dfhack.maps.enableBlockUpdates(block[,flow,temperature])`` - - Enables updates for liquid flow or temperature, unless already active. - -* ``dfhack.maps.spawnFlow(pos,type,mat_type,mat_index,dimension)`` - - Spawns a new flow (i.e. steam/mist/dust/etc) at the given pos, and with - the given parameters. Returns it, or *nil* if unsuccessful. - -* ``dfhack.maps.getGlobalInitFeature(index)`` - - Returns the global feature object with the given index. - -* ``dfhack.maps.getLocalInitFeature(region_coord2d,index)`` - - Returns the local feature object with the given region coords and index. - -* ``dfhack.maps.getTileBiomeRgn(coords)``, or ``getTileBiomeRgn(x,y,z)`` - - Returns *x, y* for use with ``getRegionBiome``. - -* ``dfhack.maps.canWalkBetween(pos1, pos2)`` - - Checks if a dwarf may be able to walk between the two tiles, - using a pathfinding cache maintained by the game. Note that - this cache is only updated when the game is unpaused, and thus - can get out of date if doors are forbidden or unforbidden, or - tools like liquids or tiletypes are used. It also cannot possibly - take into account anything that depends on the actual units, like - burrows, or the presence of invaders. - - -Burrows module --------------- - -* ``dfhack.burrows.findByName(name)`` - - Returns the burrow pointer or *nil*. - -* ``dfhack.burrows.clearUnits(burrow)`` - - Removes all units from the burrow. - -* ``dfhack.burrows.isAssignedUnit(burrow,unit)`` - - Checks if the unit is in the burrow. - -* ``dfhack.burrows.setAssignedUnit(burrow,unit,enable)`` - - Adds or removes the unit from the burrow. - -* ``dfhack.burrows.clearTiles(burrow)`` - - Removes all tiles from the burrow. - -* ``dfhack.burrows.listBlocks(burrow)`` - - Returns a table of map block pointers. - -* ``dfhack.burrows.isAssignedTile(burrow,tile_coord)`` - - Checks if the tile is in burrow. - -* ``dfhack.burrows.setAssignedTile(burrow,tile_coord,enable)`` - - Adds or removes the tile from the burrow. Returns *false* if invalid coords. - -* ``dfhack.burrows.isAssignedBlockTile(burrow,block,x,y)`` - - Checks if the tile within the block is in burrow. - -* ``dfhack.burrows.setAssignedBlockTile(burrow,block,x,y,enable)`` - - Adds or removes the tile from the burrow. Returns *false* if invalid coords. - - -Buildings module ----------------- - -* ``dfhack.buildings.setOwner(item,unit)`` - - Replaces the owner of the building. If unit is *nil*, removes ownership. - Returns *false* in case of error. - -* ``dfhack.buildings.getSize(building)`` - - Returns *width, height, centerx, centery*. - -* ``dfhack.buildings.findAtTile(pos)``, or ``findAtTile(x,y,z)`` - - Scans the buildings for the one located at the given tile. - Does not work on civzones. Warning: linear scan if the map - tile indicates there are buildings at it. - -* ``dfhack.buildings.findCivzonesAt(pos)``, or ``findCivzonesAt(x,y,z)`` - - Scans civzones, and returns a lua sequence of those that touch - the given tile, or *nil* if none. - -* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)`` - - Computes correct dimensions for the specified building type and orientation, - using width and height for flexible dimensions. - Returns *is_flexible, width, height, center_x, center_y*. - -* ``dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])`` - - Checks if the rectangle defined by ``pos`` and ``size``, and possibly extents, - can be used for placing a building. If ``change_extents`` is true, bad tiles - are removed from extents. If ``allow_occupied``, the occupancy test is skipped. - -* ``dfhack.buildings.countExtentTiles(extents,defval)`` - - Returns the number of tiles included by extents, or defval. - -* ``dfhack.buildings.containsTile(building, x, y[, room])`` - - Checks if the building contains the specified tile, either directly, or as room. - -* ``dfhack.buildings.hasSupport(pos,size)`` - - Checks if a bridge constructed at specified position would have - support from terrain, and thus won't collapse if retracted. - -Low-level building creation functions; - -* ``dfhack.buildings.allocInstance(pos, type, subtype, custom)`` - - Creates a new building instance of given type, subtype and custom type, - at specified position. Returns the object, or *nil* in case of an error. - -* ``dfhack.buildings.setSize(building, width, height, direction)`` - - Configures an object returned by ``allocInstance``, using specified - parameters wherever appropriate. If the building has fixed size along - any dimension, the corresponding input parameter will be ignored. - Returns *false* if the building cannot be placed, or *true, width, - height, rect_area, true_area*. Returned width and height are the - final values used by the building; true_area is less than rect_area - if any tiles were removed from designation. - -* ``dfhack.buildings.constructAbstract(building)`` - - Links a fully configured object created by ``allocInstance`` into the - world. The object must be an abstract building, i.e. a stockpile or civzone. - Returns *true*, or *false* if impossible. - -* ``dfhack.buildings.constructWithItems(building, items)`` - - Links a fully configured object created by ``allocInstance`` into the - world for construction, using a list of specific items as material. - Returns *true*, or *false* if impossible. - -* ``dfhack.buildings.constructWithFilters(building, job_items)`` - - Links a fully configured object created by ``allocInstance`` into the - world for construction, using a list of job_item filters as inputs. - Returns *true*, or *false* if impossible. Filter objects are claimed - and possibly destroyed in any case. - Use a negative ``quantity`` field value to auto-compute the amount - from the size of the building. - -* ``dfhack.buildings.deconstruct(building)`` - - Destroys the building, or queues a deconstruction job. - Returns *true* if the building was destroyed and deallocated immediately. - -More high-level functions are implemented in lua and can be loaded by -``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. - -Among them are: - -* ``dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)`` - - Returns a sequence of lua structures, describing input item filters - suitable for the specified building type, or *nil* if unknown or invalid. - The returned sequence is suitable for use as the ``job_items`` argument - of ``constructWithFilters``. - Uses tables defined in ``buildings.lua``. - - Argtable members ``material`` (the default name), ``bucket``, ``barrel``, - ``chain``, ``mechanism``, ``screw``, ``pipe``, ``anvil``, ``weapon`` are used to - augment the basic attributes with more detailed information if the - building has input items with the matching name (see the tables for naming details). - Note that it is impossible to *override* any properties this way, only supply those that - are not mentioned otherwise; one exception is that flags2.non_economic - is automatically cleared if an explicit material is specified. - -* ``dfhack.buildings.constructBuilding{...}`` - - Creates a building in one call, using options contained - in the argument table. Returns the building, or *nil, error*. - - **NOTE:** Despite the name, unless the building is abstract, - the function creates it in an 'unconstructed' stage, with - a queued in-game job that will actually construct it. I.e. - the function replicates programmatically what can be done - through the construct building menu in the game ui, except - that it does less environment constraint checking. - - The following options can be used: - - - ``pos = coordinates``, or ``x = ..., y = ..., z = ...`` - - Mandatory. Specifies the left upper corner of the building. - - - ``type = df.building_type.FOO, subtype = ..., custom = ...`` - - Mandatory. Specifies the type of the building. Obviously, subtype - and custom are only expected if the type requires them. - - - ``fields = { ... }`` - - Initializes fields of the building object after creation with ``df.assign``. - - - ``width = ..., height = ..., direction = ...`` - - Sets size and orientation of the building. If it is - fixed-size, specified dimensions are ignored. - - - ``full_rectangle = true`` - - For buildings like stockpiles or farm plots that can normally - accomodate individual tile exclusion, forces an error if any - tiles within the specified width*height are obstructed. - - - ``items = { item, item ... }``, or ``filters = { {...}, {...}... }`` - - Specifies explicit items or item filters to use in construction. - It is the job of the user to ensure they are correct for the building type. - - - ``abstract = true`` - - Specifies that the building is abstract and does not require construction. - Required for stockpiles and civzones; an error otherwise. - - - ``material = {...}, mechanism = {...}, ...`` - - If none of ``items``, ``filter``, or ``abstract`` is used, - the function uses ``getFiltersByType`` to compute the input - item filters, and passes the argument table through. If no filters - can be determined this way, ``constructBuilding`` throws an error. - - -Constructions module --------------------- - -* ``dfhack.constructions.designateNew(pos,type,item_type,mat_index)`` - - Designates a new construction at given position. If there already is - a planned but not completed construction there, changes its type. - Returns *true*, or *false* if obstructed. - Note that designated constructions are technically buildings. - -* ``dfhack.constructions.designateRemove(pos)``, or ``designateRemove(x,y,z)`` - - If there is a construction or a planned construction at the specified - coordinates, designates it for removal, or instantly cancels the planned one. - Returns *true, was_only_planned* if removed; or *false* if none found. - - -Screen API ----------- - -The screen module implements support for drawing to the tiled screen of the game. -Note that drawing only has any effect when done from callbacks, so it can only -be feasibly used in the core context. - -Basic painting functions: - -* ``dfhack.screen.getWindowSize()`` - - Returns *width, height* of the screen. - -* ``dfhack.screen.getMousePos()`` - - Returns *x,y* of the tile the mouse is over. - -* ``dfhack.screen.inGraphicsMode()`` - - Checks if [GRAPHICS:YES] was specified in init. - -* ``dfhack.screen.paintTile(pen,x,y[,char,tile])`` - - Paints a tile using given parameters. Pen is a table with following possible fields: - - ``ch`` - Provides the ordinary tile character, as either a 1-character string or a number. - Can be overridden with the ``char`` function parameter. - ``fg`` - Foreground color for the ordinary tile. Defaults to COLOR_GREY (7). - ``bg`` - Background color for the ordinary tile. Defaults to COLOR_BLACK (0). - ``bold`` - Bright/bold text flag. If *nil*, computed based on (fg & 8); fg is masked to 3 bits. - Otherwise should be *true/false*. - ``tile`` - Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt. - ``tile_color = true`` - Specifies that the tile should be shaded with *fg/bg*. - ``tile_fg, tile_bg`` - If specified, overrides *tile_color* and supplies shading colors directly. - - Returns *false* if coordinates out of bounds, or other error. - -* ``dfhack.screen.readTile(x,y)`` - - Retrieves the contents of the specified tile from the screen buffers. - Returns a pen, or *nil* if invalid or TrueType. - -* ``dfhack.screen.paintString(pen,x,y,text)`` - - Paints the string starting at *x,y*. Uses the string characters - in sequence to override the ``ch`` field of pen. - - Returns *true* if painting at least one character succeeded. - -* ``dfhack.screen.fillRect(pen,x1,y1,x2,y2)`` - - Fills the rectangle specified by the coordinates with the given pen. - Returns *true* if painting at least one character succeeded. - -* ``dfhack.screen.findGraphicsTile(pagename,x,y)`` - - Finds a tile from a graphics set (i.e. the raws used for creatures), - if in graphics mode and loaded. - - Returns: *tile, tile_grayscale*, or *nil* if not found. - The values can then be used for the *tile* field of *pen* structures. - -* ``dfhack.screen.clear()`` - - Fills the screen with blank background. - -* ``dfhack.screen.invalidate()`` - - Requests repaint of the screen by setting a flag. Unlike other - functions in this section, this may be used at any time. - -In order to actually be able to paint to the screen, it is necessary -to create and register a viewscreen (basically a modal dialog) with -the game. - -**NOTE**: As a matter of policy, in order to avoid user confusion, all -interface screens added by dfhack should bear the "DFHack" signature. - -Screens are managed with the following functions: - -* ``dfhack.screen.show(screen[,below])`` - - Displays the given screen, possibly placing it below a different one. - The screen must not be already shown. Returns *true* if success. - -* ``dfhack.screen.dismiss(screen[,to_first])`` - - Marks the screen to be removed when the game enters its event loop. - If ``to_first`` is *true*, all screens up to the first one will be deleted. - -* ``dfhack.screen.isDismissed(screen)`` - - Checks if the screen is already marked for removal. - -Apart from a native viewscreen object, these functions accept a table -as a screen. In this case, ``show`` creates a new native viewscreen -that delegates all processing to methods stored in that table. - -**NOTE**: Lua-implemented screens are only supported in the core context. - -Supported callbacks and fields are: - -* ``screen._native`` - - Initialized by ``show`` with a reference to the backing viewscreen - object, and removed again when the object is deleted. - -* ``function screen:onShow()`` - - Called by ``dfhack.screen.show`` if successful. - -* ``function screen:onDismiss()`` - - Called by ``dfhack.screen.dismiss`` if successful. - -* ``function screen:onDestroy()`` - - Called from the destructor when the viewscreen is deleted. - -* ``function screen:onResize(w, h)`` - - Called before ``onRender`` or ``onIdle`` when the window size has changed. - -* ``function screen:onRender()`` - - Called when the viewscreen should paint itself. This is the only context - where the above painting functions work correctly. - - If omitted, the screen is cleared; otherwise it should do that itself. - In order to make a see-through dialog, call ``self._native.parent:render()``. - -* ``function screen:onIdle()`` - - Called every frame when the screen is on top of the stack. - -* ``function screen:onHelp()`` - - Called when the help keybinding is activated (usually '?'). - -* ``function screen:onInput(keys)`` - - Called when keyboard or mouse events are available. - If any keys are pressed, the keys argument is a table mapping them to *true*. - Note that this refers to logical keybingings computed from real keys via - options; if multiple interpretations exist, the table will contain multiple keys. - - The table also may contain special keys: - - ``_STRING`` - Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience. - - ``_MOUSE_L, _MOUSE_R`` - If the left or right mouse button is pressed. - - If this method is omitted, the screen is dismissed on receival of the ``LEAVESCREEN`` key. - -* ``function screen:onGetSelectedUnit()`` -* ``function screen:onGetSelectedItem()`` -* ``function screen:onGetSelectedJob()`` -* ``function screen:onGetSelectedBuilding()`` - - Implement these to provide a return value for the matching - ``dfhack.gui.getSelected...`` function. - - -Internal API ------------- - -These functions are intended for the use by dfhack developers, -and are only documented here for completeness: - -* ``dfhack.internal.scripts`` - - The table used by ``dfhack.run_script()`` to give every script its own - global environment, persistent between calls to the script. - -* ``dfhack.internal.getAddress(name)`` - - Returns the global address ``name``, or *nil*. - -* ``dfhack.internal.setAddress(name, value)`` - - Sets the global address ``name``. Returns the value of ``getAddress`` before the change. - -* ``dfhack.internal.getVTable(name)`` - - Returns the pre-extracted vtable address ``name``, or *nil*. - -* ``dfhack.internal.getRebaseDelta()`` - - Returns the ASLR rebase offset of the DF executable. - -* ``dfhack.internal.getMemRanges()`` - - Returns a sequence of tables describing virtual memory ranges of the process. - -* ``dfhack.internal.patchMemory(dest,src,count)`` - - Like memmove below, but works even if dest is read-only memory, e.g. code. - If destination overlaps a completely invalid memory region, or another error - occurs, returns false. - -* ``dfhack.internal.memmove(dest,src,count)`` - - Wraps the standard memmove function. Accepts both numbers and refs as pointers. - -* ``dfhack.internal.memcmp(ptr1,ptr2,count)`` - - Wraps the standard memcmp function. - -* ``dfhack.internal.memscan(haystack,count,step,needle,nsize)`` - - Searches for ``needle`` of ``nsize`` bytes in ``haystack``, - using ``count`` steps of ``step`` bytes. - Returns: *step_idx, sum_idx, found_ptr*, or *nil* if not found. - -* ``dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])`` - - 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: *found_index*, or *nil* if end reached. - - -Core interpreter context -======================== - -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. - -Core context specific functions: - -* ``dfhack.is_core_context`` - - Boolean value; *true* in the core context. - -* ``dfhack.timeout(time,mode,callback)`` - - Arranges for the callback to be called once the specified - period of time passes. The ``mode`` argument specifies the - unit of time used, and may be one of ``'frames'`` (raw FPS), - ``'ticks'`` (unpaused FPS), ``'days'``, ``'months'``, - ``'years'`` (in-game time). All timers other than - ``'frames'`` are cancelled when the world is unloaded, - and cannot be queued until it is loaded again. - Returns the timer id, or *nil* if unsuccessful due to - world being unloaded. - -* ``dfhack.timeout_active(id[,new_callback])`` - - Returns the active callback with the given id, or *nil* - if inactive or nil id. If called with 2 arguments, replaces - the current callback with the given value, if still active. - Using ``timeout_active(id,nil)`` cancels the timer. - -* ``dfhack.onStateChange.foo = function(code)`` - - Event. Receives the same codes as plugin_onstatechange in C++. - - -Event type ----------- - -An event is a native object transparently wrapping a lua table, -and implementing a __call metamethod. When it is invoked, it loops -through the table with next and calls all contained values. -This is intended as an extensible way to add listeners. - -This type itself is available in any context, but only the -core context has the actual events defined by C++ code. - -Features: - -* ``dfhack.event.new()`` - - Creates a new instance of an event. - -* ``event[key] = function`` - - Sets the function as one of the listeners. Assign *nil* to remove it. - - **NOTE**: The ``df.NULL`` key is reserved for the use by - the C++ owner of the event; it is an error to try setting it. - -* ``#event`` - - Returns the number of non-nil listeners. - -* ``pairs(event)`` - - Iterates over all listeners in the table. - -* ``event(args...)`` - - Invokes all listeners contained in the event in an arbitrary - order using ``dfhack.safecall``. - - -=========== -Lua Modules -=========== - -DFHack sets up the lua interpreter so that the built-in ``require`` -function can be used to load shared lua code from hack/lua/. -The ``dfhack`` namespace reference itself may be obtained via -``require('dfhack')``, although it is initially created as a -global by C++ bootstrap code. - -The following module management functions are provided: - -* ``mkmodule(name)`` - - Creates an environment table for the module. Intended to be used as:: - - local _ENV = mkmodule('foo') - ... - return _ENV - - If called the second time, returns the same table; thus providing reload support. - -* ``reload(name)`` - - Reloads a previously ``require``-d module *"name"* from the file. - Intended as a help for module development. - -* ``dfhack.BASE_G`` - - 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. - -Global environment -================== - -A number of variables and functions are provided in the base global -environment by the mandatory init file dfhack.lua: - -* Color constants - - These are applicable both for ``dfhack.color()`` and color fields - in DF functions or structures: - - 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 - -* ``dfhack.onStateChange`` event codes - - Available only in the core context, as is the event itself: - - SC_WORLD_LOADED, SC_WORLD_UNLOADED, SC_MAP_LOADED, - SC_MAP_UNLOADED, SC_VIEWSCREEN_CHANGED, SC_CORE_INITIALIZED - -* Functions already described above - - safecall, qerror, mkmodule, reload - -* ``printall(obj)`` - - If the argument is a lua table or DF object reference, prints all fields. - -* ``copyall(obj)`` - - Returns a shallow copy of the table or reference as a lua table. - -* ``pos2xyz(obj)`` - - The object must have fields x, y and z. Returns them as 3 values. - If obj is *nil*, or x is -30000 (the usual marker for undefined - coordinates), returns *nil*. - -* ``xyz2pos(x,y,z)`` - - Returns a table with x, y and z as fields. - -* ``safe_index(obj,index...)`` - - Walks a sequence of dereferences, which may be represented by numbers or strings. - Returns *nil* if any of obj or indices is *nil*, or a numeric index is out of array bounds. - -utils -===== - -* ``utils.compare(a,b)`` - - Comparator function; returns *-1* if ab, *0* otherwise. - -* ``utils.compare_name(a,b)`` - - Comparator for names; compares empty string last. - -* ``utils.is_container(obj)`` - - Checks if obj is a container ref. - -* ``utils.make_index_sequence(start,end)`` - - Returns a lua sequence of numbers in start..end. - -* ``utils.make_sort_order(data, ordering)`` - - Computes a sorted permutation of objects in data, as a table of integer - indices into the data sequence. Uses ``data.n`` as input length - if present. - - The ordering argument is a sequence of ordering specs, represented - as lua tables with following possible fields: - - ord.key = *function(value)* - Computes comparison key from input data value. Not called on nil. - If omitted, the comparison key is the value itself. - ord.key_table = *function(data)* - Computes a key table from the data table in one go. - ord.compare = *function(a,b)* - Comparison function. Defaults to ``utils.compare`` above. - Called on non-nil keys; nil sorts last. - ord.nil_first = *true/false* - If true, nil keys are sorted first instead of last. - ord.reverse = *true/false* - If true, sort non-nil keys in descending order. - - For every comparison during sorting the specs are applied in - order until an unambiguous decision is reached. Sorting is stable. - - Example of sorting a sequence by field foo:: - - local spec = { key = function(v) return v.foo end } - local order = utils.make_sort_order(data, { spec }) - local output = {} - for i = 1,#order do output[i] = data[order[i]] end - - Separating the actual reordering of the sequence in this - way enables applying the same permutation to multiple arrays. - This function is used by the sort plugin. - -* ``utils.assign(tgt, src)`` - - Does a recursive assignment of src into tgt. - Uses ``df.assign`` if tgt is a native object ref; otherwise - recurses into lua tables. - -* ``utils.clone(obj, deep)`` - - 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. - -* ``utils.clone_with_default(obj, default, force)`` - - Copies the object, using the ``default`` lua table tree - as a guide to which values should be skipped as uninteresting. - The ``force`` argument makes it always return a non-*nil* value. - -* ``utils.sort_vector(vector,field,cmpfun)`` - - Sorts a native vector or lua sequence using the comparator function. - If ``field`` is not *nil*, applies the comparator to the field instead - of the whole object. - -* ``utils.binsearch(vector,key,field,cmpfun,min,max)`` - - Does a binary search in a native vector or lua sequence for - ``key``, using ``cmpfun`` and ``field`` like sort_vector. - If ``min`` and ``max`` are specified, they are used as the - search subrange bounds. - - If found, returns *item, true, idx*. Otherwise returns - *nil, false, insert_idx*, where *insert_idx* is the correct - insertion point. - -* ``utils.insert_sorted(vector,item,field,cmpfun)`` - - Does a binary search, and inserts item if not found. - Returns *did_insert, vector[idx], idx*. - -* ``utils.insert_or_update(vector,item,field,cmpfun)`` - - Like ``insert_sorted``, but also assigns the item into - the vector cell if insertion didn't happen. - - As an example, you can use this to set skill values:: - - utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id') - - (For an explanation of ``new=true``, see table assignment in the wrapper section) - -* ``utils.prompt_yes_no(prompt, default)`` - - Presents a yes/no prompt to the user. If ``default`` is not *nil*, - allows just pressing Enter to submit the default choice. - If the user enters ``'abort'``, throws an error. - -* ``utils.prompt_input(prompt, checkfun, quit_str)`` - - Presents a prompt to input data, until a valid string is entered. - Once ``checkfun(input)`` returns *true, ...*, passes the values - through. If the user enters the quit_str (defaults to ``'~~~'``), - throws an error. - -* ``utils.check_number(text)`` - - A ``prompt_input`` ``checkfun`` that verifies a number input. - -dumper -====== - -A third-party lua table dumper module from -http://lua-users.org/wiki/DataDumper. Defines one -function: - -* ``dumper.DataDumper(value, varname, fastmode, ident, indent_step)`` - - Returns ``value`` converted to a string. The ``indent_step`` - argument specifies the indentation step size in spaces. For - the other arguments see the original documentation link above. - -class -===== - -Implements a trivial single-inheritance class system. - -* ``Foo = defclass(Foo[, ParentClass])`` - - Defines or updates class Foo. The ``Foo = defclass(Foo)`` syntax - is needed so that when the module or script is reloaded, the - class identity will be preserved through the preservation of - global variable values. - - The ``defclass`` function is defined as a stub in the global - namespace, and using it will auto-load the class module. - -* ``Class.super`` - - This class field is set by defclass to the parent class, and - allows a readable ``Class.super.method(self, ...)`` syntax for - calling superclass methods. - -* ``Class.ATTRS { foo = xxx, bar = yyy }`` - - Declares certain instance fields to be attributes, i.e. auto-initialized - from fields in the table used as the constructor argument. If omitted, - they are initialized with the default values specified in this declaration. - - If the default value should be *nil*, use ``ATTRS { foo = DEFAULT_NIL }``. - -* ``new_obj = Class{ foo = arg, bar = arg, ... }`` - - Calling the class as a function creates and initializes a new instance. - Initialization happens in this order: - - 1. An empty instance table is created, and its metatable set. - 2. The ``preinit`` method is called via ``invoke_before`` (see below) - with the table used as argument to the class. This method is intended - for validating and tweaking that argument table. - 3. Declared ATTRS are initialized from the argument table or their default values. - 4. The ``init`` method is called via ``invoke_after`` with the argument table. - This is the main constructor method. - 5. The ``postinit`` method is called via ``invoke_after`` with the argument table. - Place code that should be called after the object is fully constructed here. - -Predefined instance methods: - -* ``instance:assign{ foo = xxx }`` - - Assigns all values in the input table to the matching instance fields. - -* ``instance:callback(method_name, [args...])`` - - Returns a closure that invokes the specified method of the class, - properly passing in self, and optionally a number of initial arguments too. - The arguments given to the closure are appended to these. - -* ``instance:invoke_before(method_name, args...)`` - - Navigates the inheritance chain of the instance starting from the most specific - class, and invokes the specified method with the arguments if it is defined in - that specific class. Equivalent to the following definition in every class:: - - function Class:invoke_before(method, ...) - if rawget(Class, method) then - rawget(Class, method)(self, ...) - end - Class.super.invoke_before(method, ...) - end - -* ``instance:invoke_after(method_name, args...)`` - - Like invoke_before, only the method is called after the recursive call to super, - i.e. invocations happen in the parent to child order. - - These two methods are inspired by the Common Lisp before and after methods, and - are intended for implementing similar protocols for certain things. The class - library itself uses them for constructors. - -To avoid confusion, these methods cannot be redefined. - - -======= -Plugins -======= - -DFHack plugins may export native functions and events -to lua contexts. They are automatically imported by -``mkmodule('plugins.')``; this means that a lua -module file is still necessary for ``require`` to read. - -The following plugins have lua support. - -burrows -======= - -Implements extended burrow manipulations. - -Events: - -* ``onBurrowRename.foo = function(burrow)`` - - Emitted when a burrow might have been renamed either through - the game UI, or ``renameBurrow()``. - -* ``onDigComplete.foo = function(job_type,pos,old_tiletype,new_tiletype,worker)`` - - Emitted when a tile might have been dug out. Only tracked if the - auto-growing burrows feature is enabled. - -Native functions: - -* ``renameBurrow(burrow,name)`` - - Renames the burrow, emitting ``onBurrowRename`` and updating auto-grow state properly. - -* ``findByName(burrow,name)`` - - Finds a burrow by name, using the same rules as the plugin command line interface. - Namely, trailing ``'+'`` characters marking auto-grow burrows are ignored. - -* ``copyUnits(target,source,enable)`` - - Applies units from ``source`` burrow to ``target``. The ``enable`` - parameter specifies if they are to be added or removed. - -* ``copyTiles(target,source,enable)`` - - Applies tiles from ``source`` burrow to ``target``. The ``enable`` - parameter specifies if they are to be added or removed. - -* ``setTilesByKeyword(target,keyword,enable)`` - - Adds or removes tiles matching a predefined keyword. The keyword - set is the same as used by the command line. - -The lua module file also re-exports functions from ``dfhack.burrows``. - -sort -==== - -Does not export any native functions as of now. Instead, it -calls lua code to perform the actual ordering of list items. - - -======= -Scripts -======= - -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. - -If the first line of the script is a one-line comment, it is -used by the built-in ``ls`` and ``help`` commands. - -**NOTE:** Scripts placed in subdirectories still can be accessed, but -do not clutter the ``ls`` 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. ``devel/lua-example``. - -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. - -Arguments are passed in to the scripts via the **...** built-in -quasi-variable; when the script is called by the DFHack core, -they are all guaranteed to be non-nil strings. - -DFHack core invokes the scripts in the *core context* (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: - -* ``dfhack.run_script(name[,args...])`` - - Run a lua script in hack/scripts/, as if it was started from dfhack command-line. - The ``name`` argument should be the name stem, as would be used on the command line. - -Note that this function lets errors propagate to the caller. diff --git a/Lua API.html b/Lua API.html new file mode 100644 index 00000000..047ef978 --- /dev/null +++ b/Lua API.html @@ -0,0 +1,2104 @@ + + + + + + +DFHack Lua API + + + +
+

DFHack Lua API

+ + +

The current version of DFHack has extensive support for +the Lua scripting language, providing access to:

+
    +
  1. Raw data structures used by the game.
  2. +
  3. Many C++ functions for high-level access to these +structures, and interaction with dfhack itself.
  4. +
  5. Some functions exported by C++ plugins.
  6. +
+

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++.

+

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/...

+
+

DF data structure wrapper

+

DF structures described by the xml files in library/xml are exported +to lua code as a tree of objects and functions under the df global, +which broadly maps to the df namespace in C++.

+

WARNING: The wrapper provides almost raw access to the memory +of the game, so mistakes in manipulating objects are as likely to +crash the game as equivalent plain C++ code would be. E.g. NULL +pointer access is safely detected, but dangling pointers aren't.

+

Objects managed by the wrapper can be broadly classified into the following groups:

+
    +
  1. Typed object pointers (references).

    +

    References represent objects in DF memory with a known type.

    +

    In addition to fields and methods defined by the wrapped type, +every reference has some built-in properties and methods.

    +
  2. +
  3. Untyped pointers

    +

    Represented as lightuserdata.

    +

    In assignment to a pointer NULL can be represented either as +nil, or a NULL lightuserdata; reading a NULL pointer field +returns nil.

    +
  4. +
  5. Named types

    +

    Objects in the df tree that represent identity of struct, class, +enum and bitfield types. They host nested named types, static +methods, builtin properties & methods, and, for enums and bitfields, +the bi-directional mapping between key names and values.

    +
  6. +
  7. The global object

    +

    df.global corresponds to the df::global namespace, and +behaves as a mix between a named type and a reference, containing +both nested types and fields corresponding to global symbols.

    +
  8. +
+

In addition to the global object and top-level types the df +global also contains a few global builtin utility functions.

+
+

Typed object references

+

The underlying primitive lua object is userdata with a metatable. +Every structured field access produces a new userdata instance.

+

All typed objects have the following built-in features:

+
    +
  • ref1 == ref2, tostring(ref)

    +

    References implement equality by type & pointer value, and string conversion.

    +
  • +
  • pairs(ref)

    +

    Returns an iterator for the sequence of actual C++ field names +and values. Fields are enumerated in memory order. Methods and +lua wrapper properties are not included in the iteration.

    +

    WARNING: a few of the data structures (like ui_look_list) +contain unions with pointers to different types with vtables. +Using pairs on such structs is an almost sure way to crash with +an access violation.

    +
  • +
  • ref._kind

    +

    Returns one of: primitive, struct, container, +or bitfield, as appropriate for the referenced object.

    +
  • +
  • ref._type

    +

    Returns the named type object or a string that represents +the referenced object type.

    +
  • +
  • ref:sizeof()

    +

    Returns size, address

    +
  • +
  • ref:new()

    +

    Allocates a new instance of the same type, and copies data +from the current object.

    +
  • +
  • ref:delete()

    +

    Destroys the object with the C++ delete operator. +If destructor is not available, returns false.

    +

    WARNING: the lua reference object remains as a dangling +pointer, like a raw C++ pointer would.

    +
  • +
  • ref:assign(object)

    +

    Assigns data from object to ref. Object must either be another +ref of a compatible type, or a lua table; in the latter case +special recursive assignment rules are applied.

    +
  • +
  • ref:_displace(index[,step])

    +

    Returns a new reference with the pointer adjusted by index*step. +Step defaults to the natural object size.

    +
  • +
+
+

Primitive references

+

References of the _kind 'primitive' are used for objects +that don't fit any of the other reference types. Such +references can only appear as a value of a pointer field, +or as a result of calling the _field() method.

+

They behave as structs with one field value of the right type.

+

To make working with numeric buffers easier, they also allow +numeric indices. Note that other than excluding negative values +no bound checking is performed, since buffer length is not available. +Index 0 is equivalent to the value field.

+
+
+

Struct references

+

Struct references are used for class and struct objects.

+

They implement the following features:

+
    +
  • ref.field, ref.field = value

    +

    Valid fields of the structure may be accessed by subscript.

    +

    Primitive typed fields, i.e. numbers & strings, are converted +to/from matching lua values. The value of a pointer is a reference +to the target, or nil/NULL. Complex types are represented by +a reference to the field within the structure; unless recursive +lua table assignment is used, such fields can only be read.

    +

    NOTE: In case of inheritance, superclass fields have precedence +over the subclass, but fields shadowed in this way can still +be accessed as ref['subclasstype.field']. +This shadowing order is necessary because vtable-based classes +are automatically exposed in their exact type, and the reverse +rule would make access to superclass fields unreliable.

    +
  • +
  • ref._field(field)

    +

    Returns a reference to a valid field. That is, unlike regular +subscript, it returns a reference to the field within the structure +even for primitive typed fields and pointers.

    +
  • +
  • ref:vmethod(args...)

    +

    Named virtual methods are also exposed, subject to the same +shadowing rules.

    +
  • +
  • pairs(ref)

    +

    Enumerates all real fields (but not methods) in memory +(= declaration) order.

    +
  • +
+
+
+

Container references

+

Containers represent vectors and arrays, possibly resizable.

+

A container field can associate an enum to the container +reference, which allows accessing elements using string keys +instead of numerical indices.

+

Implemented features:

+
    +
  • ref._enum

    +

    If the container has an associated enum, returns the matching +named type object.

    +
  • +
  • #ref

    +

    Returns the length of the container.

    +
  • +
  • ref[index]

    +

    Accesses the container element, using either a 0-based numerical +index, or, if an enum is associated, a valid enum key string.

    +

    Accessing an invalid index is an error, but some container types +may return a default value, or auto-resize instead for convenience. +Currently this relaxed mode is implemented by df-flagarray aka BitArray.

    +
  • +
  • ref._field(index)

    +

    Like with structs, returns a pointer to the array element, if possible. +Flag and bit arrays cannot return such pointer, so it fails with an error.

    +
  • +
  • pairs(ref), ipairs(ref)

    +

    If the container has no associated enum, both behave identically, +iterating over numerical indices in order. Otherwise, ipairs still +uses numbers, while pairs tries to substitute enum keys whenever +possible.

    +
  • +
  • ref:resize(new_size)

    +

    Resizes the container if supported, or fails with an error.

    +
  • +
  • ref:insert(index,item)

    +

    Inserts a new item at the specified index. To add at the end, +use #ref, or just '#' as index.

    +
  • +
  • ref:erase(index)

    +

    Removes the element at the given valid index.

    +
  • +
+
+
+

Bitfield references

+

Bitfields behave like special fixed-size containers. +Consider them to be something in between structs and +fixed-size vectors.

+

The _enum property points to the bitfield type. +Numerical indices correspond to the shift value, +and if a subfield occupies multiple bits, the +ipairs order would have a gap.

+

Since currently there is no API to allocate a bitfield +object fully in GC-managed lua heap, consider using the +lua table assignment feature outlined below in order to +pass bitfield values to dfhack API functions that need +them, e.g. matinfo:matches{metal=true}.

+
+
+
+

Named types

+

Named types are exposed in the df tree with names identical +to the C++ version, except for the :: vs . difference.

+

All types and the global object have the following features:

+
    +
  • type._kind

    +

    Evaluates to one of struct-type, class-type, enum-type, +bitfield-type or global.

    +
  • +
  • type._identity

    +

    Contains a lightuserdata pointing to the underlying +DFHack::type_instance object.

    +
  • +
+

Types excluding the global object also support:

+
    +
  • type:sizeof()

    +

    Returns the size of an object of the type.

    +
  • +
  • type:new()

    +

    Creates a new instance of an object of the type.

    +
  • +
  • type:is_instance(object)

    +

    Returns true if object is same or subclass type, or a reference +to an object of same or subclass type. It is permissible to pass +nil, NULL or non-wrapper value as object; in this case the +method returns nil.

    +
  • +
+

In addition to this, enum and bitfield types contain a +bi-directional mapping between key strings and values, and +also map _first_item and _last_item to the min and +max values.

+

Struct and class types with instance-vector attribute in the +xml have a type.find(key) function that wraps the find +method provided in C++.

+
+
+

Global functions

+

The df table itself contains the following functions and values:

+
    +
  • NULL, df.NULL

    +

    Contains the NULL lightuserdata.

    +
  • +
  • df.isnull(obj)

    +

    Evaluates to true if obj is nil or NULL; false otherwise.

    +
  • +
  • df.isvalid(obj[,allow_null])

    +

    For supported objects returns one of type, voidptr, ref.

    +

    If allow_null is true, and obj is nil or NULL, returns null.

    +

    Otherwise returns nil.

    +
  • +
  • df.sizeof(obj)

    +

    For types and refs identical to obj:sizeof(). +For lightuserdata returns nil, address

    +
  • +
  • df.new(obj), df.delete(obj), df.assign(obj, obj2)

    +

    Equivalent to using the matching methods of obj.

    +
  • +
  • df._displace(obj,index[,step])

    +

    For refs equivalent to the method, but also works with +lightuserdata (step is mandatory then).

    +
  • +
  • df.is_instance(type,obj)

    +

    Equivalent to the method, but also allows a reference as proxy for its type.

    +
  • +
  • df.new(ptype[,count])

    +

    Allocate a new instance, or an array of built-in types. +The ptype argument is a string from the following list: +string, int8_t, uint8_t, int16_t, uint16_t, +int32_t, uint32_t, int64_t, uint64_t, bool, +float, double. All of these except string can be +used with the count argument to allocate an array.

    +
  • +
  • df.reinterpret_cast(type,ptr)

    +

    Converts ptr to a ref of specified type. The type may be anything +acceptable to df.is_instance. Ptr may be nil, a ref, +a lightuserdata, or a number.

    +

    Returns nil if NULL, or a ref.

    +
  • +
+
+
+

Recursive table assignment

+

Recursive assignment is invoked when a lua table is assigned +to a C++ object or field, i.e. one of:

+
    +
  • ref:assign{...}
  • +
  • ref.field = {...}
  • +
+

The general mode of operation is that all fields of the table +are assigned to the fields of the target structure, roughly +emulating the following code:

+
+function rec_assign(ref,table)
+    for key,value in pairs(table) do
+        ref[key] = value
+    end
+end
+
+

Since assigning a table to a field using = invokes the same +process, it is recursive.

+

There are however some variations to this process depending +on the type of the field being assigned to:

+
    +
  1. If the table contains an assign field, it is +applied first, using the ref:assign(value) method. +It is never assigned as a usual field.

    +
  2. +
  3. When a table is assigned to a non-NULL pointer field +using the ref.field = {...} syntax, it is applied +to the target of the pointer instead.

    +

    If the pointer is NULL, the table is checked for a new field:

    +
      +
    1. If it is nil or false, assignment fails with an error.
    2. +
    3. If it is true, the pointer is initialized with a newly +allocated object of the declared target type of the pointer.
    4. +
    5. Otherwise, table.new must be a named type, or an +object of a type compatible with the pointer. The pointer +is initialized with the result of calling table.new:new().
    6. +
    +

    After this auto-vivification process, assignment proceeds +as if the pointer wasn't NULL.

    +

    Obviously, the new field inside the table is always skipped +during the actual per-field assignment processing.

    +
  4. +
  5. If the target of the assignment is a container, a separate +rule set is used:

    +
      +
    1. If the table contains neither assign nor resize +fields, it is interpreted as an ordinary 1-based lua +array. The container is resized to the #-size of the +table, and elements are assigned in numeric order:

      +
      +ref:resize(#table);
      +for i=1,#table do ref[i-1] = table[i] end
      +
      +
    2. +
    3. Otherwise, resize must be true, false, or +an explicit number. If it is not false, the container +is resized. After that the usual struct-like 'pairs' +assignment is performed.

      +

      In case resize is true, the size is computed +by scanning the table for the largest numeric key.

      +
    4. +
    +

    This means that in order to reassign only one element of +a container using this system, it is necessary to use:

    +
    +{ resize=false, [idx]=value }
    +
    +
  6. +
+

Since nil inside a table is indistinguishable from missing key, +it is necessary to use df.NULL as a null pointer value.

+

This system is intended as a way to define a nested object +tree using pure lua data structures, and then materialize it in +C++ memory in one go. Note that if pointer auto-vivification +is used, an error in the middle of the recursive walk would +not destroy any objects allocated in this way, so the user +should be prepared to catch the error and do the necessary +cleanup.

+
+
+
+

DFHack API

+

DFHack utility functions are placed in the dfhack global tree.

+
+

Native utilities

+
+

Input & Output

+
    +
  • dfhack.print(args...)

    +

    Output tab-separated args as standard lua print would do, +but without a newline.

    +
  • +
  • print(args...), dfhack.println(args...)

    +

    A replacement of the standard library print function that +works with DFHack output infrastructure.

    +
  • +
  • dfhack.printerr(args...)

    +

    Same as println; intended for errors. Uses red color and logs to stderr.log.

    +
  • +
  • dfhack.color([color])

    +

    Sets the current output color. If color is nil or -1, resets to default. +Returns the previous color value.

    +
  • +
  • dfhack.is_interactive()

    +

    Checks if the thread can access the interactive console and returns true or false.

    +
  • +
  • dfhack.lineedit([prompt[,history_filename]])

    +

    If the thread owns the interactive console, shows a prompt +and returns the entered string. Otherwise returns nil, error.

    +

    Depending on the context, this function may actually yield the +running coroutine and let the C++ code release the core suspend +lock. Using an explicit dfhack.with_suspend will prevent +this, forcing the function to block on input with lock held.

    +
  • +
  • dfhack.interpreter([prompt[,history_filename[,env]]])

    +

    Starts an interactive lua interpreter, using the specified prompt +string, global environment and command-line history file.

    +

    If the interactive console is not accessible, returns nil, error.

    +
  • +
+
+
+

Exception handling

+
    +
  • dfhack.error(msg[,level[,verbose]])

    +

    Throws a dfhack exception object with location and stack trace. +The verbose parameter controls whether the trace is printed by default.

    +
  • +
  • qerror(msg[,level])

    +

    Calls dfhack.error() with verbose being false. Intended to +be used for user-caused errors in scripts, where stack traces are not +desirable.

    +
  • +
  • dfhack.pcall(f[,args...])

    +

    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.

    +
  • +
  • safecall(f[,args...]), dfhack.safecall(f[,args...])

    +

    Just like pcall, but also prints the error using printerr before +returning. Intended as a convenience function.

    +
  • +
  • dfhack.saferesume(coroutine[,args...])

    +

    Compares to coroutine.resume like dfhack.safecall vs pcall.

    +
  • +
  • dfhack.exception

    +

    Metatable of error objects used by dfhack. The objects have the +following properties:

    +
    +
    err.where
    +

    The location prefix string, or nil.

    +
    +
    err.message
    +

    The base message string.

    +
    +
    err.stacktrace
    +

    The stack trace string, or nil.

    +
    +
    err.cause
    +

    A different exception object, or nil.

    +
    +
    err.thread
    +

    The coroutine that has thrown the exception.

    +
    +
    err.verbose
    +

    Boolean, or nil; specifies if where and stacktrace should be printed.

    +
    +
    tostring(err), or err:tostring([verbose])
    +

    Converts the exception to string.

    +
    +
    +
  • +
  • dfhack.exception.verbose

    +

    The default value of the verbose argument of err:tostring().

    +
  • +
+
+
+

Miscellaneous

+
    +
  • dfhack.VERSION

    +

    DFHack version string constant.

    +
  • +
  • dfhack.curry(func,args...), or curry(func,args...)

    +

    Returns a closure that invokes the function with args combined +both from the curry call and the closure call itself. I.e. +curry(func,a,b)(c,d) equals func(a,b,c,d).

    +
  • +
+
+
+

Locking and finalization

+
    +
  • dfhack.with_suspend(f[,args...])

    +

    Calls f with arguments after grabbing the DF core suspend lock. +Suspending is necessary for accessing a consistent state of DF memory.

    +

    Returned values and errors are propagated through after releasing +the lock. It is safe to nest suspends.

    +

    Every thread is allowed only one suspend per DF frame, so it is best +to group operations together in one big critical section. A plugin +can choose to run all lua code inside a C++-side suspend lock.

    +
  • +
  • dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])

    +

    Invokes fn with args, and after it returns or throws an +error calls cleanup_fn with cleanup_args. Any return values from +fn are propagated, and errors are re-thrown.

    +

    The num_cleanup_args integer specifies the number of cleanup_args, +and the always boolean specifies if cleanup should be called in any case, +or only in case of an error.

    +
  • +
  • dfhack.with_finalize(cleanup_fn,fn[,args...])

    +

    Calls fn with arguments, then finalizes with cleanup_fn. +Implemented using call_with_finalizer(0,true,...).

    +
  • +
  • dfhack.with_onerror(cleanup_fn,fn[,args...])

    +

    Calls fn with arguments, then finalizes with cleanup_fn on any thrown error. +Implemented using call_with_finalizer(0,false,...).

    +
  • +
  • dfhack.with_temp_object(obj,fn[,args...])

    +

    Calls fn(obj,args...), then finalizes with obj:delete().

    +
  • +
+
+
+

Persistent configuration storage

+

This api is intended for storing configuration options in the world itself. +It probably should be restricted to data that is world-dependent.

+

Entries are identified by a string key, but it is also possible to manage +multiple entries with the same key; their identity is determined by entry_id. +Every entry has a mutable string value, and an array of 7 mutable ints.

+
    +
  • dfhack.persistent.get(key), entry:get()

    +

    Retrieves a persistent config record with the given string key, +or refreshes an already retrieved entry. If there are multiple +entries with the same key, it is undefined which one is retrieved +by the first version of the call.

    +

    Returns entry, or nil if not found.

    +
  • +
  • dfhack.persistent.delete(key), entry:delete()

    +

    Removes an existing entry. Returns true if succeeded.

    +
  • +
  • dfhack.persistent.get_all(key[,match_prefix])

    +

    Retrieves all entries with the same key, or starting with key..'/'. +Calling get_all('',true) will match all entries.

    +

    If none found, returns nil; otherwise returns an array of entries.

    +
  • +
  • dfhack.persistent.save({key=str1, ...}[,new]), entry:save([new])

    +

    Saves changes in an entry, or creates a new one. Passing true as +new forces creation of a new entry even if one already exists; +otherwise the existing one is simply updated. +Returns entry, did_create_new

    +
  • +
+

Since the data is hidden in data structures owned by the DF world, +and automatically stored in the save game, these save and retrieval +functions can just copy values in memory without doing any actual I/O. +However, currently every entry has a 180+-byte dead-weight overhead.

+
+
+

Material info lookup

+

A material info record has fields:

+
    +
  • type, index, material

    +

    DF material code pair, and a reference to the material object.

    +
  • +
  • mode

    +

    One of 'builtin', 'inorganic', 'plant', 'creature'.

    +
  • +
  • inorganic, plant, creature

    +

    If the material is of the matching type, contains a reference to the raw object.

    +
  • +
  • figure

    +

    For a specific creature material contains a ref to the historical figure.

    +
  • +
+

Functions:

+
    +
  • dfhack.matinfo.decode(type,index)

    +

    Looks up material info for the given number pair; if not found, returs nil.

    +
  • +
  • ....decode(matinfo), ....decode(item), ....decode(obj)

    +

    Uses matinfo.type/matinfo.index, item getter vmethods, +or obj.mat_type/obj.mat_index to get the code pair.

    +
  • +
  • dfhack.matinfo.find(token[,token...])

    +

    Looks up material by a token string, or a pre-split string token sequence.

    +
  • +
  • dfhack.matinfo.getToken(...), info:getToken()

    +

    Applies decode and constructs a string token.

    +
  • +
  • info:toString([temperature[,named]])

    +

    Returns the human-readable name at the given temperature.

    +
  • +
  • info:getCraftClass()

    +

    Returns the classification used for craft skills.

    +
  • +
  • info:matches(obj)

    +

    Checks if the material matches job_material_category or job_item. +Accept dfhack_material_category auto-assign table.

    +
  • +
+
+
+
+

C++ function wrappers

+

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 +can be omitted.

+
    +
  • dfhack.getOSType()

    +

    Returns the OS type string from symbols.xml.

    +
  • +
  • dfhack.getDFVersion()

    +

    Returns the DF version string from symbols.xml.

    +
  • +
  • dfhack.getDFPath()

    +

    Returns the DF directory path.

    +
  • +
  • dfhack.getHackPath()

    +

    Returns the dfhack directory path, i.e. ".../df/hack/".

    +
  • +
  • dfhack.getTickCount()

    +

    Returns the tick count in ms, exactly as DF ui uses.

    +
  • +
  • dfhack.isWorldLoaded()

    +

    Checks if the world is loaded.

    +
  • +
  • dfhack.isMapLoaded()

    +

    Checks if the world and map are loaded.

    +
  • +
  • dfhack.TranslateName(name[,in_english,only_last_name])

    +

    Convert a language_name or only the last name part to string.

    +
  • +
+
+

Gui module

+
    +
  • dfhack.gui.getCurViewscreen([skip_dismissed])

    +

    Returns the topmost viewscreen. If skip_dismissed is true, +ignores screens already marked to be removed.

    +
  • +
  • dfhack.gui.getFocusString(viewscreen)

    +

    Returns a string representation of the current focus position +in the ui. The string has a "screen/foo/bar/baz..." format.

    +
  • +
  • dfhack.gui.getCurFocus([skip_dismissed])

    +

    Returns the focus string of the current viewscreen.

    +
  • +
  • dfhack.gui.getSelectedWorkshopJob([silent])

    +

    When a job is selected in 'q' mode, returns the job, else +prints error unless silent and returns nil.

    +
  • +
  • dfhack.gui.getSelectedJob([silent])

    +

    Returns the job selected in a workshop or unit/jobs screen.

    +
  • +
  • dfhack.gui.getSelectedUnit([silent])

    +

    Returns the unit selected via 'v', 'k', unit/jobs, or +a full-screen item view of a cage or suchlike.

    +
  • +
  • dfhack.gui.getSelectedItem([silent])

    +

    Returns the item selected via 'v' ->inventory, 'k', 't', or +a full-screen item view of a container. Note that in the +last case, the highlighted contained item is returned, not +the container itself.

    +
  • +
  • dfhack.gui.getSelectedBuilding([silent])

    +

    Returns the building selected via 'q', 't', 'k' or 'i'.

    +
  • +
  • dfhack.gui.showAnnouncement(text,color[,is_bright])

    +

    Adds a regular announcement with given text, color, and brightness. +The is_bright boolean actually seems to invert the brightness.

    +
  • +
  • dfhack.gui.showZoomAnnouncement(type,pos,text,color[,is_bright])

    +

    Like above, but also specifies a position you can zoom to from the announcement menu.

    +
  • +
  • dfhack.gui.showPopupAnnouncement(text,color[,is_bright])

    +

    Pops up a titan-style modal announcement window.

    +
  • +
  • dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])

    +

    Uses the type to look up options from announcements.txt, and calls the +above operations accordingly. If enabled, pauses and zooms to position.

    +
  • +
+
+
+

Job module

+
    +
  • dfhack.job.cloneJobStruct(job)

    +

    Creates a deep copy of the given job.

    +
  • +
  • dfhack.job.printJobDetails(job)

    +

    Prints info about the job.

    +
  • +
  • dfhack.job.printItemDetails(jobitem,idx)

    +

    Prints info about the job item.

    +
  • +
  • dfhack.job.getHolder(job)

    +

    Returns the building holding the job.

    +
  • +
  • dfhack.job.getWorker(job)

    +

    Returns the unit performing the job.

    +
  • +
  • dfhack.job.checkBuildingsNow()

    +

    Instructs the game to check buildings for jobs next frame and assign workers.

    +
  • +
  • dfhack.job.checkDesignationsNow()

    +

    Instructs the game to check designations for jobs next frame and assign workers.

    +
  • +
  • dfhack.job.is_equal(job1,job2)

    +

    Compares important fields in the job and nested item structures.

    +
  • +
  • dfhack.job.is_item_equal(job_item1,job_item2)

    +

    Compares important fields in the job item structures.

    +
  • +
  • dfhack.job.listNewlyCreated(first_id)

    +

    Returns the current value of df.global.job_next_id, and +if there are any jobs with first_id <= id < job_next_id, +a lua list containing them.

    +
  • +
+
+
+

Units module

+
    +
  • dfhack.units.getPosition(unit)

    +

    Returns true x,y,z of the unit, or nil if invalid; may be not equal to unit.pos if caged.

    +
  • +
  • dfhack.units.getContainer(unit)

    +

    Returns the container (cage) item or nil.

    +
  • +
  • dfhack.units.setNickname(unit,nick)

    +

    Sets the unit's nickname properly.

    +
  • +
  • dfhack.units.getVisibleName(unit)

    +

    Returns the language_name object visible in game, accounting for false identities.

    +
  • +
  • dfhack.units.getIdentity(unit)

    +

    Returns the false identity of the unit if it has one, or nil.

    +
  • +
  • dfhack.units.getNemesis(unit)

    +

    Returns the nemesis record of the unit if it has one, or nil.

    +
  • +
  • dfhack.units.isHidingCurse(unit)

    +

    Checks if the unit hides improved attributes from its curse.

    +
  • +
  • dfhack.units.getPhysicalAttrValue(unit, attr_type)

    +
  • +
  • dfhack.units.getMentalAttrValue(unit, attr_type)

    +

    Computes the effective attribute value, including curse effect.

    +
  • +
  • dfhack.units.isCrazed(unit)

    +
  • +
  • dfhack.units.isOpposedToLife(unit)

    +
  • +
  • dfhack.units.hasExtravision(unit)

    +
  • +
  • dfhack.units.isBloodsucker(unit)

    +

    Simple checks of caste attributes that can be modified by curses.

    +
  • +
  • dfhack.units.getMiscTrait(unit, type[, create])

    +

    Finds (or creates if requested) a misc trait object with the given id.

    +
  • +
  • dfhack.units.isDead(unit)

    +

    The unit is completely dead and passive, or a ghost.

    +
  • +
  • dfhack.units.isAlive(unit)

    +

    The unit isn't dead or undead.

    +
  • +
  • dfhack.units.isSane(unit)

    +

    The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.

    +
  • +
  • dfhack.units.isDwarf(unit)

    +

    The unit is of the correct race of the fortress.

    +
  • +
  • dfhack.units.isCitizen(unit)

    +

    The unit is an alive sane citizen of the fortress; wraps the +same checks the game uses to decide game-over by extinction.

    +
  • +
  • dfhack.units.getAge(unit[,true_age])

    +

    Returns the age of the unit in years as a floating-point value. +If true_age is true, ignores false identities.

    +
  • +
  • dfhack.units.getNominalSkill(unit, skill[, use_rust])

    +

    Retrieves the nominal skill level for the given unit. If use_rust +is true, subtracts the rust penalty.

    +
  • +
  • dfhack.units.getEffectiveSkill(unit, skill)

    +

    Computes the effective rating for the given skill, taking into account exhaustion, pain etc.

    +
  • +
  • dfhack.units.computeMovementSpeed(unit)

    +

    Computes number of frames * 100 it takes the unit to move in its current state of mind and body.

    +
  • +
  • dfhack.units.getNoblePositions(unit)

    +

    Returns a list of tables describing noble position assignments, or nil. +Every table has fields entity, assignment and position.

    +
  • +
  • dfhack.units.getProfessionName(unit[,ignore_noble,plural])

    +

    Retrieves the profession name using custom profession, noble assignments +or raws. The ignore_noble boolean disables the use of noble positions.

    +
  • +
  • dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])

    +

    Retrieves the profession name for the given race/caste using raws.

    +
  • +
  • dfhack.units.getProfessionColor(unit[,ignore_noble])

    +

    Retrieves the color associated with the profession, using noble assignments +or raws. The ignore_noble boolean disables the use of noble positions.

    +
  • +
  • dfhack.units.getCasteProfessionColor(race,caste,prof_id)

    +

    Retrieves the profession color for the given race/caste using raws.

    +
  • +
+
+
+

Items module

+
    +
  • dfhack.items.getPosition(item)

    +

    Returns true x,y,z of the item, or nil if invalid; may be not equal to item.pos if in inventory.

    +
  • +
  • dfhack.items.getDescription(item, type[, decorate])

    +

    Returns the string description of the item, as produced by the getItemDescription +method. If decorate is true, also adds markings for quality and improvements.

    +
  • +
  • dfhack.items.getGeneralRef(item, type)

    +

    Searches for a general_ref with the given type.

    +
  • +
  • dfhack.items.getSpecificRef(item, type)

    +

    Searches for a specific_ref with the given type.

    +
  • +
  • dfhack.items.getOwner(item)

    +

    Returns the owner unit or nil.

    +
  • +
  • dfhack.items.setOwner(item,unit)

    +

    Replaces the owner of the item. If unit is nil, removes ownership. +Returns false in case of error.

    +
  • +
  • dfhack.items.getContainer(item)

    +

    Returns the container item or nil.

    +
  • +
  • dfhack.items.getContainedItems(item)

    +

    Returns a list of items contained in this one.

    +
  • +
  • dfhack.items.moveToGround(item,pos)

    +

    Move the item to the ground at position. Returns false if impossible.

    +
  • +
  • dfhack.items.moveToContainer(item,container)

    +

    Move the item to the container. Returns false if impossible.

    +
  • +
  • dfhack.items.moveToBuilding(item,building,use_mode)

    +

    Move the item to the building. Returns false if impossible.

    +
  • +
  • dfhack.items.moveToInventory(item,unit,use_mode,body_part)

    +

    Move the item to the unit inventory. Returns false if impossible.

    +
  • +
  • dfhack.items.remove(item[, no_uncat])

    +

    Removes the item, and marks it for garbage collection unless no_uncat is true.

    +
  • +
  • dfhack.items.makeProjectile(item)

    +

    Turns the item into a projectile, and returns the new object, or nil if impossible.

    +
  • +
+
+
+

Maps module

+
    +
  • dfhack.maps.getSize()

    +

    Returns map size in blocks: x, y, z

    +
  • +
  • dfhack.maps.getTileSize()

    +

    Returns map size in tiles: x, y, z

    +
  • +
  • dfhack.maps.getBlock(x,y,z)

    +

    Returns a map block object for given x,y,z in local block coordinates.

    +
  • +
  • dfhack.maps.isValidTilePos(coords), or isValidTilePos(x,y,z)``

    +

    Checks if the given df::coord or x,y,z in local tile coordinates are valid.

    +
  • +
  • dfhack.maps.getTileBlock(coords), or getTileBlock(x,y,z)

    +

    Returns a map block object for given df::coord or x,y,z in local tile coordinates.

    +
  • +
  • dfhack.maps.ensureTileBlock(coords), or ensureTileBlock(x,y,z)

    +

    Like getTileBlock, but if the block is not allocated, try creating it.

    +
  • +
  • dfhack.maps.getRegionBiome(region_coord2d), or getRegionBiome(x,y)

    +

    Returns the biome info struct for the given global map region.

    +
  • +
  • dfhack.maps.enableBlockUpdates(block[,flow,temperature])

    +

    Enables updates for liquid flow or temperature, unless already active.

    +
  • +
  • dfhack.maps.spawnFlow(pos,type,mat_type,mat_index,dimension)

    +

    Spawns a new flow (i.e. steam/mist/dust/etc) at the given pos, and with +the given parameters. Returns it, or nil if unsuccessful.

    +
  • +
  • dfhack.maps.getGlobalInitFeature(index)

    +

    Returns the global feature object with the given index.

    +
  • +
  • dfhack.maps.getLocalInitFeature(region_coord2d,index)

    +

    Returns the local feature object with the given region coords and index.

    +
  • +
  • dfhack.maps.getTileBiomeRgn(coords), or getTileBiomeRgn(x,y,z)

    +

    Returns x, y for use with getRegionBiome.

    +
  • +
  • dfhack.maps.canWalkBetween(pos1, pos2)

    +

    Checks if a dwarf may be able to walk between the two tiles, +using a pathfinding cache maintained by the game. Note that +this cache is only updated when the game is unpaused, and thus +can get out of date if doors are forbidden or unforbidden, or +tools like liquids or tiletypes are used. It also cannot possibly +take into account anything that depends on the actual units, like +burrows, or the presence of invaders.

    +
  • +
+
+
+

Burrows module

+
    +
  • dfhack.burrows.findByName(name)

    +

    Returns the burrow pointer or nil.

    +
  • +
  • dfhack.burrows.clearUnits(burrow)

    +

    Removes all units from the burrow.

    +
  • +
  • dfhack.burrows.isAssignedUnit(burrow,unit)

    +

    Checks if the unit is in the burrow.

    +
  • +
  • dfhack.burrows.setAssignedUnit(burrow,unit,enable)

    +

    Adds or removes the unit from the burrow.

    +
  • +
  • dfhack.burrows.clearTiles(burrow)

    +

    Removes all tiles from the burrow.

    +
  • +
  • dfhack.burrows.listBlocks(burrow)

    +

    Returns a table of map block pointers.

    +
  • +
  • dfhack.burrows.isAssignedTile(burrow,tile_coord)

    +

    Checks if the tile is in burrow.

    +
  • +
  • dfhack.burrows.setAssignedTile(burrow,tile_coord,enable)

    +

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    +
  • +
  • dfhack.burrows.isAssignedBlockTile(burrow,block,x,y)

    +

    Checks if the tile within the block is in burrow.

    +
  • +
  • dfhack.burrows.setAssignedBlockTile(burrow,block,x,y,enable)

    +

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    +
  • +
+
+
+

Buildings module

+
    +
  • dfhack.buildings.setOwner(item,unit)

    +

    Replaces the owner of the building. If unit is nil, removes ownership. +Returns false in case of error.

    +
  • +
  • dfhack.buildings.getSize(building)

    +

    Returns width, height, centerx, centery.

    +
  • +
  • dfhack.buildings.findAtTile(pos), or findAtTile(x,y,z)

    +

    Scans the buildings for the one located at the given tile. +Does not work on civzones. Warning: linear scan if the map +tile indicates there are buildings at it.

    +
  • +
  • dfhack.buildings.findCivzonesAt(pos), or findCivzonesAt(x,y,z)

    +

    Scans civzones, and returns a lua sequence of those that touch +the given tile, or nil if none.

    +
  • +
  • dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)

    +

    Computes correct dimensions for the specified building type and orientation, +using width and height for flexible dimensions. +Returns is_flexible, width, height, center_x, center_y.

    +
  • +
  • dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])

    +

    Checks if the rectangle defined by pos and size, and possibly extents, +can be used for placing a building. If change_extents is true, bad tiles +are removed from extents. If allow_occupied, the occupancy test is skipped.

    +
  • +
  • dfhack.buildings.countExtentTiles(extents,defval)

    +

    Returns the number of tiles included by extents, or defval.

    +
  • +
  • dfhack.buildings.containsTile(building, x, y[, room])

    +

    Checks if the building contains the specified tile, either directly, or as room.

    +
  • +
  • dfhack.buildings.hasSupport(pos,size)

    +

    Checks if a bridge constructed at specified position would have +support from terrain, and thus won't collapse if retracted.

    +
  • +
+

Low-level building creation functions;

+
    +
  • dfhack.buildings.allocInstance(pos, type, subtype, custom)

    +

    Creates a new building instance of given type, subtype and custom type, +at specified position. Returns the object, or nil in case of an error.

    +
  • +
  • dfhack.buildings.setSize(building, width, height, direction)

    +

    Configures an object returned by allocInstance, using specified +parameters wherever appropriate. If the building has fixed size along +any dimension, the corresponding input parameter will be ignored. +Returns false if the building cannot be placed, or true, width, +height, rect_area, true_area. Returned width and height are the +final values used by the building; true_area is less than rect_area +if any tiles were removed from designation.

    +
  • +
  • dfhack.buildings.constructAbstract(building)

    +

    Links a fully configured object created by allocInstance into the +world. The object must be an abstract building, i.e. a stockpile or civzone. +Returns true, or false if impossible.

    +
  • +
  • dfhack.buildings.constructWithItems(building, items)

    +

    Links a fully configured object created by allocInstance into the +world for construction, using a list of specific items as material. +Returns true, or false if impossible.

    +
  • +
  • dfhack.buildings.constructWithFilters(building, job_items)

    +

    Links a fully configured object created by allocInstance into the +world for construction, using a list of job_item filters as inputs. +Returns true, or false if impossible. Filter objects are claimed +and possibly destroyed in any case. +Use a negative quantity field value to auto-compute the amount +from the size of the building.

    +
  • +
  • dfhack.buildings.deconstruct(building)

    +

    Destroys the building, or queues a deconstruction job. +Returns true if the building was destroyed and deallocated immediately.

    +
  • +
+

More high-level functions are implemented in lua and can be loaded by +require('dfhack.buildings'). See hack/lua/dfhack/buildings.lua.

+

Among them are:

+
    +
  • dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)

    +

    Returns a sequence of lua structures, describing input item filters +suitable for the specified building type, or nil if unknown or invalid. +The returned sequence is suitable for use as the job_items argument +of constructWithFilters. +Uses tables defined in buildings.lua.

    +

    Argtable members material (the default name), bucket, barrel, +chain, mechanism, screw, pipe, anvil, weapon are used to +augment the basic attributes with more detailed information if the +building has input items with the matching name (see the tables for naming details). +Note that it is impossible to override any properties this way, only supply those that +are not mentioned otherwise; one exception is that flags2.non_economic +is automatically cleared if an explicit material is specified.

    +
  • +
  • dfhack.buildings.constructBuilding{...}

    +

    Creates a building in one call, using options contained +in the argument table. Returns the building, or nil, error.

    +

    NOTE: Despite the name, unless the building is abstract, +the function creates it in an 'unconstructed' stage, with +a queued in-game job that will actually construct it. I.e. +the function replicates programmatically what can be done +through the construct building menu in the game ui, except +that it does less environment constraint checking.

    +

    The following options can be used:

    +
      +
    • pos = coordinates, or x = ..., y = ..., z = ...

      +

      Mandatory. Specifies the left upper corner of the building.

      +
    • +
    • type = df.building_type.FOO, subtype = ..., custom = ...

      +

      Mandatory. Specifies the type of the building. Obviously, subtype +and custom are only expected if the type requires them.

      +
    • +
    • fields = { ... }

      +

      Initializes fields of the building object after creation with df.assign.

      +
    • +
    • width = ..., height = ..., direction = ...

      +

      Sets size and orientation of the building. If it is +fixed-size, specified dimensions are ignored.

      +
    • +
    • full_rectangle = true

      +

      For buildings like stockpiles or farm plots that can normally +accomodate individual tile exclusion, forces an error if any +tiles within the specified width*height are obstructed.

      +
    • +
    • items = { item, item ... }, or filters = { {...}, {...}... }

      +

      Specifies explicit items or item filters to use in construction. +It is the job of the user to ensure they are correct for the building type.

      +
    • +
    • abstract = true

      +

      Specifies that the building is abstract and does not require construction. +Required for stockpiles and civzones; an error otherwise.

      +
    • +
    • material = {...}, mechanism = {...}, ...

      +

      If none of items, filter, or abstract is used, +the function uses getFiltersByType to compute the input +item filters, and passes the argument table through. If no filters +can be determined this way, constructBuilding throws an error.

      +
    • +
    +
  • +
+
+
+

Constructions module

+
    +
  • dfhack.constructions.designateNew(pos,type,item_type,mat_index)

    +

    Designates a new construction at given position. If there already is +a planned but not completed construction there, changes its type. +Returns true, or false if obstructed. +Note that designated constructions are technically buildings.

    +
  • +
  • dfhack.constructions.designateRemove(pos), or designateRemove(x,y,z)

    +

    If there is a construction or a planned construction at the specified +coordinates, designates it for removal, or instantly cancels the planned one. +Returns true, was_only_planned if removed; or false if none found.

    +
  • +
+
+
+

Screen API

+

The screen module implements support for drawing to the tiled screen of the game. +Note that drawing only has any effect when done from callbacks, so it can only +be feasibly used in the core context.

+

Basic painting functions:

+
    +
  • dfhack.screen.getWindowSize()

    +

    Returns width, height of the screen.

    +
  • +
  • dfhack.screen.getMousePos()

    +

    Returns x,y of the tile the mouse is over.

    +
  • +
  • dfhack.screen.inGraphicsMode()

    +

    Checks if [GRAPHICS:YES] was specified in init.

    +
  • +
  • dfhack.screen.paintTile(pen,x,y[,char,tile])

    +

    Paints a tile using given parameters. Pen is a table with following possible fields:

    +
    +
    ch
    +

    Provides the ordinary tile character, as either a 1-character string or a number. +Can be overridden with the char function parameter.

    +
    +
    fg
    +

    Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).

    +
    +
    bg
    +

    Background color for the ordinary tile. Defaults to COLOR_BLACK (0).

    +
    +
    bold
    +

    Bright/bold text flag. If nil, computed based on (fg & 8); fg is masked to 3 bits. +Otherwise should be true/false.

    +
    +
    tile
    +

    Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.

    +
    +
    tile_color = true
    +

    Specifies that the tile should be shaded with fg/bg.

    +
    +
    tile_fg, tile_bg
    +

    If specified, overrides tile_color and supplies shading colors directly.

    +
    +
    +

    Returns false if coordinates out of bounds, or other error.

    +
  • +
  • dfhack.screen.readTile(x,y)

    +

    Retrieves the contents of the specified tile from the screen buffers. +Returns a pen, or nil if invalid or TrueType.

    +
  • +
  • dfhack.screen.paintString(pen,x,y,text)

    +

    Paints the string starting at x,y. Uses the string characters +in sequence to override the ch field of pen.

    +

    Returns true if painting at least one character succeeded.

    +
  • +
  • dfhack.screen.fillRect(pen,x1,y1,x2,y2)

    +

    Fills the rectangle specified by the coordinates with the given pen. +Returns true if painting at least one character succeeded.

    +
  • +
  • dfhack.screen.findGraphicsTile(pagename,x,y)

    +

    Finds a tile from a graphics set (i.e. the raws used for creatures), +if in graphics mode and loaded.

    +

    Returns: tile, tile_grayscale, or nil if not found. +The values can then be used for the tile field of pen structures.

    +
  • +
  • dfhack.screen.clear()

    +

    Fills the screen with blank background.

    +
  • +
  • dfhack.screen.invalidate()

    +

    Requests repaint of the screen by setting a flag. Unlike other +functions in this section, this may be used at any time.

    +
  • +
+

In order to actually be able to paint to the screen, it is necessary +to create and register a viewscreen (basically a modal dialog) with +the game.

+

NOTE: As a matter of policy, in order to avoid user confusion, all +interface screens added by dfhack should bear the "DFHack" signature.

+

Screens are managed with the following functions:

+
    +
  • dfhack.screen.show(screen[,below])

    +

    Displays the given screen, possibly placing it below a different one. +The screen must not be already shown. Returns true if success.

    +
  • +
  • dfhack.screen.dismiss(screen[,to_first])

    +

    Marks the screen to be removed when the game enters its event loop. +If to_first is true, all screens up to the first one will be deleted.

    +
  • +
  • dfhack.screen.isDismissed(screen)

    +

    Checks if the screen is already marked for removal.

    +
  • +
+

Apart from a native viewscreen object, these functions accept a table +as a screen. In this case, show creates a new native viewscreen +that delegates all processing to methods stored in that table.

+

NOTE: Lua-implemented screens are only supported in the core context.

+

Supported callbacks and fields are:

+
    +
  • screen._native

    +

    Initialized by show with a reference to the backing viewscreen +object, and removed again when the object is deleted.

    +
  • +
  • function screen:onShow()

    +

    Called by dfhack.screen.show if successful.

    +
  • +
  • function screen:onDismiss()

    +

    Called by dfhack.screen.dismiss if successful.

    +
  • +
  • function screen:onDestroy()

    +

    Called from the destructor when the viewscreen is deleted.

    +
  • +
  • function screen:onResize(w, h)

    +

    Called before onRender or onIdle when the window size has changed.

    +
  • +
  • function screen:onRender()

    +

    Called when the viewscreen should paint itself. This is the only context +where the above painting functions work correctly.

    +

    If omitted, the screen is cleared; otherwise it should do that itself. +In order to make a see-through dialog, call self._native.parent:render().

    +
  • +
  • function screen:onIdle()

    +

    Called every frame when the screen is on top of the stack.

    +
  • +
  • function screen:onHelp()

    +

    Called when the help keybinding is activated (usually '?').

    +
  • +
  • function screen:onInput(keys)

    +

    Called when keyboard or mouse events are available. +If any keys are pressed, the keys argument is a table mapping them to true. +Note that this refers to logical keybingings computed from real keys via +options; if multiple interpretations exist, the table will contain multiple keys.

    +

    The table also may contain special keys:

    +
    +
    _STRING
    +

    Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience.

    +
    +
    _MOUSE_L, _MOUSE_R
    +

    If the left or right mouse button is pressed.

    +
    +
    +

    If this method is omitted, the screen is dismissed on receival of the LEAVESCREEN key.

    +
  • +
  • function screen:onGetSelectedUnit()

    +
  • +
  • function screen:onGetSelectedItem()

    +
  • +
  • function screen:onGetSelectedJob()

    +
  • +
  • function screen:onGetSelectedBuilding()

    +

    Implement these to provide a return value for the matching +dfhack.gui.getSelected... function.

    +
  • +
+
+
+

Internal API

+

These functions are intended for the use by dfhack developers, +and are only documented here for completeness:

+
    +
  • dfhack.internal.scripts

    +

    The table used by dfhack.run_script() to give every script its own +global environment, persistent between calls to the script.

    +
  • +
  • dfhack.internal.getAddress(name)

    +

    Returns the global address name, or nil.

    +
  • +
  • dfhack.internal.setAddress(name, value)

    +

    Sets the global address name. Returns the value of getAddress before the change.

    +
  • +
  • dfhack.internal.getVTable(name)

    +

    Returns the pre-extracted vtable address name, or nil.

    +
  • +
  • dfhack.internal.getRebaseDelta()

    +

    Returns the ASLR rebase offset of the DF executable.

    +
  • +
  • dfhack.internal.getMemRanges()

    +

    Returns a sequence of tables describing virtual memory ranges of the process.

    +
  • +
  • dfhack.internal.patchMemory(dest,src,count)

    +

    Like memmove below, but works even if dest is read-only memory, e.g. code. +If destination overlaps a completely invalid memory region, or another error +occurs, returns false.

    +
  • +
  • dfhack.internal.memmove(dest,src,count)

    +

    Wraps the standard memmove function. Accepts both numbers and refs as pointers.

    +
  • +
  • dfhack.internal.memcmp(ptr1,ptr2,count)

    +

    Wraps the standard memcmp function.

    +
  • +
  • dfhack.internal.memscan(haystack,count,step,needle,nsize)

    +

    Searches for needle of nsize bytes in haystack, +using count steps of step bytes. +Returns: step_idx, sum_idx, found_ptr, or nil if not found.

    +
  • +
  • dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])

    +

    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: found_index, or nil if end reached.

    +
  • +
+
+
+
+

Core interpreter context

+

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.

+

Core context specific functions:

+
    +
  • dfhack.is_core_context

    +

    Boolean value; true in the core context.

    +
  • +
  • dfhack.timeout(time,mode,callback)

    +

    Arranges for the callback to be called once the specified +period of time passes. The mode argument specifies the +unit of time used, and may be one of 'frames' (raw FPS), +'ticks' (unpaused FPS), 'days', 'months', +'years' (in-game time). All timers other than +'frames' are cancelled when the world is unloaded, +and cannot be queued until it is loaded again. +Returns the timer id, or nil if unsuccessful due to +world being unloaded.

    +
  • +
  • dfhack.timeout_active(id[,new_callback])

    +

    Returns the active callback with the given id, or nil +if inactive or nil id. If called with 2 arguments, replaces +the current callback with the given value, if still active. +Using timeout_active(id,nil) cancels the timer.

    +
  • +
  • dfhack.onStateChange.foo = function(code)

    +

    Event. Receives the same codes as plugin_onstatechange in C++.

    +
  • +
+
+

Event type

+

An event is a native object transparently wrapping a lua table, +and implementing a __call metamethod. When it is invoked, it loops +through the table with next and calls all contained values. +This is intended as an extensible way to add listeners.

+

This type itself is available in any context, but only the +core context has the actual events defined by C++ code.

+

Features:

+
    +
  • dfhack.event.new()

    +

    Creates a new instance of an event.

    +
  • +
  • event[key] = function

    +

    Sets the function as one of the listeners. Assign nil to remove it.

    +

    NOTE: The df.NULL key is reserved for the use by +the C++ owner of the event; it is an error to try setting it.

    +
  • +
  • #event

    +

    Returns the number of non-nil listeners.

    +
  • +
  • pairs(event)

    +

    Iterates over all listeners in the table.

    +
  • +
  • event(args...)

    +

    Invokes all listeners contained in the event in an arbitrary +order using dfhack.safecall.

    +
  • +
+
+
+
+
+

Lua Modules

+

DFHack sets up the lua interpreter so that the built-in require +function can be used to load shared lua code from hack/lua/. +The dfhack namespace reference itself may be obtained via +require('dfhack'), although it is initially created as a +global by C++ bootstrap code.

+

The following module management functions are provided:

+
    +
  • mkmodule(name)

    +

    Creates an environment table for the module. Intended to be used as:

    +
    +local _ENV = mkmodule('foo')
    +...
    +return _ENV
    +
    +

    If called the second time, returns the same table; thus providing reload support.

    +
  • +
  • reload(name)

    +

    Reloads a previously require-d module "name" from the file. +Intended as a help for module development.

    +
  • +
  • dfhack.BASE_G

    +

    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.

    +
  • +
+
+

Global environment

+

A number of variables and functions are provided in the base global +environment by the mandatory init file dfhack.lua:

+
    +
  • Color constants

    +

    These are applicable both for dfhack.color() and color fields +in DF functions or structures:

    +

    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

    +
  • +
  • dfhack.onStateChange event codes

    +

    Available only in the core context, as is the event itself:

    +

    SC_WORLD_LOADED, SC_WORLD_UNLOADED, SC_MAP_LOADED, +SC_MAP_UNLOADED, SC_VIEWSCREEN_CHANGED, SC_CORE_INITIALIZED

    +
  • +
  • Functions already described above

    +

    safecall, qerror, mkmodule, reload

    +
  • +
  • printall(obj)

    +

    If the argument is a lua table or DF object reference, prints all fields.

    +
  • +
  • copyall(obj)

    +

    Returns a shallow copy of the table or reference as a lua table.

    +
  • +
  • pos2xyz(obj)

    +

    The object must have fields x, y and z. Returns them as 3 values. +If obj is nil, or x is -30000 (the usual marker for undefined +coordinates), returns nil.

    +
  • +
  • xyz2pos(x,y,z)

    +

    Returns a table with x, y and z as fields.

    +
  • +
  • safe_index(obj,index...)

    +

    Walks a sequence of dereferences, which may be represented by numbers or strings. +Returns nil if any of obj or indices is nil, or a numeric index is out of array bounds.

    +
  • +
+
+
+

utils

+
    +
  • utils.compare(a,b)

    +

    Comparator function; returns -1 if a<b, 1 if a>b, 0 otherwise.

    +
  • +
  • utils.compare_name(a,b)

    +

    Comparator for names; compares empty string last.

    +
  • +
  • utils.is_container(obj)

    +

    Checks if obj is a container ref.

    +
  • +
  • utils.make_index_sequence(start,end)

    +

    Returns a lua sequence of numbers in start..end.

    +
  • +
  • utils.make_sort_order(data, ordering)

    +

    Computes a sorted permutation of objects in data, as a table of integer +indices into the data sequence. Uses data.n as input length +if present.

    +

    The ordering argument is a sequence of ordering specs, represented +as lua tables with following possible fields:

    +
    +
    ord.key = function(value)
    +

    Computes comparison key from input data value. Not called on nil. +If omitted, the comparison key is the value itself.

    +
    +
    ord.key_table = function(data)
    +

    Computes a key table from the data table in one go.

    +
    +
    ord.compare = function(a,b)
    +

    Comparison function. Defaults to utils.compare above. +Called on non-nil keys; nil sorts last.

    +
    +
    ord.nil_first = true/false
    +

    If true, nil keys are sorted first instead of last.

    +
    +
    ord.reverse = true/false
    +

    If true, sort non-nil keys in descending order.

    +
    +
    +

    For every comparison during sorting the specs are applied in +order until an unambiguous decision is reached. Sorting is stable.

    +

    Example of sorting a sequence by field foo:

    +
    +local spec = { key = function(v) return v.foo end }
    +local order = utils.make_sort_order(data, { spec })
    +local output = {}
    +for i = 1,#order do output[i] = data[order[i]] end
    +
    +

    Separating the actual reordering of the sequence in this +way enables applying the same permutation to multiple arrays. +This function is used by the sort plugin.

    +
  • +
  • utils.assign(tgt, src)

    +

    Does a recursive assignment of src into tgt. +Uses df.assign if tgt is a native object ref; otherwise +recurses into lua tables.

    +
  • +
  • utils.clone(obj, deep)

    +

    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.

    +
  • +
  • utils.clone_with_default(obj, default, force)

    +

    Copies the object, using the default lua table tree +as a guide to which values should be skipped as uninteresting. +The force argument makes it always return a non-nil value.

    +
  • +
  • utils.sort_vector(vector,field,cmpfun)

    +

    Sorts a native vector or lua sequence using the comparator function. +If field is not nil, applies the comparator to the field instead +of the whole object.

    +
  • +
  • utils.binsearch(vector,key,field,cmpfun,min,max)

    +

    Does a binary search in a native vector or lua sequence for +key, using cmpfun and field like sort_vector. +If min and max are specified, they are used as the +search subrange bounds.

    +

    If found, returns item, true, idx. Otherwise returns +nil, false, insert_idx, where insert_idx is the correct +insertion point.

    +
  • +
  • utils.insert_sorted(vector,item,field,cmpfun)

    +

    Does a binary search, and inserts item if not found. +Returns did_insert, vector[idx], idx.

    +
  • +
  • utils.insert_or_update(vector,item,field,cmpfun)

    +

    Like insert_sorted, but also assigns the item into +the vector cell if insertion didn't happen.

    +

    As an example, you can use this to set skill values:

    +
    +utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id')
    +
    +

    (For an explanation of new=true, see table assignment in the wrapper section)

    +
  • +
  • utils.prompt_yes_no(prompt, default)

    +

    Presents a yes/no prompt to the user. If default is not nil, +allows just pressing Enter to submit the default choice. +If the user enters 'abort', throws an error.

    +
  • +
  • utils.prompt_input(prompt, checkfun, quit_str)

    +

    Presents a prompt to input data, until a valid string is entered. +Once checkfun(input) returns true, ..., passes the values +through. If the user enters the quit_str (defaults to '~~~'), +throws an error.

    +
  • +
  • utils.check_number(text)

    +

    A prompt_input checkfun that verifies a number input.

    +
  • +
+
+
+

dumper

+

A third-party lua table dumper module from +http://lua-users.org/wiki/DataDumper. Defines one +function:

+
    +
  • dumper.DataDumper(value, varname, fastmode, ident, indent_step)

    +

    Returns value converted to a string. The indent_step +argument specifies the indentation step size in spaces. For +the other arguments see the original documentation link above.

    +
  • +
+
+
+

class

+

Implements a trivial single-inheritance class system.

+
    +
  • Foo = defclass(Foo[, ParentClass])

    +

    Defines or updates class Foo. The Foo = defclass(Foo) syntax +is needed so that when the module or script is reloaded, the +class identity will be preserved through the preservation of +global variable values.

    +

    The defclass function is defined as a stub in the global +namespace, and using it will auto-load the class module.

    +
  • +
  • Class.super

    +

    This class field is set by defclass to the parent class, and +allows a readable Class.super.method(self, ...) syntax for +calling superclass methods.

    +
  • +
  • Class.ATTRS { foo = xxx, bar = yyy }

    +

    Declares certain instance fields to be attributes, i.e. auto-initialized +from fields in the table used as the constructor argument. If omitted, +they are initialized with the default values specified in this declaration.

    +

    If the default value should be nil, use ATTRS { foo = DEFAULT_NIL }.

    +
  • +
  • new_obj = Class{ foo = arg, bar = arg, ... }

    +

    Calling the class as a function creates and initializes a new instance. +Initialization happens in this order:

    +
      +
    1. An empty instance table is created, and its metatable set.
    2. +
    3. The preinit method is called via invoke_before (see below) +with the table used as argument to the class. This method is intended +for validating and tweaking that argument table.
    4. +
    5. Declared ATTRS are initialized from the argument table or their default values.
    6. +
    7. The init method is called via invoke_after with the argument table. +This is the main constructor method.
    8. +
    9. The postinit method is called via invoke_after with the argument table. +Place code that should be called after the object is fully constructed here.
    10. +
    +
  • +
+

Predefined instance methods:

+
    +
  • instance:assign{ foo = xxx }

    +

    Assigns all values in the input table to the matching instance fields.

    +
  • +
  • instance:callback(method_name, [args...])

    +

    Returns a closure that invokes the specified method of the class, +properly passing in self, and optionally a number of initial arguments too. +The arguments given to the closure are appended to these.

    +
  • +
  • instance:invoke_before(method_name, args...)

    +

    Navigates the inheritance chain of the instance starting from the most specific +class, and invokes the specified method with the arguments if it is defined in +that specific class. Equivalent to the following definition in every class:

    +
    +function Class:invoke_before(method, ...)
    +  if rawget(Class, method) then
    +    rawget(Class, method)(self, ...)
    +  end
    +  Class.super.invoke_before(method, ...)
    +end
    +
    +
  • +
  • instance:invoke_after(method_name, args...)

    +

    Like invoke_before, only the method is called after the recursive call to super, +i.e. invocations happen in the parent to child order.

    +

    These two methods are inspired by the Common Lisp before and after methods, and +are intended for implementing similar protocols for certain things. The class +library itself uses them for constructors.

    +
  • +
+

To avoid confusion, these methods cannot be redefined.

+
+
+
+

Plugins

+

DFHack plugins may export native functions and events +to lua contexts. They are automatically imported by +mkmodule('plugins.<name>'); this means that a lua +module file is still necessary for require to read.

+

The following plugins have lua support.

+
+

burrows

+

Implements extended burrow manipulations.

+

Events:

+
    +
  • onBurrowRename.foo = function(burrow)

    +

    Emitted when a burrow might have been renamed either through +the game UI, or renameBurrow().

    +
  • +
  • onDigComplete.foo = function(job_type,pos,old_tiletype,new_tiletype,worker)

    +

    Emitted when a tile might have been dug out. Only tracked if the +auto-growing burrows feature is enabled.

    +
  • +
+

Native functions:

+
    +
  • renameBurrow(burrow,name)

    +

    Renames the burrow, emitting onBurrowRename and updating auto-grow state properly.

    +
  • +
  • findByName(burrow,name)

    +

    Finds a burrow by name, using the same rules as the plugin command line interface. +Namely, trailing '+' characters marking auto-grow burrows are ignored.

    +
  • +
  • copyUnits(target,source,enable)

    +

    Applies units from source burrow to target. The enable +parameter specifies if they are to be added or removed.

    +
  • +
  • copyTiles(target,source,enable)

    +

    Applies tiles from source burrow to target. The enable +parameter specifies if they are to be added or removed.

    +
  • +
  • setTilesByKeyword(target,keyword,enable)

    +

    Adds or removes tiles matching a predefined keyword. The keyword +set is the same as used by the command line.

    +
  • +
+

The lua module file also re-exports functions from dfhack.burrows.

+
+
+

sort

+

Does not export any native functions as of now. Instead, it +calls lua code to perform the actual ordering of list items.

+
+
+
+

Scripts

+

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.

+

If the first line of the script is a one-line comment, it is +used by the built-in ls and help commands.

+

NOTE: Scripts placed in subdirectories still can be accessed, but +do not clutter the ls 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. devel/lua-example.

+

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.

+

Arguments are passed in to the scripts via the ... built-in +quasi-variable; when the script is called by the DFHack core, +they are all guaranteed to be non-nil strings.

+

DFHack core invokes the scripts in the core context (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:

+
    +
  • dfhack.run_script(name[,args...])

    +

    Run a lua script in hack/scripts/, as if it was started from dfhack command-line. +The name argument should be the name stem, as would be used on the command line.

    +
  • +
+

Note that this function lets errors propagate to the caller.

+
+
+ + diff --git a/Lua API.rst b/Lua API.rst new file mode 100644 index 00000000..bf7ee45a --- /dev/null +++ b/Lua API.rst @@ -0,0 +1,2020 @@ +############## +DFHack Lua API +############## + +.. contents:: + +The current version of DFHack has extensive support for +the Lua scripting language, providing access to: + +1. Raw data structures used by the game. +2. Many C++ functions for high-level access to these + structures, and interaction with dfhack itself. +3. Some functions exported by C++ plugins. + +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++. + +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/... + + +========================= +DF data structure wrapper +========================= + +DF structures described by the xml files in library/xml are exported +to lua code as a tree of objects and functions under the ``df`` global, +which broadly maps to the ``df`` namespace in C++. + +**WARNING**: The wrapper provides almost raw access to the memory +of the game, so mistakes in manipulating objects are as likely to +crash the game as equivalent plain C++ code would be. E.g. NULL +pointer access is safely detected, but dangling pointers aren't. + +Objects managed by the wrapper can be broadly classified into the following groups: + +1. Typed object pointers (references). + + References represent objects in DF memory with a known type. + + In addition to fields and methods defined by the wrapped type, + every reference has some built-in properties and methods. + +2. Untyped pointers + + Represented as lightuserdata. + + In assignment to a pointer NULL can be represented either as + ``nil``, or a NULL lightuserdata; reading a NULL pointer field + returns ``nil``. + +3. Named types + + Objects in the ``df`` tree that represent identity of struct, class, + enum and bitfield types. They host nested named types, static + methods, builtin properties & methods, and, for enums and bitfields, + the bi-directional mapping between key names and values. + +4. The ``global`` object + + ``df.global`` corresponds to the ``df::global`` namespace, and + behaves as a mix between a named type and a reference, containing + both nested types and fields corresponding to global symbols. + +In addition to the ``global`` object and top-level types the ``df`` +global also contains a few global builtin utility functions. + +Typed object references +======================= + +The underlying primitive lua object is userdata with a metatable. +Every structured field access produces a new userdata instance. + +All typed objects have the following built-in features: + +* ``ref1 == ref2``, ``tostring(ref)`` + + References implement equality by type & pointer value, and string conversion. + +* ``pairs(ref)`` + + Returns an iterator for the sequence of actual C++ field names + and values. Fields are enumerated in memory order. Methods and + lua wrapper properties are not included in the iteration. + + **WARNING**: a few of the data structures (like ui_look_list) + contain unions with pointers to different types with vtables. + Using pairs on such structs is an almost sure way to crash with + an access violation. + +* ``ref._kind`` + + Returns one of: ``primitive``, ``struct``, ``container``, + or ``bitfield``, as appropriate for the referenced object. + +* ``ref._type`` + + Returns the named type object or a string that represents + the referenced object type. + +* ``ref:sizeof()`` + + Returns *size, address* + +* ``ref:new()`` + + Allocates a new instance of the same type, and copies data + from the current object. + +* ``ref:delete()`` + + Destroys the object with the C++ ``delete`` operator. + If destructor is not available, returns *false*. + + **WARNING**: the lua reference object remains as a dangling + pointer, like a raw C++ pointer would. + +* ``ref:assign(object)`` + + Assigns data from object to ref. Object must either be another + ref of a compatible type, or a lua table; in the latter case + special recursive assignment rules are applied. + +* ``ref:_displace(index[,step])`` + + Returns a new reference with the pointer adjusted by index*step. + Step defaults to the natural object size. + +Primitive references +-------------------- + +References of the *_kind* ``'primitive'`` are used for objects +that don't fit any of the other reference types. Such +references can only appear as a value of a pointer field, +or as a result of calling the ``_field()`` method. + +They behave as structs with one field ``value`` of the right type. + +To make working with numeric buffers easier, they also allow +numeric indices. Note that other than excluding negative values +no bound checking is performed, since buffer length is not available. +Index 0 is equivalent to the ``value`` field. + + +Struct references +----------------- + +Struct references are used for class and struct objects. + +They implement the following features: + +* ``ref.field``, ``ref.field = value`` + + Valid fields of the structure may be accessed by subscript. + + Primitive typed fields, i.e. numbers & strings, are converted + to/from matching lua values. The value of a pointer is a reference + to the target, or nil/NULL. Complex types are represented by + a reference to the field within the structure; unless recursive + lua table assignment is used, such fields can only be read. + + **NOTE:** In case of inheritance, *superclass* fields have precedence + over the subclass, but fields shadowed in this way can still + be accessed as ``ref['subclasstype.field']``. + This shadowing order is necessary because vtable-based classes + are automatically exposed in their exact type, and the reverse + rule would make access to superclass fields unreliable. + +* ``ref._field(field)`` + + Returns a reference to a valid field. That is, unlike regular + subscript, it returns a reference to the field within the structure + even for primitive typed fields and pointers. + +* ``ref:vmethod(args...)`` + + Named virtual methods are also exposed, subject to the same + shadowing rules. + +* ``pairs(ref)`` + + Enumerates all real fields (but not methods) in memory + (= declaration) order. + +Container references +-------------------- + +Containers represent vectors and arrays, possibly resizable. + +A container field can associate an enum to the container +reference, which allows accessing elements using string keys +instead of numerical indices. + +Implemented features: + +* ``ref._enum`` + + If the container has an associated enum, returns the matching + named type object. + +* ``#ref`` + + Returns the *length* of the container. + +* ``ref[index]`` + + Accesses the container element, using either a *0-based* numerical + index, or, if an enum is associated, a valid enum key string. + + Accessing an invalid index is an error, but some container types + may return a default value, or auto-resize instead for convenience. + Currently this relaxed mode is implemented by df-flagarray aka BitArray. + +* ``ref._field(index)`` + + Like with structs, returns a pointer to the array element, if possible. + Flag and bit arrays cannot return such pointer, so it fails with an error. + +* ``pairs(ref)``, ``ipairs(ref)`` + + If the container has no associated enum, both behave identically, + iterating over numerical indices in order. Otherwise, ipairs still + uses numbers, while pairs tries to substitute enum keys whenever + possible. + +* ``ref:resize(new_size)`` + + Resizes the container if supported, or fails with an error. + +* ``ref:insert(index,item)`` + + Inserts a new item at the specified index. To add at the end, + use ``#ref``, or just ``'#'`` as index. + +* ``ref:erase(index)`` + + Removes the element at the given valid index. + +Bitfield references +------------------- + +Bitfields behave like special fixed-size containers. +Consider them to be something in between structs and +fixed-size vectors. + +The ``_enum`` property points to the bitfield type. +Numerical indices correspond to the shift value, +and if a subfield occupies multiple bits, the +``ipairs`` order would have a gap. + +Since currently there is no API to allocate a bitfield +object fully in GC-managed lua heap, consider using the +lua table assignment feature outlined below in order to +pass bitfield values to dfhack API functions that need +them, e.g. ``matinfo:matches{metal=true}``. + + +Named types +=========== + +Named types are exposed in the ``df`` tree with names identical +to the C++ version, except for the ``::`` vs ``.`` difference. + +All types and the global object have the following features: + +* ``type._kind`` + + Evaluates to one of ``struct-type``, ``class-type``, ``enum-type``, + ``bitfield-type`` or ``global``. + +* ``type._identity`` + + Contains a lightuserdata pointing to the underlying + DFHack::type_instance object. + +Types excluding the global object also support: + +* ``type:sizeof()`` + + Returns the size of an object of the type. + +* ``type:new()`` + + Creates a new instance of an object of the type. + +* ``type:is_instance(object)`` + + Returns true if object is same or subclass type, or a reference + to an object of same or subclass type. It is permissible to pass + nil, NULL or non-wrapper value as object; in this case the + method returns nil. + +In addition to this, enum and bitfield types contain a +bi-directional mapping between key strings and values, and +also map ``_first_item`` and ``_last_item`` to the min and +max values. + +Struct and class types with instance-vector attribute in the +xml have a ``type.find(key)`` function that wraps the find +method provided in C++. + +Global functions +================ + +The ``df`` table itself contains the following functions and values: + +* ``NULL``, ``df.NULL`` + + Contains the NULL lightuserdata. + +* ``df.isnull(obj)`` + + Evaluates to true if obj is nil or NULL; false otherwise. + +* ``df.isvalid(obj[,allow_null])`` + + For supported objects returns one of ``type``, ``voidptr``, ``ref``. + + If *allow_null* is true, and obj is nil or NULL, returns ``null``. + + Otherwise returns *nil*. + +* ``df.sizeof(obj)`` + + For types and refs identical to ``obj:sizeof()``. + For lightuserdata returns *nil, address* + +* ``df.new(obj)``, ``df.delete(obj)``, ``df.assign(obj, obj2)`` + + Equivalent to using the matching methods of obj. + +* ``df._displace(obj,index[,step])`` + + For refs equivalent to the method, but also works with + lightuserdata (step is mandatory then). + +* ``df.is_instance(type,obj)`` + + Equivalent to the method, but also allows a reference as proxy for its type. + +* ``df.new(ptype[,count])`` + + Allocate a new instance, or an array of built-in types. + The ``ptype`` argument is a string from the following list: + ``string``, ``int8_t``, ``uint8_t``, ``int16_t``, ``uint16_t``, + ``int32_t``, ``uint32_t``, ``int64_t``, ``uint64_t``, ``bool``, + ``float``, ``double``. All of these except ``string`` can be + used with the count argument to allocate an array. + +* ``df.reinterpret_cast(type,ptr)`` + + Converts ptr to a ref of specified type. The type may be anything + acceptable to ``df.is_instance``. Ptr may be *nil*, a ref, + a lightuserdata, or a number. + + Returns *nil* if NULL, or a ref. + + +Recursive table assignment +========================== + +Recursive assignment is invoked when a lua table is assigned +to a C++ object or field, i.e. one of: + +* ``ref:assign{...}`` +* ``ref.field = {...}`` + +The general mode of operation is that all fields of the table +are assigned to the fields of the target structure, roughly +emulating the following code:: + + function rec_assign(ref,table) + for key,value in pairs(table) do + ref[key] = value + end + end + +Since assigning a table to a field using = invokes the same +process, it is recursive. + +There are however some variations to this process depending +on the type of the field being assigned to: + +1. If the table contains an ``assign`` field, it is + applied first, using the ``ref:assign(value)`` method. + It is never assigned as a usual field. + +2. When a table is assigned to a non-NULL pointer field + using the ``ref.field = {...}`` syntax, it is applied + to the target of the pointer instead. + + If the pointer is NULL, the table is checked for a ``new`` field: + + a. If it is *nil* or *false*, assignment fails with an error. + + b. If it is *true*, the pointer is initialized with a newly + allocated object of the declared target type of the pointer. + + c. Otherwise, ``table.new`` must be a named type, or an + object of a type compatible with the pointer. The pointer + is initialized with the result of calling ``table.new:new()``. + + After this auto-vivification process, assignment proceeds + as if the pointer wasn't NULL. + + Obviously, the ``new`` field inside the table is always skipped + during the actual per-field assignment processing. + +3. If the target of the assignment is a container, a separate + rule set is used: + + a. If the table contains neither ``assign`` nor ``resize`` + fields, it is interpreted as an ordinary *1-based* lua + array. The container is resized to the #-size of the + table, and elements are assigned in numeric order:: + + ref:resize(#table); + for i=1,#table do ref[i-1] = table[i] end + + b. Otherwise, ``resize`` must be *true*, *false*, or + an explicit number. If it is not false, the container + is resized. After that the usual struct-like 'pairs' + assignment is performed. + + In case ``resize`` is *true*, the size is computed + by scanning the table for the largest numeric key. + + This means that in order to reassign only one element of + a container using this system, it is necessary to use:: + + { resize=false, [idx]=value } + +Since nil inside a table is indistinguishable from missing key, +it is necessary to use ``df.NULL`` as a null pointer value. + +This system is intended as a way to define a nested object +tree using pure lua data structures, and then materialize it in +C++ memory in one go. Note that if pointer auto-vivification +is used, an error in the middle of the recursive walk would +not destroy any objects allocated in this way, so the user +should be prepared to catch the error and do the necessary +cleanup. + +========== +DFHack API +========== + +DFHack utility functions are placed in the ``dfhack`` global tree. + +Native utilities +================ + +Input & Output +-------------- + +* ``dfhack.print(args...)`` + + Output tab-separated args as standard lua print would do, + but without a newline. + +* ``print(args...)``, ``dfhack.println(args...)`` + + A replacement of the standard library print function that + works with DFHack output infrastructure. + +* ``dfhack.printerr(args...)`` + + Same as println; intended for errors. Uses red color and logs to stderr.log. + +* ``dfhack.color([color])`` + + Sets the current output color. If color is *nil* or *-1*, resets to default. + Returns the previous color value. + +* ``dfhack.is_interactive()`` + + Checks if the thread can access the interactive console and returns *true* or *false*. + +* ``dfhack.lineedit([prompt[,history_filename]])`` + + If the thread owns the interactive console, shows a prompt + and returns the entered string. Otherwise returns *nil, error*. + + Depending on the context, this function may actually yield the + running coroutine and let the C++ code release the core suspend + lock. Using an explicit ``dfhack.with_suspend`` will prevent + this, forcing the function to block on input with lock held. + +* ``dfhack.interpreter([prompt[,history_filename[,env]]])`` + + Starts an interactive lua interpreter, using the specified prompt + string, global environment and command-line history file. + + If the interactive console is not accessible, returns *nil, error*. + + +Exception handling +------------------ + +* ``dfhack.error(msg[,level[,verbose]])`` + + Throws a dfhack exception object with location and stack trace. + The verbose parameter controls whether the trace is printed by default. + +* ``qerror(msg[,level])`` + + Calls ``dfhack.error()`` with ``verbose`` being *false*. Intended to + be used for user-caused errors in scripts, where stack traces are not + desirable. + +* ``dfhack.pcall(f[,args...])`` + + 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. + +* ``safecall(f[,args...])``, ``dfhack.safecall(f[,args...])`` + + Just like pcall, but also prints the error using printerr before + returning. Intended as a convenience function. + +* ``dfhack.saferesume(coroutine[,args...])`` + + Compares to coroutine.resume like dfhack.safecall vs pcall. + +* ``dfhack.exception`` + + Metatable of error objects used by dfhack. The objects have the + following properties: + + ``err.where`` + The location prefix string, or *nil*. + ``err.message`` + The base message string. + ``err.stacktrace`` + The stack trace string, or *nil*. + ``err.cause`` + A different exception object, or *nil*. + ``err.thread`` + The coroutine that has thrown the exception. + ``err.verbose`` + Boolean, or *nil*; specifies if where and stacktrace should be printed. + ``tostring(err)``, or ``err:tostring([verbose])`` + Converts the exception to string. + +* ``dfhack.exception.verbose`` + + The default value of the ``verbose`` argument of ``err:tostring()``. + + +Miscellaneous +------------- + +* ``dfhack.VERSION`` + + DFHack version string constant. + +* ``dfhack.curry(func,args...)``, or ``curry(func,args...)`` + + Returns a closure that invokes the function with args combined + both from the curry call and the closure call itself. I.e. + ``curry(func,a,b)(c,d)`` equals ``func(a,b,c,d)``. + + +Locking and finalization +------------------------ + +* ``dfhack.with_suspend(f[,args...])`` + + Calls ``f`` with arguments after grabbing the DF core suspend lock. + Suspending is necessary for accessing a consistent state of DF memory. + + Returned values and errors are propagated through after releasing + the lock. It is safe to nest suspends. + + Every thread is allowed only one suspend per DF frame, so it is best + to group operations together in one big critical section. A plugin + can choose to run all lua code inside a C++-side suspend lock. + +* ``dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])`` + + Invokes ``fn`` with ``args``, and after it returns or throws an + error calls ``cleanup_fn`` with ``cleanup_args``. Any return values from + ``fn`` are propagated, and errors are re-thrown. + + The ``num_cleanup_args`` integer specifies the number of ``cleanup_args``, + and the ``always`` boolean specifies if cleanup should be called in any case, + or only in case of an error. + +* ``dfhack.with_finalize(cleanup_fn,fn[,args...])`` + + Calls ``fn`` with arguments, then finalizes with ``cleanup_fn``. + Implemented using ``call_with_finalizer(0,true,...)``. + +* ``dfhack.with_onerror(cleanup_fn,fn[,args...])`` + + Calls ``fn`` with arguments, then finalizes with ``cleanup_fn`` on any thrown error. + Implemented using ``call_with_finalizer(0,false,...)``. + +* ``dfhack.with_temp_object(obj,fn[,args...])`` + + Calls ``fn(obj,args...)``, then finalizes with ``obj:delete()``. + + +Persistent configuration storage +-------------------------------- + +This api is intended for storing configuration options in the world itself. +It probably should be restricted to data that is world-dependent. + +Entries are identified by a string ``key``, but it is also possible to manage +multiple entries with the same key; their identity is determined by ``entry_id``. +Every entry has a mutable string ``value``, and an array of 7 mutable ``ints``. + +* ``dfhack.persistent.get(key)``, ``entry:get()`` + + Retrieves a persistent config record with the given string key, + or refreshes an already retrieved entry. If there are multiple + entries with the same key, it is undefined which one is retrieved + by the first version of the call. + + Returns entry, or *nil* if not found. + +* ``dfhack.persistent.delete(key)``, ``entry:delete()`` + + Removes an existing entry. Returns *true* if succeeded. + +* ``dfhack.persistent.get_all(key[,match_prefix])`` + + Retrieves all entries with the same key, or starting with key..'/'. + Calling ``get_all('',true)`` will match all entries. + + If none found, returns nil; otherwise returns an array of entries. + +* ``dfhack.persistent.save({key=str1, ...}[,new])``, ``entry:save([new])`` + + Saves changes in an entry, or creates a new one. Passing true as + new forces creation of a new entry even if one already exists; + otherwise the existing one is simply updated. + Returns *entry, did_create_new* + +Since the data is hidden in data structures owned by the DF world, +and automatically stored in the save game, these save and retrieval +functions can just copy values in memory without doing any actual I/O. +However, currently every entry has a 180+-byte dead-weight overhead. + +Material info lookup +-------------------- + +A material info record has fields: + +* ``type``, ``index``, ``material`` + + DF material code pair, and a reference to the material object. + +* ``mode`` + + One of ``'builtin'``, ``'inorganic'``, ``'plant'``, ``'creature'``. + +* ``inorganic``, ``plant``, ``creature`` + + If the material is of the matching type, contains a reference to the raw object. + +* ``figure`` + + For a specific creature material contains a ref to the historical figure. + +Functions: + +* ``dfhack.matinfo.decode(type,index)`` + + Looks up material info for the given number pair; if not found, returs *nil*. + +* ``....decode(matinfo)``, ``....decode(item)``, ``....decode(obj)`` + + Uses ``matinfo.type``/``matinfo.index``, item getter vmethods, + or ``obj.mat_type``/``obj.mat_index`` to get the code pair. + +* ``dfhack.matinfo.find(token[,token...])`` + + Looks up material by a token string, or a pre-split string token sequence. + +* ``dfhack.matinfo.getToken(...)``, ``info:getToken()`` + + Applies ``decode`` and constructs a string token. + +* ``info:toString([temperature[,named]])`` + + Returns the human-readable name at the given temperature. + +* ``info:getCraftClass()`` + + Returns the classification used for craft skills. + +* ``info:matches(obj)`` + + Checks if the material matches job_material_category or job_item. + Accept dfhack_material_category auto-assign table. + +C++ function wrappers +===================== + +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 +can be omitted. + +* ``dfhack.getOSType()`` + + Returns the OS type string from ``symbols.xml``. + +* ``dfhack.getDFVersion()`` + + Returns the DF version string from ``symbols.xml``. + +* ``dfhack.getDFPath()`` + + Returns the DF directory path. + +* ``dfhack.getHackPath()`` + + Returns the dfhack directory path, i.e. ``".../df/hack/"``. + +* ``dfhack.getTickCount()`` + + Returns the tick count in ms, exactly as DF ui uses. + +* ``dfhack.isWorldLoaded()`` + + Checks if the world is loaded. + +* ``dfhack.isMapLoaded()`` + + Checks if the world and map are loaded. + +* ``dfhack.TranslateName(name[,in_english,only_last_name])`` + + Convert a language_name or only the last name part to string. + +Gui module +---------- + +* ``dfhack.gui.getCurViewscreen([skip_dismissed])`` + + Returns the topmost viewscreen. If ``skip_dismissed`` is *true*, + ignores screens already marked to be removed. + +* ``dfhack.gui.getFocusString(viewscreen)`` + + Returns a string representation of the current focus position + in the ui. The string has a "screen/foo/bar/baz..." format. + +* ``dfhack.gui.getCurFocus([skip_dismissed])`` + + Returns the focus string of the current viewscreen. + +* ``dfhack.gui.getSelectedWorkshopJob([silent])`` + + When a job is selected in *'q'* mode, returns the job, else + prints error unless silent and returns *nil*. + +* ``dfhack.gui.getSelectedJob([silent])`` + + Returns the job selected in a workshop or unit/jobs screen. + +* ``dfhack.gui.getSelectedUnit([silent])`` + + Returns the unit selected via *'v'*, *'k'*, unit/jobs, or + a full-screen item view of a cage or suchlike. + +* ``dfhack.gui.getSelectedItem([silent])`` + + Returns the item selected via *'v'* ->inventory, *'k'*, *'t'*, or + a full-screen item view of a container. Note that in the + last case, the highlighted *contained item* is returned, not + the container itself. + +* ``dfhack.gui.getSelectedBuilding([silent])`` + + Returns the building selected via *'q'*, *'t'*, *'k'* or *'i'*. + +* ``dfhack.gui.showAnnouncement(text,color[,is_bright])`` + + Adds a regular announcement with given text, color, and brightness. + The is_bright boolean actually seems to invert the brightness. + +* ``dfhack.gui.showZoomAnnouncement(type,pos,text,color[,is_bright])`` + + Like above, but also specifies a position you can zoom to from the announcement menu. + +* ``dfhack.gui.showPopupAnnouncement(text,color[,is_bright])`` + + Pops up a titan-style modal announcement window. + +* ``dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])`` + + Uses the type to look up options from announcements.txt, and calls the + above operations accordingly. If enabled, pauses and zooms to position. + + +Job module +---------- + +* ``dfhack.job.cloneJobStruct(job)`` + + Creates a deep copy of the given job. + +* ``dfhack.job.printJobDetails(job)`` + + Prints info about the job. + +* ``dfhack.job.printItemDetails(jobitem,idx)`` + + Prints info about the job item. + +* ``dfhack.job.getHolder(job)`` + + Returns the building holding the job. + +* ``dfhack.job.getWorker(job)`` + + Returns the unit performing the job. + +* ``dfhack.job.checkBuildingsNow()`` + + Instructs the game to check buildings for jobs next frame and assign workers. + +* ``dfhack.job.checkDesignationsNow()`` + + Instructs the game to check designations for jobs next frame and assign workers. + +* ``dfhack.job.is_equal(job1,job2)`` + + Compares important fields in the job and nested item structures. + +* ``dfhack.job.is_item_equal(job_item1,job_item2)`` + + Compares important fields in the job item structures. + +* ``dfhack.job.listNewlyCreated(first_id)`` + + Returns the current value of ``df.global.job_next_id``, and + if there are any jobs with ``first_id <= id < job_next_id``, + a lua list containing them. + +Units module +------------ + +* ``dfhack.units.getPosition(unit)`` + + Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged. + +* ``dfhack.units.getContainer(unit)`` + + Returns the container (cage) item or *nil*. + +* ``dfhack.units.setNickname(unit,nick)`` + + Sets the unit's nickname properly. + +* ``dfhack.units.getVisibleName(unit)`` + + Returns the language_name object visible in game, accounting for false identities. + +* ``dfhack.units.getIdentity(unit)`` + + Returns the false identity of the unit if it has one, or *nil*. + +* ``dfhack.units.getNemesis(unit)`` + + Returns the nemesis record of the unit if it has one, or *nil*. + +* ``dfhack.units.isHidingCurse(unit)`` + + Checks if the unit hides improved attributes from its curse. + +* ``dfhack.units.getPhysicalAttrValue(unit, attr_type)`` +* ``dfhack.units.getMentalAttrValue(unit, attr_type)`` + + Computes the effective attribute value, including curse effect. + +* ``dfhack.units.isCrazed(unit)`` +* ``dfhack.units.isOpposedToLife(unit)`` +* ``dfhack.units.hasExtravision(unit)`` +* ``dfhack.units.isBloodsucker(unit)`` + + Simple checks of caste attributes that can be modified by curses. + +* ``dfhack.units.getMiscTrait(unit, type[, create])`` + + Finds (or creates if requested) a misc trait object with the given id. + +* ``dfhack.units.isDead(unit)`` + + The unit is completely dead and passive, or a ghost. + +* ``dfhack.units.isAlive(unit)`` + + The unit isn't dead or undead. + +* ``dfhack.units.isSane(unit)`` + + The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf. + +* ``dfhack.units.isDwarf(unit)`` + + The unit is of the correct race of the fortress. + +* ``dfhack.units.isCitizen(unit)`` + + The unit is an alive sane citizen of the fortress; wraps the + same checks the game uses to decide game-over by extinction. + +* ``dfhack.units.getAge(unit[,true_age])`` + + Returns the age of the unit in years as a floating-point value. + If ``true_age`` is true, ignores false identities. + +* ``dfhack.units.getNominalSkill(unit, skill[, use_rust])`` + + Retrieves the nominal skill level for the given unit. If ``use_rust`` + is *true*, subtracts the rust penalty. + +* ``dfhack.units.getEffectiveSkill(unit, skill)`` + + Computes the effective rating for the given skill, taking into account exhaustion, pain etc. + +* ``dfhack.units.computeMovementSpeed(unit)`` + + Computes number of frames * 100 it takes the unit to move in its current state of mind and body. + +* ``dfhack.units.getNoblePositions(unit)`` + + Returns a list of tables describing noble position assignments, or *nil*. + Every table has fields ``entity``, ``assignment`` and ``position``. + +* ``dfhack.units.getProfessionName(unit[,ignore_noble,plural])`` + + Retrieves the profession name using custom profession, noble assignments + or raws. The ``ignore_noble`` boolean disables the use of noble positions. + +* ``dfhack.units.getCasteProfessionName(race,caste,prof_id[,plural])`` + + Retrieves the profession name for the given race/caste using raws. + +* ``dfhack.units.getProfessionColor(unit[,ignore_noble])`` + + Retrieves the color associated with the profession, using noble assignments + or raws. The ``ignore_noble`` boolean disables the use of noble positions. + +* ``dfhack.units.getCasteProfessionColor(race,caste,prof_id)`` + + Retrieves the profession color for the given race/caste using raws. + + +Items module +------------ + +* ``dfhack.items.getPosition(item)`` + + Returns true *x,y,z* of the item, or *nil* if invalid; may be not equal to item.pos if in inventory. + +* ``dfhack.items.getDescription(item, type[, decorate])`` + + Returns the string description of the item, as produced by the getItemDescription + method. If decorate is true, also adds markings for quality and improvements. + +* ``dfhack.items.getGeneralRef(item, type)`` + + Searches for a general_ref with the given type. + +* ``dfhack.items.getSpecificRef(item, type)`` + + Searches for a specific_ref with the given type. + +* ``dfhack.items.getOwner(item)`` + + Returns the owner unit or *nil*. + +* ``dfhack.items.setOwner(item,unit)`` + + Replaces the owner of the item. If unit is *nil*, removes ownership. + Returns *false* in case of error. + +* ``dfhack.items.getContainer(item)`` + + Returns the container item or *nil*. + +* ``dfhack.items.getContainedItems(item)`` + + Returns a list of items contained in this one. + +* ``dfhack.items.moveToGround(item,pos)`` + + Move the item to the ground at position. Returns *false* if impossible. + +* ``dfhack.items.moveToContainer(item,container)`` + + Move the item to the container. Returns *false* if impossible. + +* ``dfhack.items.moveToBuilding(item,building,use_mode)`` + + Move the item to the building. Returns *false* if impossible. + +* ``dfhack.items.moveToInventory(item,unit,use_mode,body_part)`` + + Move the item to the unit inventory. Returns *false* if impossible. + +* ``dfhack.items.remove(item[, no_uncat])`` + + Removes the item, and marks it for garbage collection unless ``no_uncat`` is true. + +* ``dfhack.items.makeProjectile(item)`` + + Turns the item into a projectile, and returns the new object, or *nil* if impossible. + + +Maps module +----------- + +* ``dfhack.maps.getSize()`` + + Returns map size in blocks: *x, y, z* + +* ``dfhack.maps.getTileSize()`` + + Returns map size in tiles: *x, y, z* + +* ``dfhack.maps.getBlock(x,y,z)`` + + Returns a map block object for given x,y,z in local block coordinates. + +* ``dfhack.maps.isValidTilePos(coords)``, or isValidTilePos(x,y,z)`` + + Checks if the given df::coord or x,y,z in local tile coordinates are valid. + +* ``dfhack.maps.getTileBlock(coords)``, or ``getTileBlock(x,y,z)`` + + Returns a map block object for given df::coord or x,y,z in local tile coordinates. + +* ``dfhack.maps.ensureTileBlock(coords)``, or ``ensureTileBlock(x,y,z)`` + + Like ``getTileBlock``, but if the block is not allocated, try creating it. + +* ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)`` + + Returns the biome info struct for the given global map region. + +* ``dfhack.maps.enableBlockUpdates(block[,flow,temperature])`` + + Enables updates for liquid flow or temperature, unless already active. + +* ``dfhack.maps.spawnFlow(pos,type,mat_type,mat_index,dimension)`` + + Spawns a new flow (i.e. steam/mist/dust/etc) at the given pos, and with + the given parameters. Returns it, or *nil* if unsuccessful. + +* ``dfhack.maps.getGlobalInitFeature(index)`` + + Returns the global feature object with the given index. + +* ``dfhack.maps.getLocalInitFeature(region_coord2d,index)`` + + Returns the local feature object with the given region coords and index. + +* ``dfhack.maps.getTileBiomeRgn(coords)``, or ``getTileBiomeRgn(x,y,z)`` + + Returns *x, y* for use with ``getRegionBiome``. + +* ``dfhack.maps.canWalkBetween(pos1, pos2)`` + + Checks if a dwarf may be able to walk between the two tiles, + using a pathfinding cache maintained by the game. Note that + this cache is only updated when the game is unpaused, and thus + can get out of date if doors are forbidden or unforbidden, or + tools like liquids or tiletypes are used. It also cannot possibly + take into account anything that depends on the actual units, like + burrows, or the presence of invaders. + + +Burrows module +-------------- + +* ``dfhack.burrows.findByName(name)`` + + Returns the burrow pointer or *nil*. + +* ``dfhack.burrows.clearUnits(burrow)`` + + Removes all units from the burrow. + +* ``dfhack.burrows.isAssignedUnit(burrow,unit)`` + + Checks if the unit is in the burrow. + +* ``dfhack.burrows.setAssignedUnit(burrow,unit,enable)`` + + Adds or removes the unit from the burrow. + +* ``dfhack.burrows.clearTiles(burrow)`` + + Removes all tiles from the burrow. + +* ``dfhack.burrows.listBlocks(burrow)`` + + Returns a table of map block pointers. + +* ``dfhack.burrows.isAssignedTile(burrow,tile_coord)`` + + Checks if the tile is in burrow. + +* ``dfhack.burrows.setAssignedTile(burrow,tile_coord,enable)`` + + Adds or removes the tile from the burrow. Returns *false* if invalid coords. + +* ``dfhack.burrows.isAssignedBlockTile(burrow,block,x,y)`` + + Checks if the tile within the block is in burrow. + +* ``dfhack.burrows.setAssignedBlockTile(burrow,block,x,y,enable)`` + + Adds or removes the tile from the burrow. Returns *false* if invalid coords. + + +Buildings module +---------------- + +* ``dfhack.buildings.setOwner(item,unit)`` + + Replaces the owner of the building. If unit is *nil*, removes ownership. + Returns *false* in case of error. + +* ``dfhack.buildings.getSize(building)`` + + Returns *width, height, centerx, centery*. + +* ``dfhack.buildings.findAtTile(pos)``, or ``findAtTile(x,y,z)`` + + Scans the buildings for the one located at the given tile. + Does not work on civzones. Warning: linear scan if the map + tile indicates there are buildings at it. + +* ``dfhack.buildings.findCivzonesAt(pos)``, or ``findCivzonesAt(x,y,z)`` + + Scans civzones, and returns a lua sequence of those that touch + the given tile, or *nil* if none. + +* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)`` + + Computes correct dimensions for the specified building type and orientation, + using width and height for flexible dimensions. + Returns *is_flexible, width, height, center_x, center_y*. + +* ``dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])`` + + Checks if the rectangle defined by ``pos`` and ``size``, and possibly extents, + can be used for placing a building. If ``change_extents`` is true, bad tiles + are removed from extents. If ``allow_occupied``, the occupancy test is skipped. + +* ``dfhack.buildings.countExtentTiles(extents,defval)`` + + Returns the number of tiles included by extents, or defval. + +* ``dfhack.buildings.containsTile(building, x, y[, room])`` + + Checks if the building contains the specified tile, either directly, or as room. + +* ``dfhack.buildings.hasSupport(pos,size)`` + + Checks if a bridge constructed at specified position would have + support from terrain, and thus won't collapse if retracted. + +Low-level building creation functions; + +* ``dfhack.buildings.allocInstance(pos, type, subtype, custom)`` + + Creates a new building instance of given type, subtype and custom type, + at specified position. Returns the object, or *nil* in case of an error. + +* ``dfhack.buildings.setSize(building, width, height, direction)`` + + Configures an object returned by ``allocInstance``, using specified + parameters wherever appropriate. If the building has fixed size along + any dimension, the corresponding input parameter will be ignored. + Returns *false* if the building cannot be placed, or *true, width, + height, rect_area, true_area*. Returned width and height are the + final values used by the building; true_area is less than rect_area + if any tiles were removed from designation. + +* ``dfhack.buildings.constructAbstract(building)`` + + Links a fully configured object created by ``allocInstance`` into the + world. The object must be an abstract building, i.e. a stockpile or civzone. + Returns *true*, or *false* if impossible. + +* ``dfhack.buildings.constructWithItems(building, items)`` + + Links a fully configured object created by ``allocInstance`` into the + world for construction, using a list of specific items as material. + Returns *true*, or *false* if impossible. + +* ``dfhack.buildings.constructWithFilters(building, job_items)`` + + Links a fully configured object created by ``allocInstance`` into the + world for construction, using a list of job_item filters as inputs. + Returns *true*, or *false* if impossible. Filter objects are claimed + and possibly destroyed in any case. + Use a negative ``quantity`` field value to auto-compute the amount + from the size of the building. + +* ``dfhack.buildings.deconstruct(building)`` + + Destroys the building, or queues a deconstruction job. + Returns *true* if the building was destroyed and deallocated immediately. + +More high-level functions are implemented in lua and can be loaded by +``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. + +Among them are: + +* ``dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)`` + + Returns a sequence of lua structures, describing input item filters + suitable for the specified building type, or *nil* if unknown or invalid. + The returned sequence is suitable for use as the ``job_items`` argument + of ``constructWithFilters``. + Uses tables defined in ``buildings.lua``. + + Argtable members ``material`` (the default name), ``bucket``, ``barrel``, + ``chain``, ``mechanism``, ``screw``, ``pipe``, ``anvil``, ``weapon`` are used to + augment the basic attributes with more detailed information if the + building has input items with the matching name (see the tables for naming details). + Note that it is impossible to *override* any properties this way, only supply those that + are not mentioned otherwise; one exception is that flags2.non_economic + is automatically cleared if an explicit material is specified. + +* ``dfhack.buildings.constructBuilding{...}`` + + Creates a building in one call, using options contained + in the argument table. Returns the building, or *nil, error*. + + **NOTE:** Despite the name, unless the building is abstract, + the function creates it in an 'unconstructed' stage, with + a queued in-game job that will actually construct it. I.e. + the function replicates programmatically what can be done + through the construct building menu in the game ui, except + that it does less environment constraint checking. + + The following options can be used: + + - ``pos = coordinates``, or ``x = ..., y = ..., z = ...`` + + Mandatory. Specifies the left upper corner of the building. + + - ``type = df.building_type.FOO, subtype = ..., custom = ...`` + + Mandatory. Specifies the type of the building. Obviously, subtype + and custom are only expected if the type requires them. + + - ``fields = { ... }`` + + Initializes fields of the building object after creation with ``df.assign``. + + - ``width = ..., height = ..., direction = ...`` + + Sets size and orientation of the building. If it is + fixed-size, specified dimensions are ignored. + + - ``full_rectangle = true`` + + For buildings like stockpiles or farm plots that can normally + accomodate individual tile exclusion, forces an error if any + tiles within the specified width*height are obstructed. + + - ``items = { item, item ... }``, or ``filters = { {...}, {...}... }`` + + Specifies explicit items or item filters to use in construction. + It is the job of the user to ensure they are correct for the building type. + + - ``abstract = true`` + + Specifies that the building is abstract and does not require construction. + Required for stockpiles and civzones; an error otherwise. + + - ``material = {...}, mechanism = {...}, ...`` + + If none of ``items``, ``filter``, or ``abstract`` is used, + the function uses ``getFiltersByType`` to compute the input + item filters, and passes the argument table through. If no filters + can be determined this way, ``constructBuilding`` throws an error. + + +Constructions module +-------------------- + +* ``dfhack.constructions.designateNew(pos,type,item_type,mat_index)`` + + Designates a new construction at given position. If there already is + a planned but not completed construction there, changes its type. + Returns *true*, or *false* if obstructed. + Note that designated constructions are technically buildings. + +* ``dfhack.constructions.designateRemove(pos)``, or ``designateRemove(x,y,z)`` + + If there is a construction or a planned construction at the specified + coordinates, designates it for removal, or instantly cancels the planned one. + Returns *true, was_only_planned* if removed; or *false* if none found. + + +Screen API +---------- + +The screen module implements support for drawing to the tiled screen of the game. +Note that drawing only has any effect when done from callbacks, so it can only +be feasibly used in the core context. + +Basic painting functions: + +* ``dfhack.screen.getWindowSize()`` + + Returns *width, height* of the screen. + +* ``dfhack.screen.getMousePos()`` + + Returns *x,y* of the tile the mouse is over. + +* ``dfhack.screen.inGraphicsMode()`` + + Checks if [GRAPHICS:YES] was specified in init. + +* ``dfhack.screen.paintTile(pen,x,y[,char,tile])`` + + Paints a tile using given parameters. Pen is a table with following possible fields: + + ``ch`` + Provides the ordinary tile character, as either a 1-character string or a number. + Can be overridden with the ``char`` function parameter. + ``fg`` + Foreground color for the ordinary tile. Defaults to COLOR_GREY (7). + ``bg`` + Background color for the ordinary tile. Defaults to COLOR_BLACK (0). + ``bold`` + Bright/bold text flag. If *nil*, computed based on (fg & 8); fg is masked to 3 bits. + Otherwise should be *true/false*. + ``tile`` + Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt. + ``tile_color = true`` + Specifies that the tile should be shaded with *fg/bg*. + ``tile_fg, tile_bg`` + If specified, overrides *tile_color* and supplies shading colors directly. + + Returns *false* if coordinates out of bounds, or other error. + +* ``dfhack.screen.readTile(x,y)`` + + Retrieves the contents of the specified tile from the screen buffers. + Returns a pen, or *nil* if invalid or TrueType. + +* ``dfhack.screen.paintString(pen,x,y,text)`` + + Paints the string starting at *x,y*. Uses the string characters + in sequence to override the ``ch`` field of pen. + + Returns *true* if painting at least one character succeeded. + +* ``dfhack.screen.fillRect(pen,x1,y1,x2,y2)`` + + Fills the rectangle specified by the coordinates with the given pen. + Returns *true* if painting at least one character succeeded. + +* ``dfhack.screen.findGraphicsTile(pagename,x,y)`` + + Finds a tile from a graphics set (i.e. the raws used for creatures), + if in graphics mode and loaded. + + Returns: *tile, tile_grayscale*, or *nil* if not found. + The values can then be used for the *tile* field of *pen* structures. + +* ``dfhack.screen.clear()`` + + Fills the screen with blank background. + +* ``dfhack.screen.invalidate()`` + + Requests repaint of the screen by setting a flag. Unlike other + functions in this section, this may be used at any time. + +In order to actually be able to paint to the screen, it is necessary +to create and register a viewscreen (basically a modal dialog) with +the game. + +**NOTE**: As a matter of policy, in order to avoid user confusion, all +interface screens added by dfhack should bear the "DFHack" signature. + +Screens are managed with the following functions: + +* ``dfhack.screen.show(screen[,below])`` + + Displays the given screen, possibly placing it below a different one. + The screen must not be already shown. Returns *true* if success. + +* ``dfhack.screen.dismiss(screen[,to_first])`` + + Marks the screen to be removed when the game enters its event loop. + If ``to_first`` is *true*, all screens up to the first one will be deleted. + +* ``dfhack.screen.isDismissed(screen)`` + + Checks if the screen is already marked for removal. + +Apart from a native viewscreen object, these functions accept a table +as a screen. In this case, ``show`` creates a new native viewscreen +that delegates all processing to methods stored in that table. + +**NOTE**: Lua-implemented screens are only supported in the core context. + +Supported callbacks and fields are: + +* ``screen._native`` + + Initialized by ``show`` with a reference to the backing viewscreen + object, and removed again when the object is deleted. + +* ``function screen:onShow()`` + + Called by ``dfhack.screen.show`` if successful. + +* ``function screen:onDismiss()`` + + Called by ``dfhack.screen.dismiss`` if successful. + +* ``function screen:onDestroy()`` + + Called from the destructor when the viewscreen is deleted. + +* ``function screen:onResize(w, h)`` + + Called before ``onRender`` or ``onIdle`` when the window size has changed. + +* ``function screen:onRender()`` + + Called when the viewscreen should paint itself. This is the only context + where the above painting functions work correctly. + + If omitted, the screen is cleared; otherwise it should do that itself. + In order to make a see-through dialog, call ``self._native.parent:render()``. + +* ``function screen:onIdle()`` + + Called every frame when the screen is on top of the stack. + +* ``function screen:onHelp()`` + + Called when the help keybinding is activated (usually '?'). + +* ``function screen:onInput(keys)`` + + Called when keyboard or mouse events are available. + If any keys are pressed, the keys argument is a table mapping them to *true*. + Note that this refers to logical keybingings computed from real keys via + options; if multiple interpretations exist, the table will contain multiple keys. + + The table also may contain special keys: + + ``_STRING`` + Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience. + + ``_MOUSE_L, _MOUSE_R`` + If the left or right mouse button is pressed. + + If this method is omitted, the screen is dismissed on receival of the ``LEAVESCREEN`` key. + +* ``function screen:onGetSelectedUnit()`` +* ``function screen:onGetSelectedItem()`` +* ``function screen:onGetSelectedJob()`` +* ``function screen:onGetSelectedBuilding()`` + + Implement these to provide a return value for the matching + ``dfhack.gui.getSelected...`` function. + + +Internal API +------------ + +These functions are intended for the use by dfhack developers, +and are only documented here for completeness: + +* ``dfhack.internal.scripts`` + + The table used by ``dfhack.run_script()`` to give every script its own + global environment, persistent between calls to the script. + +* ``dfhack.internal.getAddress(name)`` + + Returns the global address ``name``, or *nil*. + +* ``dfhack.internal.setAddress(name, value)`` + + Sets the global address ``name``. Returns the value of ``getAddress`` before the change. + +* ``dfhack.internal.getVTable(name)`` + + Returns the pre-extracted vtable address ``name``, or *nil*. + +* ``dfhack.internal.getRebaseDelta()`` + + Returns the ASLR rebase offset of the DF executable. + +* ``dfhack.internal.getMemRanges()`` + + Returns a sequence of tables describing virtual memory ranges of the process. + +* ``dfhack.internal.patchMemory(dest,src,count)`` + + Like memmove below, but works even if dest is read-only memory, e.g. code. + If destination overlaps a completely invalid memory region, or another error + occurs, returns false. + +* ``dfhack.internal.memmove(dest,src,count)`` + + Wraps the standard memmove function. Accepts both numbers and refs as pointers. + +* ``dfhack.internal.memcmp(ptr1,ptr2,count)`` + + Wraps the standard memcmp function. + +* ``dfhack.internal.memscan(haystack,count,step,needle,nsize)`` + + Searches for ``needle`` of ``nsize`` bytes in ``haystack``, + using ``count`` steps of ``step`` bytes. + Returns: *step_idx, sum_idx, found_ptr*, or *nil* if not found. + +* ``dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])`` + + 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: *found_index*, or *nil* if end reached. + + +Core interpreter context +======================== + +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. + +Core context specific functions: + +* ``dfhack.is_core_context`` + + Boolean value; *true* in the core context. + +* ``dfhack.timeout(time,mode,callback)`` + + Arranges for the callback to be called once the specified + period of time passes. The ``mode`` argument specifies the + unit of time used, and may be one of ``'frames'`` (raw FPS), + ``'ticks'`` (unpaused FPS), ``'days'``, ``'months'``, + ``'years'`` (in-game time). All timers other than + ``'frames'`` are cancelled when the world is unloaded, + and cannot be queued until it is loaded again. + Returns the timer id, or *nil* if unsuccessful due to + world being unloaded. + +* ``dfhack.timeout_active(id[,new_callback])`` + + Returns the active callback with the given id, or *nil* + if inactive or nil id. If called with 2 arguments, replaces + the current callback with the given value, if still active. + Using ``timeout_active(id,nil)`` cancels the timer. + +* ``dfhack.onStateChange.foo = function(code)`` + + Event. Receives the same codes as plugin_onstatechange in C++. + + +Event type +---------- + +An event is a native object transparently wrapping a lua table, +and implementing a __call metamethod. When it is invoked, it loops +through the table with next and calls all contained values. +This is intended as an extensible way to add listeners. + +This type itself is available in any context, but only the +core context has the actual events defined by C++ code. + +Features: + +* ``dfhack.event.new()`` + + Creates a new instance of an event. + +* ``event[key] = function`` + + Sets the function as one of the listeners. Assign *nil* to remove it. + + **NOTE**: The ``df.NULL`` key is reserved for the use by + the C++ owner of the event; it is an error to try setting it. + +* ``#event`` + + Returns the number of non-nil listeners. + +* ``pairs(event)`` + + Iterates over all listeners in the table. + +* ``event(args...)`` + + Invokes all listeners contained in the event in an arbitrary + order using ``dfhack.safecall``. + + +=========== +Lua Modules +=========== + +DFHack sets up the lua interpreter so that the built-in ``require`` +function can be used to load shared lua code from hack/lua/. +The ``dfhack`` namespace reference itself may be obtained via +``require('dfhack')``, although it is initially created as a +global by C++ bootstrap code. + +The following module management functions are provided: + +* ``mkmodule(name)`` + + Creates an environment table for the module. Intended to be used as:: + + local _ENV = mkmodule('foo') + ... + return _ENV + + If called the second time, returns the same table; thus providing reload support. + +* ``reload(name)`` + + Reloads a previously ``require``-d module *"name"* from the file. + Intended as a help for module development. + +* ``dfhack.BASE_G`` + + 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. + +Global environment +================== + +A number of variables and functions are provided in the base global +environment by the mandatory init file dfhack.lua: + +* Color constants + + These are applicable both for ``dfhack.color()`` and color fields + in DF functions or structures: + + 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 + +* ``dfhack.onStateChange`` event codes + + Available only in the core context, as is the event itself: + + SC_WORLD_LOADED, SC_WORLD_UNLOADED, SC_MAP_LOADED, + SC_MAP_UNLOADED, SC_VIEWSCREEN_CHANGED, SC_CORE_INITIALIZED + +* Functions already described above + + safecall, qerror, mkmodule, reload + +* ``printall(obj)`` + + If the argument is a lua table or DF object reference, prints all fields. + +* ``copyall(obj)`` + + Returns a shallow copy of the table or reference as a lua table. + +* ``pos2xyz(obj)`` + + The object must have fields x, y and z. Returns them as 3 values. + If obj is *nil*, or x is -30000 (the usual marker for undefined + coordinates), returns *nil*. + +* ``xyz2pos(x,y,z)`` + + Returns a table with x, y and z as fields. + +* ``safe_index(obj,index...)`` + + Walks a sequence of dereferences, which may be represented by numbers or strings. + Returns *nil* if any of obj or indices is *nil*, or a numeric index is out of array bounds. + +utils +===== + +* ``utils.compare(a,b)`` + + Comparator function; returns *-1* if ab, *0* otherwise. + +* ``utils.compare_name(a,b)`` + + Comparator for names; compares empty string last. + +* ``utils.is_container(obj)`` + + Checks if obj is a container ref. + +* ``utils.make_index_sequence(start,end)`` + + Returns a lua sequence of numbers in start..end. + +* ``utils.make_sort_order(data, ordering)`` + + Computes a sorted permutation of objects in data, as a table of integer + indices into the data sequence. Uses ``data.n`` as input length + if present. + + The ordering argument is a sequence of ordering specs, represented + as lua tables with following possible fields: + + ord.key = *function(value)* + Computes comparison key from input data value. Not called on nil. + If omitted, the comparison key is the value itself. + ord.key_table = *function(data)* + Computes a key table from the data table in one go. + ord.compare = *function(a,b)* + Comparison function. Defaults to ``utils.compare`` above. + Called on non-nil keys; nil sorts last. + ord.nil_first = *true/false* + If true, nil keys are sorted first instead of last. + ord.reverse = *true/false* + If true, sort non-nil keys in descending order. + + For every comparison during sorting the specs are applied in + order until an unambiguous decision is reached. Sorting is stable. + + Example of sorting a sequence by field foo:: + + local spec = { key = function(v) return v.foo end } + local order = utils.make_sort_order(data, { spec }) + local output = {} + for i = 1,#order do output[i] = data[order[i]] end + + Separating the actual reordering of the sequence in this + way enables applying the same permutation to multiple arrays. + This function is used by the sort plugin. + +* ``utils.assign(tgt, src)`` + + Does a recursive assignment of src into tgt. + Uses ``df.assign`` if tgt is a native object ref; otherwise + recurses into lua tables. + +* ``utils.clone(obj, deep)`` + + 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. + +* ``utils.clone_with_default(obj, default, force)`` + + Copies the object, using the ``default`` lua table tree + as a guide to which values should be skipped as uninteresting. + The ``force`` argument makes it always return a non-*nil* value. + +* ``utils.sort_vector(vector,field,cmpfun)`` + + Sorts a native vector or lua sequence using the comparator function. + If ``field`` is not *nil*, applies the comparator to the field instead + of the whole object. + +* ``utils.binsearch(vector,key,field,cmpfun,min,max)`` + + Does a binary search in a native vector or lua sequence for + ``key``, using ``cmpfun`` and ``field`` like sort_vector. + If ``min`` and ``max`` are specified, they are used as the + search subrange bounds. + + If found, returns *item, true, idx*. Otherwise returns + *nil, false, insert_idx*, where *insert_idx* is the correct + insertion point. + +* ``utils.insert_sorted(vector,item,field,cmpfun)`` + + Does a binary search, and inserts item if not found. + Returns *did_insert, vector[idx], idx*. + +* ``utils.insert_or_update(vector,item,field,cmpfun)`` + + Like ``insert_sorted``, but also assigns the item into + the vector cell if insertion didn't happen. + + As an example, you can use this to set skill values:: + + utils.insert_or_update(soul.skills, {new=true, id=..., rating=...}, 'id') + + (For an explanation of ``new=true``, see table assignment in the wrapper section) + +* ``utils.prompt_yes_no(prompt, default)`` + + Presents a yes/no prompt to the user. If ``default`` is not *nil*, + allows just pressing Enter to submit the default choice. + If the user enters ``'abort'``, throws an error. + +* ``utils.prompt_input(prompt, checkfun, quit_str)`` + + Presents a prompt to input data, until a valid string is entered. + Once ``checkfun(input)`` returns *true, ...*, passes the values + through. If the user enters the quit_str (defaults to ``'~~~'``), + throws an error. + +* ``utils.check_number(text)`` + + A ``prompt_input`` ``checkfun`` that verifies a number input. + +dumper +====== + +A third-party lua table dumper module from +http://lua-users.org/wiki/DataDumper. Defines one +function: + +* ``dumper.DataDumper(value, varname, fastmode, ident, indent_step)`` + + Returns ``value`` converted to a string. The ``indent_step`` + argument specifies the indentation step size in spaces. For + the other arguments see the original documentation link above. + +class +===== + +Implements a trivial single-inheritance class system. + +* ``Foo = defclass(Foo[, ParentClass])`` + + Defines or updates class Foo. The ``Foo = defclass(Foo)`` syntax + is needed so that when the module or script is reloaded, the + class identity will be preserved through the preservation of + global variable values. + + The ``defclass`` function is defined as a stub in the global + namespace, and using it will auto-load the class module. + +* ``Class.super`` + + This class field is set by defclass to the parent class, and + allows a readable ``Class.super.method(self, ...)`` syntax for + calling superclass methods. + +* ``Class.ATTRS { foo = xxx, bar = yyy }`` + + Declares certain instance fields to be attributes, i.e. auto-initialized + from fields in the table used as the constructor argument. If omitted, + they are initialized with the default values specified in this declaration. + + If the default value should be *nil*, use ``ATTRS { foo = DEFAULT_NIL }``. + +* ``new_obj = Class{ foo = arg, bar = arg, ... }`` + + Calling the class as a function creates and initializes a new instance. + Initialization happens in this order: + + 1. An empty instance table is created, and its metatable set. + 2. The ``preinit`` method is called via ``invoke_before`` (see below) + with the table used as argument to the class. This method is intended + for validating and tweaking that argument table. + 3. Declared ATTRS are initialized from the argument table or their default values. + 4. The ``init`` method is called via ``invoke_after`` with the argument table. + This is the main constructor method. + 5. The ``postinit`` method is called via ``invoke_after`` with the argument table. + Place code that should be called after the object is fully constructed here. + +Predefined instance methods: + +* ``instance:assign{ foo = xxx }`` + + Assigns all values in the input table to the matching instance fields. + +* ``instance:callback(method_name, [args...])`` + + Returns a closure that invokes the specified method of the class, + properly passing in self, and optionally a number of initial arguments too. + The arguments given to the closure are appended to these. + +* ``instance:invoke_before(method_name, args...)`` + + Navigates the inheritance chain of the instance starting from the most specific + class, and invokes the specified method with the arguments if it is defined in + that specific class. Equivalent to the following definition in every class:: + + function Class:invoke_before(method, ...) + if rawget(Class, method) then + rawget(Class, method)(self, ...) + end + Class.super.invoke_before(method, ...) + end + +* ``instance:invoke_after(method_name, args...)`` + + Like invoke_before, only the method is called after the recursive call to super, + i.e. invocations happen in the parent to child order. + + These two methods are inspired by the Common Lisp before and after methods, and + are intended for implementing similar protocols for certain things. The class + library itself uses them for constructors. + +To avoid confusion, these methods cannot be redefined. + + +======= +Plugins +======= + +DFHack plugins may export native functions and events +to lua contexts. They are automatically imported by +``mkmodule('plugins.')``; this means that a lua +module file is still necessary for ``require`` to read. + +The following plugins have lua support. + +burrows +======= + +Implements extended burrow manipulations. + +Events: + +* ``onBurrowRename.foo = function(burrow)`` + + Emitted when a burrow might have been renamed either through + the game UI, or ``renameBurrow()``. + +* ``onDigComplete.foo = function(job_type,pos,old_tiletype,new_tiletype,worker)`` + + Emitted when a tile might have been dug out. Only tracked if the + auto-growing burrows feature is enabled. + +Native functions: + +* ``renameBurrow(burrow,name)`` + + Renames the burrow, emitting ``onBurrowRename`` and updating auto-grow state properly. + +* ``findByName(burrow,name)`` + + Finds a burrow by name, using the same rules as the plugin command line interface. + Namely, trailing ``'+'`` characters marking auto-grow burrows are ignored. + +* ``copyUnits(target,source,enable)`` + + Applies units from ``source`` burrow to ``target``. The ``enable`` + parameter specifies if they are to be added or removed. + +* ``copyTiles(target,source,enable)`` + + Applies tiles from ``source`` burrow to ``target``. The ``enable`` + parameter specifies if they are to be added or removed. + +* ``setTilesByKeyword(target,keyword,enable)`` + + Adds or removes tiles matching a predefined keyword. The keyword + set is the same as used by the command line. + +The lua module file also re-exports functions from ``dfhack.burrows``. + +sort +==== + +Does not export any native functions as of now. Instead, it +calls lua code to perform the actual ordering of list items. + + +======= +Scripts +======= + +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. + +If the first line of the script is a one-line comment, it is +used by the built-in ``ls`` and ``help`` commands. + +**NOTE:** Scripts placed in subdirectories still can be accessed, but +do not clutter the ``ls`` 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. ``devel/lua-example``. + +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. + +Arguments are passed in to the scripts via the **...** built-in +quasi-variable; when the script is called by the DFHack core, +they are all guaranteed to be non-nil strings. + +DFHack core invokes the scripts in the *core context* (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: + +* ``dfhack.run_script(name[,args...])`` + + Run a lua script in hack/scripts/, as if it was started from dfhack command-line. + The ``name`` argument should be the name stem, as would be used on the command line. + +Note that this function lets errors propagate to the caller. diff --git a/fixTexts.sh b/fixTexts.sh index e8d89044..91719941 100755 --- a/fixTexts.sh +++ b/fixTexts.sh @@ -2,5 +2,5 @@ # this script is used for easy testing of the rst documentation files. rst2html Readme.rst Readme.html rst2html Compile.rst Compile.html -rst2html LUA\ Api.rst LUA\ Api.html +rst2html Lua\ API.rst Lua\ API.html rst2html Contributors.rst > Contributors.html -- cgit v1.2.1