Merge branch 'develop' of https://github.com/DFHack/dfhack into develop

develop
Japa 2015-09-28 10:07:23 +05:30
commit 449e0c7578
93 changed files with 6269 additions and 13484 deletions

7
.gitignore vendored

@ -20,6 +20,10 @@ nix
buntu buntu
build/VC2010 build/VC2010
# Sphinx generated documentation
docs/_*/
docs/html/
#except for the real one #except for the real one
!build/ !build/
@ -67,3 +71,6 @@ tags
# Mac OS X .DS_Store files # Mac OS X .DS_Store files
.DS_Store .DS_Store
# autogenerated include-all.rst files
**include-all.rst

17
.gitmodules vendored

@ -15,4 +15,19 @@
url = git://github.com/DFHack/clsocket.git url = git://github.com/DFHack/clsocket.git
[submodule "scripts/3rdparty/lethosor"] [submodule "scripts/3rdparty/lethosor"]
path = scripts/3rdparty/lethosor path = scripts/3rdparty/lethosor
url = https://github.com/DFHack/lethosor-scripts url = git://github.com/DFHack/lethosor-scripts
[submodule "scripts/3rdparty/roses"]
path = scripts/3rdparty/roses
url = git://github.com/DFHack/roses-scripts.git
[submodule "scripts/3rdparty/maxthyme"]
path = scripts/3rdparty/maxthyme
url = git://github.com/DFHack/maxthyme-scripts.git
[submodule "scripts/3rdparty/dscorbett"]
path = scripts/3rdparty/dscorbett
url = git://github.com/DFHack/dscorbett-scripts.git
[submodule "scripts/3rdparty/kane-t"]
path = scripts/3rdparty/kane-t
url = git://github.com/DFHack/kane-t-scripts.git
[submodule "scripts/3rdparty/maienm"]
path = scripts/3rdparty/maienm
url = git://github.com/DFHack/maienm-scripts.git

@ -1,15 +1,16 @@
sudo: false
addons:
apt:
packages:
- lua5.2
language: cpp language: cpp
env:
matrix:
-LUA_VERSION=5.2
before_install: before_install:
- sudo apt-get install lua$LUA_VERSION pip install --user sphinx
- sudo pip install docutils
script: script:
- python travis/pr-check-base.py - python travis/pr-check-base.py
- python travis/lint.py - python travis/lint.py
- python travis/script-syntax.py --ext=lua --cmd="luac$LUA_VERSION -p" - python travis/script-in-readme.py
- python travis/script-syntax.py --ext=lua --cmd="luac5.2 -p"
- python travis/script-syntax.py --ext=rb --cmd="ruby -c" - python travis/script-syntax.py --ext=rb --cmd="ruby -c"
- ./fixTexts.sh --force
notifications: notifications:
email: false email: false

@ -0,0 +1,16 @@
# build the documentation with Sphinx
find_program(SPHINX_EXECUTABLE NAMES sphinx-build
HINTS
$ENV{SPHINX_DIR}
PATH_SUFFIXES bin
DOC "Sphinx Documentation Generator"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Sphinx DEFAULT_MSG
SPHINX_EXECUTABLE
)
mark_as_advanced(SPHINX_EXECUTABLE)

@ -1,5 +1,10 @@
# main project file. use it from a build sub-folder, see COMPILE for details # main project file. use it from a build sub-folder, see COMPILE for details
# prevent CMake warnings about INTERFACE_LINK_LIBRARIES vs LINK_INTERFACE_LIBRARIES
IF(CMAKE_VERSION VERSION_GREATER "2.8.12")
CMAKE_POLICY(SET CMP0022 OLD)
ENDIF()
# Set up build types # Set up build types
if(CMAKE_CONFIGURATION_TYPES) if(CMAKE_CONFIGURATION_TYPES)
SET(CMAKE_CONFIGURATION_TYPES Release RelWithDebInfo) SET(CMAKE_CONFIGURATION_TYPES Release RelWithDebInfo)
@ -10,10 +15,39 @@ else(CMAKE_CONFIGURATION_TYPES)
endif (NOT CMAKE_BUILD_TYPE) endif (NOT CMAKE_BUILD_TYPE)
endif(CMAKE_CONFIGURATION_TYPES) endif(CMAKE_CONFIGURATION_TYPES)
OPTION(BUILD_DOCS "Choose whether to build the documentation (requires python and Sphinx)." ON)
## some generic CMake magic ## some generic CMake magic
cmake_minimum_required(VERSION 2.8 FATAL_ERROR) cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(dfhack) project(dfhack)
macro(CHECK_GCC COMPILER_PATH)
execute_process(COMMAND ${COMPILER_PATH} -dumpversion OUTPUT_VARIABLE GCC_VERSION_OUT)
string(STRIP "${GCC_VERSION_OUT}" GCC_VERSION_OUT)
if (${GCC_VERSION_OUT} VERSION_LESS "4.5" OR ${GCC_VERSION_OUT} VERSION_GREATER "4.9.9")
message(SEND_ERROR "${COMPILER_PATH} version ${GCC_VERSION_OUT} cannot be used - use GCC 4.5 through 4.9")
endif()
endmacro()
if(UNIX)
if(CMAKE_COMPILER_IS_GNUCC)
CHECK_GCC(${CMAKE_C_COMPILER})
else()
message(SEND_ERROR "C compiler is not GCC")
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
CHECK_GCC(${CMAKE_CXX_COMPILER})
else()
message(SEND_ERROR "C++ compiler is not GCC")
endif()
endif()
if(WIN32)
if(NOT MSVC)
message(SEND_ERROR "MSVC 2010 is required")
endif()
endif()
if(MSVC) if(MSVC)
# disable C4819 code-page warning # disable C4819 code-page warning
add_definitions( "/wd4819" ) add_definitions( "/wd4819" )
@ -54,7 +88,7 @@ endif()
# make sure all the necessary submodules have been set up # make sure all the necessary submodules have been set up
if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/clsocket/CMakeLists.txt) if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/clsocket/CMakeLists.txt)
message(FATAL_ERROR "One or more required submodules could not be found! Run 'git submodule update --init' from the root DFHack directory. (See the section 'Getting the Code' in Compile.rst or Compile.html)") message(SEND_ERROR "One or more required submodules could not be found! Run 'git submodule update --init' from the root DFHack directory. (See the section 'Getting the Code' in Compile.rst or Compile.html)")
endif() endif()
# set up versioning. # set up versioning.
@ -96,12 +130,12 @@ SET(DFHACK_DEVDOC_DESTINATION hack)
OPTION(BUILD_LIBRARY "Build the library that goes into DF." ON) OPTION(BUILD_LIBRARY "Build the library that goes into DF." ON)
OPTION(BUILD_PLUGINS "Build the plugins." ON) OPTION(BUILD_PLUGINS "Build the plugins." ON)
IF(UNIX)
## flags for GCC ## flags for GCC
# default to hidden symbols # default to hidden symbols
# build 32bit # build 32bit
# ensure compatibility with older CPUs # ensure compatibility with older CPUs
# enable C++11 features # enable C++11 features
IF(UNIX)
add_definitions(-DLINUX_BUILD) add_definitions(-DLINUX_BUILD)
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g -Wall -Wno-unused-variable") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g -Wall -Wno-unused-variable")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -m32 -march=i686 -mtune=generic -std=c++0x") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -m32 -march=i686 -mtune=generic -std=c++0x")
@ -147,34 +181,13 @@ if(NOT GIT_FOUND)
message(FATAL_ERROR "could not find git") message(FATAL_ERROR "could not find git")
endif() endif()
#find_package(Docutils)
#set (RST_FILES
#"Readme"
#"Compile"
#"LUA Api"
#"Contributors"
#)
#set (RST_PROCESSED_FILES "")
#IF(RST2HTML_EXECUTABLE)
# foreach(F ${RST_FILES})
# add_custom_command(
# OUTPUT "${dfhack_BINARY_DIR}/${F}.html"
# COMMAND ${RST2HTML_EXECUTABLE} "${dfhack_SOURCE_DIR}/${F}.rst" "${dfhack_BINARY_DIR}/${F}.html"
# COMMENT "Translating ${F} to html"
# DEPENDS "${dfhack_SOURCE_DIR}/${F}.rst")
# list (APPEND RST_PROCESSED_FILES "${dfhack_BINARY_DIR}/${F}.html")
# endforeach()
# add_custom_target(HTML_DOCS ALL DEPENDS ${RST_PROCESSED_FILES})
#ENDIF()
# build the lib itself # build the lib itself
IF(BUILD_LIBRARY) IF(BUILD_LIBRARY)
add_subdirectory (library) add_subdirectory (library)
## install the default documentation files ## install the default documentation files
install(FILES LICENSE NEWS "Lua API.html" Readme.html Compile.html Contributors.html DESTINATION ${DFHACK_USERDOC_DESTINATION}) #install(FILES LICENSE NEWS "Lua API.html" Readme.html Compile.html Contributors.html DESTINATION ${DFHACK_USERDOC_DESTINATION})
install(DIRECTORY images DESTINATION ${DFHACK_USERDOC_DESTINATION}) install(FILES LICENSE NEWS DESTINATION ${DFHACK_USERDOC_DESTINATION})
#install(DIRECTORY docs/images DESTINATION ${DFHACK_USERDOC_DESTINATION})
endif() endif()
install(DIRECTORY dfhack-config/ DESTINATION dfhack-config/default) install(DIRECTORY dfhack-config/ DESTINATION dfhack-config/default)
@ -186,10 +199,71 @@ endif()
add_subdirectory(scripts) add_subdirectory(scripts)
find_package(Sphinx)
if (BUILD_DOCS)
if (NOT SPHINX_FOUND)
message(SEND_ERROR "Sphinx not found but BUILD_DOCS enabled")
endif()
set(SPHINX_THEME "alabaster")
set(SPHINX_THEME_DIR)
set(SPHINX_BINARY_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/docs/_build")
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/docs/_build/_doctrees")
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/docs/html/")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/docs/conf.py.in"
"${SPHINX_BINARY_BUILD_DIR}/conf.py"
@ONLY)
file(GLOB SPHINX_DEPS
"${CMAKE_CURRENT_SOURCE_DIR}/docs/*.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/docs/images/*.png"
"${CMAKE_CURRENT_SOURCE_DIR}/docs/conf.py.in"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*/*/*/*/*.lua"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/*/*/*/*/*/*/*/*/*.lua"
)
set(SPHINX_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/docs/html/.buildinfo")
set_source_files_properties(${SPHINX_OUTPUT} PROPERTIES GENERATED TRUE)
add_custom_command(OUTPUT ${SPHINX_OUTPUT}
COMMAND ${SPHINX_EXECUTABLE}
-a -E -q -b html
-c "${SPHINX_BINARY_BUILD_DIR}"
-d "${SPHINX_CACHE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
"${SPHINX_HTML_DIR}"
DEPENDS ${SPHINX_DEPS}
COMMENT "Building HTML documentation with Sphinx"
)
add_custom_target(dfhack_docs ALL
DEPENDS ${SPHINX_OUTPUT}
)
# Sphinx doesn't touch this file if it didn't make changes,
# which makes CMake think it didn't complete
add_custom_command(TARGET dfhack_docs POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${SPHINX_OUTPUT})
install(DIRECTORY ${dfhack_SOURCE_DIR}/docs/html
DESTINATION ${DFHACK_USERDOC_DESTINATION}
#FILES_MATCHING PATTERN "*.lua"
# PATTERN "*.rb"
# PATTERN "3rdparty" EXCLUDE
)
endif()
# Packaging with CPack! # Packaging with CPack!
IF(UNIX) IF(UNIX)
if(APPLE) if(APPLE)
SET(CPACK_GENERATOR "ZIP") SET(CPACK_GENERATOR "ZIP;TBZ2")
else() else()
SET(CPACK_GENERATOR "TBZ2") SET(CPACK_GENERATOR "TBZ2")
endif() endif()
@ -204,3 +278,5 @@ ELSE()
ENDIF() ENDIF()
set(CPACK_PACKAGE_FILE_NAME "dfhack-${DFHACK_VERSION}-${DFHACK_PACKAGE_PLATFORM_NAME}") set(CPACK_PACKAGE_FILE_NAME "dfhack-${DFHACK_VERSION}-${DFHACK_PACKAGE_PLATFORM_NAME}")
INCLUDE(CPack) INCLUDE(CPack)
#INCLUDE(FindSphinx.cmake)

@ -1,655 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Building DFHACK</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="building-dfhack">
<h1 class="title">Building DFHACK</h1>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#linux" id="id4">Linux</a><ul>
<li><a class="reference internal" href="#how-to-get-the-code" id="id5">How to get the code</a></li>
<li><a class="reference internal" href="#dependencies" id="id6">Dependencies</a></li>
<li><a class="reference internal" href="#build" id="id7">Build</a></li>
<li><a class="reference internal" href="#fixing-the-libstdc-version-bug" id="id8">Fixing the libstdc++ version bug</a></li>
</ul>
</li>
<li><a class="reference internal" href="#mac-os-x" id="id9">Mac OS X</a><ul>
<li><a class="reference internal" href="#snow-leopard-changes" id="id10">Snow Leopard Changes</a></li>
<li><a class="reference internal" href="#yosemite-changes" id="id11">Yosemite Changes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#windows" id="id12">Windows</a><ul>
<li><a class="reference internal" href="#id1" id="id13">How to get the code</a></li>
<li><a class="reference internal" href="#id2" id="id14">Dependencies</a></li>
<li><a class="reference internal" href="#id3" id="id15">Build</a></li>
</ul>
</li>
<li><a class="reference internal" href="#build-types" id="id16">Build types</a></li>
<li><a class="reference internal" href="#using-the-library-as-a-developer" id="id17">Using the library as a developer</a><ul>
<li><a class="reference internal" href="#df-data-structure-definitions" id="id18">DF data structure definitions</a></li>
<li><a class="reference internal" href="#remote-access-interface" id="id19">Remote access interface</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="linux">
<h1><a class="toc-backref" href="#id4">Linux</a></h1>
<p>On Linux, DFHack acts as a library that shadows parts of the SDL API using LD_PRELOAD.</p>
<div class="section" id="how-to-get-the-code">
<h2><a class="toc-backref" href="#id5">How to get the code</a></h2>
<p>DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
Having a 'git' package installed is the minimal requirement, but some sort of git gui or git integration for your favorite text editor/IDE will certainly help.</p>
<p>The code resides here: <a class="reference external" href="https://github.com/DFHack/dfhack">https://github.com/DFHack/dfhack</a></p>
<p>If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address:</p>
<pre class="literal-block">
git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
</pre>
<p>If you want to get really involved with the development, create an account on github, make a clone there and then use that as your remote repository instead. Detailed instructions are beyond the scope of this document. If you need help, join us on IRC (#dfhack channel on freenode).</p>
</div>
<div class="section" id="dependencies">
<h2><a class="toc-backref" href="#id6">Dependencies</a></h2>
<p>DFHack is meant to be installed into an existing DF folder, so get one ready.</p>
<p>For building, you need a 32-bit version of GCC. For example, to build DFHack on
a 64-bit distribution like Arch, you'll need the multilib development tools and libraries.
Alternatively, you might be able to use <tt class="docutils literal">lxc</tt> to
<a class="reference external" href="http://www.bay12forums.com/smf/index.php?topic=139553.msg5435310#msg5435310">create a virtual 32-bit environment</a>.</p>
<p>Before you can build anything, you'll also need <tt class="docutils literal">cmake</tt>. It is advisable to also get
<tt class="docutils literal">ccmake</tt> on distributions that split the cmake package into multiple parts.</p>
<p>You also need perl and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts).
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt') or through <tt class="docutils literal">cpan</tt>.</p>
<p>To build Stonesense, you'll also need OpenGL headers.</p>
</div>
<div class="section" id="build">
<h2><a class="toc-backref" href="#id7">Build</a></h2>
<p>Building is fairly straightforward. Enter the <tt class="docutils literal">build</tt> folder and start the build like this:</p>
<pre class="literal-block">
cd build
cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/home/user/DF
make install
</pre>
<p>Obviously, replace the install path with path to your DF. This will build the library
along with the normal set of plugins and install them into your DF folder.</p>
<p>Alternatively, you can use ccmake instead of cmake:</p>
<pre class="literal-block">
cd build
ccmake ..
make install
</pre>
<p>This will show a curses-based interface that lets you set all of the
extra options.</p>
<p>You can also use a cmake-friendly IDE like KDevelop 4 or the cmake-gui
program.</p>
</div>
<div class="section" id="fixing-the-libstdc-version-bug">
<h2><a class="toc-backref" href="#id8">Fixing the libstdc++ version bug</a></h2>
<p>When compiling dfhack yourself, it builds against your system libc.
When Dwarf Fortress runs, it uses a libstdc++ shipped with the binary, which
is usually way older, and incompatible with your dfhack. This manifests with
the error message:</p>
<pre class="literal-block">
./libs/Dwarf_Fortress: /pathToDF/libs/libstdc++.so.6: version
`GLIBCXX_3.4.15' not found (required by ./hack/libdfhack.so)
</pre>
<p>To fix this, simply remove the libstdc++ shipped with DF, it will fall back
to your system lib and everything will work fine:</p>
<pre class="literal-block">
cd /path/to/DF/
rm libs/libstdc++.so.6
</pre>
</div>
</div>
<div class="section" id="mac-os-x">
<h1><a class="toc-backref" href="#id9">Mac OS X</a></h1>
<p>If you are building on 10.6, please read the subsection below titled &quot;Snow Leopard Changes&quot; FIRST.</p>
<ol class="arabic">
<li><p class="first">Download and unpack a copy of the latest DF</p>
</li>
<li><p class="first">Install Xcode from Mac App Store</p>
</li>
<li><p class="first">Open Xcode, go to Preferences &gt; Downloads, and install the Command Line Tools.</p>
</li>
<li><p class="first">Install dependencies</p>
<blockquote>
<p>Option 1: Using MacPorts:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="http://www.macports.org/">Install MacPorts</a></li>
<li>Run <tt class="docutils literal">sudo port install gcc45 +universal cmake +universal <span class="pre">git-core</span> +universal</tt>
This will take some time—maybe hours, depending on your machine.</li>
</ul>
<p>At some point during this process, it may ask you to install a Java environment; let it do so.</p>
</blockquote>
<p>Option 2: Using Homebrew:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="http://brew.sh/">Install Homebrew</a> and run:</li>
<li><tt class="docutils literal">brew tap homebrew/versions</tt></li>
<li><tt class="docutils literal">brew install git</tt></li>
<li><tt class="docutils literal">brew install cmake</tt></li>
<li><tt class="docutils literal">brew install gcc45 <span class="pre">--enable-multilib</span></tt></li>
</ul>
</blockquote>
</blockquote>
</li>
<li><p class="first">Install perl dependencies</p>
<blockquote>
<ol class="arabic">
<li><p class="first"><tt class="docutils literal">sudo cpan</tt></p>
<p>If this is the first time you've run cpan, you will need to go through the setup
process. Just stick with the defaults for everything and you'll be fine.</p>
</li>
<li><p class="first"><tt class="docutils literal">install <span class="pre">XML::LibXML</span></tt></p>
</li>
<li><p class="first"><tt class="docutils literal">install <span class="pre">XML::LibXSLT</span></tt></p>
</li>
</ol>
</blockquote>
</li>
<li><p class="first">Get the dfhack source:</p>
<pre class="literal-block">
git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
</pre>
</li>
<li><p class="first">Set environment variables:</p>
</li>
</ol>
<blockquote>
<p>Macports:</p>
<pre class="literal-block">
export CC=/opt/local/bin/gcc-mp-4.5
export CXX=/opt/local/bin/g++-mp-4.5
</pre>
<p>Homebrew:</p>
<pre class="literal-block">
export CC=/usr/local/bin/gcc-4.5
export CXX=/usr/local/bin/g++-4.5
</pre>
</blockquote>
<ol class="arabic" start="8">
<li><p class="first">Build dfhack:</p>
<pre class="literal-block">
mkdir build-osx
cd build-osx
cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/path/to/DF/directory
make
make install
</pre>
</li>
</ol>
<div class="section" id="snow-leopard-changes">
<h2><a class="toc-backref" href="#id10">Snow Leopard Changes</a></h2>
<ol class="arabic">
<li><dl class="first docutils">
<dt>Add a step 6.2a (before Install XML::LibXSLT)::</dt>
<dd><p class="first last">In a separate Terminal window or tab, run:
<tt class="docutils literal">sudo ln <span class="pre">-s</span> /usr/include/libxml2/libxml /usr/include/libxml</tt></p>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Add a step 7a (before building)::</dt>
<dd><dl class="first last docutils">
<dt>In &lt;dfhack directory&gt;/library/LuaTypes.cpp, change line 467 to</dt>
<dd><p class="first last"><tt class="docutils literal">int len = <span class="pre">strlen((char*)ptr);</span></tt></p>
</dd>
</dl>
</dd>
</dl>
</li>
</ol>
</div>
<div class="section" id="yosemite-changes">
<h2><a class="toc-backref" href="#id11">Yosemite Changes</a></h2>
<p>If you have issues building on OS X Yosemite (or above), try definining the following environment variable:</p>
<blockquote>
export MACOSX_DEPLOYMENT_TARGET=10.9</blockquote>
</div>
</div>
<div class="section" id="windows">
<h1><a class="toc-backref" href="#id12">Windows</a></h1>
<p>On Windows, DFHack replaces the SDL library distributed with DF.</p>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id13">How to get the code</a></h2>
<p>DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
You will need some sort of Windows port of git, or a GUI. Some examples:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="http://msysgit.github.io/">http://msysgit.github.io/</a> - this is a command line version of git for windows. Most tutorials on git usage will apply.</li>
<li><a class="reference external" href="http://code.google.com/p/tortoisegit/">http://code.google.com/p/tortoisegit/</a> - this puts a pretty, graphical face on top of msysgit :)</li>
</ul>
</blockquote>
<p>The code resides here: <a class="reference external" href="https://github.com/DFHack/dfhack">https://github.com/DFHack/dfhack</a></p>
<p>If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address:</p>
<pre class="literal-block">
git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
</pre>
<p>The tortoisegit GUI should have the equivalent options included.</p>
<p>If you want to get really involved with the development, create an account on github, make a clone there and then use that as your remote repository instead. Detailed instructions are beyond the scope of this document. If you need help, join us on IRC (#dfhack channel on freenode).</p>
</div>
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id14">Dependencies</a></h2>
<p>First, you need <tt class="docutils literal">cmake</tt>. Get the win32 installer version from the official
site: <a class="reference external" href="http://www.cmake.org/cmake/resources/software.html">http://www.cmake.org/cmake/resources/software.html</a></p>
<p>It has the usual installer wizard. Make sure you let it add its binary folder
to your binary search PATH so the tool can be later run from anywhere.</p>
<p>You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient.
Grab it from Microsoft's site.</p>
<p>You'll also need the Visual Studio 2010 SP1 update.</p>
<p>For the code generation parts, you'll need perl with XML::LibXML and XML::LibXSLT. Strawberry Perl works nicely for this: http://strawberryperl.com/</p>
<p>If you already have a different version of perl (for example the one from cygwin), you can run into some trouble. Either remove the other perl install from PATH, or install libxml and libxslt for it instead. Strawberry perl works though and has all the required packages.</p>
</div>
<div class="section" id="id3">
<h2><a class="toc-backref" href="#id15">Build</a></h2>
<p>There are several different batch files in the <tt class="docutils literal">build</tt> folder along with a script that's used for picking the DF path.</p>
<p>First, run set_df_path.vbs and point the dialog that pops up at your DF folder that you want to use for development.
Next, run one of the scripts with <tt class="docutils literal">generate</tt> prefix. These create the MSVC solution file(s):</p>
<ul class="simple">
<li><tt class="docutils literal">all</tt> will create a solution with everything enabled (and the kitchen sink).</li>
<li><tt class="docutils literal">gui</tt> will pop up the cmake gui and let you pick and choose what to build. This is probably what you want most of the time. Set the options you are interested in, then hit configure, then generate. More options can appear after the configure step.</li>
<li><tt class="docutils literal">minimal</tt> will create a minimal solution with just the bare necessities - the main library and standard plugins.</li>
</ul>
<p>Then you can either open the solution with MSVC or use one of the msbuild scripts:</p>
<ul class="simple">
<li>Scripts with <tt class="docutils literal">build</tt> prefix will only build.</li>
<li>Scripts with <tt class="docutils literal">install</tt> prefix will build DFHack and install it to the previously selected DF path.</li>
<li>Scripts with <tt class="docutils literal">package</tt> prefix will build and create a .zip package of DFHack.</li>
</ul>
<p>When you open the solution in MSVC, make sure you never use the Debug builds. Those aren't
binary-compatible with DF. If you try to use a debug build with DF, you'll only get crashes.
So pick either Release or RelWithDebInfo build and build the INSTALL target.</p>
<p>The <tt class="docutils literal">debug</tt> scripts actually do RelWithDebInfo builds.</p>
</div>
</div>
<div class="section" id="build-types">
<h1><a class="toc-backref" href="#id16">Build types</a></h1>
<p><tt class="docutils literal">cmake</tt> allows you to pick a build type by changing this
variable: <tt class="docutils literal">CMAKE_BUILD_TYPE</tt></p>
<pre class="literal-block">
cmake .. -DCMAKE_BUILD_TYPE:string=BUILD_TYPE
</pre>
<p>Without specifying a build type or 'None', cmake uses the
<tt class="docutils literal">CMAKE_CXX_FLAGS</tt> variable for building.</p>
<p>Valid and useful build types include 'Release', 'Debug' and
'RelWithDebInfo'. 'Debug' is not available on Windows.</p>
</div>
<div class="section" id="using-the-library-as-a-developer">
<h1><a class="toc-backref" href="#id17">Using the library as a developer</a></h1>
<p>Currently, the most direct way to use the library is to write a plugin that can be loaded by it.
All the plugins can be found in the 'plugins' folder. There's no in-depth documentation
on how to write one yet, but it should be easy enough to copy one and just follow the pattern.</p>
<p>Other than through plugins, it is possible to use DFHack via remote access interface, or by writing Lua scripts.</p>
<p>The most important parts of DFHack are the Core, Console, Modules and Plugins.</p>
<ul class="simple">
<li>Core acts as the centerpiece of DFHack - it acts as a filter between DF and SDL and synchronizes the various plugins with DF.</li>
<li>Console is a thread-safe console that can be used to invoke commands exported by Plugins.</li>
<li>Modules actually describe the way to access information in DF's memory. You can get them from the Core. Most modules are split into two parts: high-level and low-level. Higl-level is mostly method calls, low-level publicly visible pointers to DF's data structures.</li>
<li>Plugins are the tools that use all the other stuff to make things happen. A plugin can have a list of commands that it exports and an onupdate function that will be called each DF game tick.</li>
</ul>
<p>Rudimentary API documentation can be built using doxygen (see build options with <tt class="docutils literal">ccmake</tt> or <tt class="docutils literal"><span class="pre">cmake-gui</span></tt>).</p>
<p>DFHack consists of variously licensed code, but invariably weak copyleft.
The main license is zlib/libpng, some bits are MIT licensed, and some are BSD licensed.</p>
<p>Feel free to add your own extensions and plugins. Contributing back to
the dfhack repository is welcome and the right thing to do :)</p>
<div class="section" id="df-data-structure-definitions">
<h2><a class="toc-backref" href="#id18">DF data structure definitions</a></h2>
<p>DFHack uses information about the game data structures, represented via xml files in the library/xml/ submodule.</p>
<p>Data structure layouts are described in files following the df.*.xml name pattern. This information is transformed by a perl script into C++ headers describing the structures, and associated metadata for the Lua wrapper. These headers and data are then compiled into the DFHack libraries, thus necessitating a compatibility break every time layouts change; in return it significantly boosts the efficiency and capabilities of DFHack code.</p>
<p>Global object addresses are stored in symbols.xml, which is copied to the dfhack release package and loaded as data at runtime.</p>
</div>
<div class="section" id="remote-access-interface">
<h2><a class="toc-backref" href="#id19">Remote access interface</a></h2>
<p>DFHack supports remote access by exchanging Google protobuf messages via a TCP socket. Both the core and plugins can define remotely accessible methods. The <tt class="docutils literal"><span class="pre">dfhack-run</span></tt> command uses this interface to invoke ordinary console commands.</p>
<p>Currently the supported set of requests is limited, because the developers don't know what exactly is most useful.</p>
<p>Protocol client implementations exist for Java and C#.</p>
</div>
</div>
</div>
</body>
</html>

@ -1,410 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Contributing to DFHACK</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="contributing-to-dfhack">
<h1 class="title">Contributing to DFHACK</h1>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#id1" id="id2">Contributing to DFHack</a><ul>
<li><a class="reference internal" href="#code-format" id="id3">Code Format</a></li>
<li><a class="reference internal" href="#how-to-get-new-code-into-dfhack" id="id4">How to get new code into DFHack</a></li>
<li><a class="reference internal" href="#memory-research" id="id5">Memory research</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="id1">
<h1><a class="toc-backref" href="#id2">Contributing to DFHack</a></h1>
<p>Several things should be kept in mind when contributing to DFHack.</p>
<div class="section" id="code-format">
<h2><a class="toc-backref" href="#id3">Code Format</a></h2>
<ul class="simple">
<li>Four space indents for C++. Never use tabs for indentation in any language.</li>
<li>LF (Unix style) line terminators</li>
<li>Avoid trailing whitespace</li>
<li>UTF-8 encoding</li>
<li>For C++:<ul>
<li>Opening and closing braces on their own lines or opening brace at the end of the previous line</li>
<li>Braces placed at original indent level if on their own lines</li>
<li>#includes should be sorted. C++ libraries first, then dfhack modules, then df structures, then local includes. Within each category they should be sorted alphabetically. This policy is currently broken by most C++ files but try to follow it if you can.</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="how-to-get-new-code-into-dfhack">
<h2><a class="toc-backref" href="#id4">How to get new code into DFHack</a></h2>
<ul class="simple">
<li>Submit pull requests to the develop branch, not the master branch. The master branch always points at the most recent release.</li>
<li>Use new branches for each feature/fix so that your changes can be merged independently.</li>
<li>If possible, compile on multiple platforms</li>
<li>Do update NEWS/Contributors.rst</li>
<li>Do <strong>NOT</strong> run fix-texts.sh or update .html files (except to locally test changes to .rst files)</li>
<li>Create a Github Pull Request once finished</li>
<li>Work done against <a class="reference external" href="http://github.com/DFHack/dfhack/issues">issues</a> that are tagged &quot;bug report&quot; gets priority<ul>
<li>Submit ideas and bug reports as issues on github. Posts in the forum thread are also acceptable but can get missed or forgotten more easily.</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="memory-research">
<h2><a class="toc-backref" href="#id5">Memory research</a></h2>
<p>If you want to do memory research, you'll need some tools and some knowledge.
In general, you'll need a good memory viewer and optionally something
to look at machine code without getting crazy :)</p>
<p>Good windows tools include:</p>
<ul class="simple">
<li>Cheat Engine</li>
<li>IDA Pro 5.0 (freely available for non-commercial use)</li>
</ul>
<p>Good linux tools:</p>
<ul class="simple">
<li>angavrilov's df-structures gui (visit us on IRC for details).</li>
<li>edb (Evan's Debugger)</li>
<li>IDA Pro 5.0 running under Wine</li>
<li>Some of the tools residing in the <tt class="docutils literal">legacy</tt> dfhack branch.</li>
</ul>
<p>Using publicly known information and analyzing the game's data is preferred.</p>
</div>
</div>
</div>
</body>
</html>

@ -1,59 +0,0 @@
######################
Contributing to DFHACK
######################
.. contents::
Contributing to DFHack
======================
Several things should be kept in mind when contributing to DFHack.
-----------
Code Format
-----------
* Four space indents for C++. Never use tabs for indentation in any language.
* LF (Unix style) line terminators
* Avoid trailing whitespace
* UTF-8 encoding
* For C++:
* Opening and closing braces on their own lines or opening brace at the end of the previous line
* Braces placed at original indent level if on their own lines
* #includes should be sorted. C++ libraries first, then dfhack modules, then df structures, then local includes. Within each category they should be sorted alphabetically. This policy is currently broken by most C++ files but try to follow it if you can.
-------------------------------
How to get new code into DFHack
-------------------------------
* Submit pull requests to the ``develop`` branch, not the master branch. The master branch always points at the most recent release.
* Use new branches for each feature/fix so that your changes can be merged independently (i.e. not the master or develop branch of your fork).
* If possible, compile on multiple platforms
* Update NEWS and Contributors.rst when applicable
* Do **NOT** run fixTexts.sh or update .html files (except to locally test changes to .rst files)
* Create a Github Pull Request once finished
* Work done against `issues <http://github.com/DFHack/dfhack/issues>`_ that are tagged "bug report" gets priority
* Submit ideas and bug reports as issues on Github. Posts in the forum thread are also acceptable but can get missed or forgotten more easily.
---------------
Memory research
---------------
If you want to do memory research, you'll need some tools and some knowledge.
In general, you'll need a good memory viewer and optionally something
to look at machine code without getting crazy :)
Good windows tools include:
* Cheat Engine
* IDA Pro 5.0 (freely available for non-commercial use)
Good linux tools:
* angavrilov's df-structures gui (visit us on IRC for details).
* edb (Evan's Debugger)
* IDA Pro 5.0 running under Wine
* Some of the tools residing in the ``legacy`` dfhack branch.
Using publicly known information and analyzing the game's data is preferred.

@ -1,703 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>Contributors</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="contributors">
<h1 class="title">Contributors</h1>
<p>If you belong here and are missing, please add yourself and send me (peterix) a pull request :-)</p>
<p>The following is a list of people who have contributed to <strong>DFHack</strong>.</p>
<table border="1" class="docutils">
<colgroup>
<col width="31%" />
<col width="27%" />
<col width="43%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Name</th>
<th class="head">Github</th>
<th class="head">Email</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Petr Mrázek</td>
<td>peterix</td>
<td><a class="reference external" href="mailto:peterix&#64;gmail.com">peterix&#64;gmail.com</a></td>
</tr>
<tr><td>Alexander Gavrilov</td>
<td>angavrilov</td>
<td><a class="reference external" href="mailto:angavrilov&#64;gmail.com">angavrilov&#64;gmail.com</a></td>
</tr>
<tr><td>doomchild</td>
<td>doomchild</td>
<td><a class="reference external" href="mailto:lee.crabtree&#64;gmail.com">lee.crabtree&#64;gmail.com</a></td>
</tr>
<tr><td>Quietust</td>
<td>quietust</td>
<td><a class="reference external" href="mailto:quietust&#64;gmail.com">quietust&#64;gmail.com</a></td>
</tr>
<tr><td>jj</td>
<td>jjyg</td>
<td><a class="reference external" href="mailto:john-git&#64;ofjj.net">john-git&#64;ofjj.net</a></td>
</tr>
<tr><td>Warmist</td>
<td>warmist</td>
<td><a class="reference external" href="mailto:warmist&#64;gmail.com">warmist&#64;gmail.com</a></td>
</tr>
<tr><td>Robert Heinrich</td>
<td>rh73</td>
<td><a class="reference external" href="mailto:robertheinrich73&#64;googlemail.com">robertheinrich73&#64;googlemail.com</a></td>
</tr>
<tr><td>simon</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:simon&#64;banquise.net">simon&#64;banquise.net</a></td>
</tr>
<tr><td>Kelly Martin</td>
<td>ab9rf</td>
<td><a class="reference external" href="mailto:kelly.lynn.martin&#64;gmail.com">kelly.lynn.martin&#64;gmail.com</a></td>
</tr>
<tr><td>mizipzor</td>
<td>mizipzor</td>
<td><a class="reference external" href="mailto:mizipzor&#64;gmail.com">mizipzor&#64;gmail.com</a></td>
</tr>
<tr><td>Simon Jackson</td>
<td>sizeak</td>
<td><a class="reference external" href="mailto:sizeak&#64;hotmail.com">sizeak&#64;hotmail.com</a></td>
</tr>
<tr><td>belal</td>
<td>jimhester</td>
<td><a class="reference external" href="mailto:jimbelal&#64;gmail.com">jimbelal&#64;gmail.com</a></td>
</tr>
<tr><td>RusAnon</td>
<td>RusAnon</td>
<td><a class="reference external" href="mailto:rusanon&#64;dollchan.ru">rusanon&#64;dollchan.ru</a></td>
</tr>
<tr><td>Raoul XQ</td>
<td>raoulxq</td>
<td><a class="reference external" href="mailto:raoulxq&#64;gmail.com">raoulxq&#64;gmail.com</a></td>
</tr>
<tr><td>Matthew Cline</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:zelgadis&#64;sourceforge.net">zelgadis&#64;sourceforge.net</a></td>
</tr>
<tr><td>Mike Stewart</td>
<td>thewonderidiot</td>
<td><a class="reference external" href="mailto:thewonderidiot&#64;gmail.com">thewonderidiot&#64;gmail.com</a></td>
</tr>
<tr><td>Timothy Collett</td>
<td>danaris</td>
<td><a class="reference external" href="mailto:tcollett+github&#64;topazgryphon.org">tcollett+github&#64;topazgryphon.org</a></td>
</tr>
<tr><td>RossM</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:Ross&#64;Gnome">Ross&#64;Gnome</a></td>
</tr>
<tr><td>Tom Prince</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:tom.prince&#64;ualberta.net">tom.prince&#64;ualberta.net</a></td>
</tr>
<tr><td>Jared Adams</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:jaxad0127&#64;gmail.com">jaxad0127&#64;gmail.com</a></td>
</tr>
<tr><td>expwnent</td>
<td>expwnent</td>
<td>&nbsp;</td>
</tr>
<tr><td>Erik Youngren</td>
<td>Artanis</td>
<td><a class="reference external" href="mailto:artanis.00&#64;gmail.com">artanis.00&#64;gmail.com</a></td>
</tr>
<tr><td>Espen Wiborg</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:espen.wiborg&#64;telio.no">espen.wiborg&#64;telio.no</a></td>
</tr>
<tr><td>Tim Walberg</td>
<td>twalberg</td>
<td><a class="reference external" href="mailto:twalberg&#64;comcast.net">twalberg&#64;comcast.net</a></td>
</tr>
<tr><td>Mikko Juola</td>
<td>Noeda</td>
<td><a class="reference external" href="mailto:mikko.juola&#64;kolumbus.fi">mikko.juola&#64;kolumbus.fi</a></td>
</tr>
<tr><td>rampaging-poet</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:yrudoingthis&#64;hotmail.com">yrudoingthis&#64;hotmail.com</a></td>
</tr>
<tr><td>U-glouglou\simon</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:simon&#64;glouglou">simon&#64;glouglou</a></td>
</tr>
<tr><td>Clayton Hughes</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:clayton.hughes&#64;gmail.com">clayton.hughes&#64;gmail.com</a></td>
</tr>
<tr><td>zilpin</td>
<td>zilpin</td>
<td><a class="reference external" href="mailto:ziLpin&#64;gmail.com">ziLpin&#64;gmail.com</a></td>
</tr>
<tr><td>Will Rogers</td>
<td>wjrogers</td>
<td><a class="reference external" href="mailto:wjrogers&#64;gmail.com">wjrogers&#64;gmail.com</a></td>
</tr>
<tr><td>NMLittle</td>
<td>nmlittle</td>
<td><a class="reference external" href="mailto:nmlittle&#64;gmail.com">nmlittle&#64;gmail.com</a></td>
</tr>
<tr><td>root</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>reverb</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>Zhentar</td>
<td>Zhentar</td>
<td><a class="reference external" href="mailto:Zhentar&#64;gmail.com">Zhentar&#64;gmail.com</a></td>
</tr>
<tr><td>Valentin Ochs</td>
<td>Cat-Ion</td>
<td><a class="reference external" href="mailto:a&#64;0au.de">a&#64;0au.de</a></td>
</tr>
<tr><td>Priit Laes</td>
<td>plaes</td>
<td><a class="reference external" href="mailto:plaes&#64;plaes.org">plaes&#64;plaes.org</a></td>
</tr>
<tr><td>kmartin</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>Neil Little</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>rout</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:rout.mail+github&#64;gmail.com">rout.mail+github&#64;gmail.com</a></td>
</tr>
<tr><td>rofl0r</td>
<td>rofl0r</td>
<td><a class="reference external" href="mailto:retnyg&#64;gmx.net">retnyg&#64;gmx.net</a></td>
</tr>
<tr><td>harlanplayford</td>
<td>playfordh</td>
<td><a class="reference external" href="mailto:harlanplayford&#64;gmail.com">harlanplayford&#64;gmail.com</a></td>
</tr>
<tr><td>John Shade</td>
<td>gsvslto</td>
<td><a class="reference external" href="mailto:gsvslto&#64;gmail.com">gsvslto&#64;gmail.com</a></td>
</tr>
<tr><td>sami</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>potato</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>feng1st</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:nf_xp&#64;hotmail.com">nf_xp&#64;hotmail.com</a></td>
</tr>
<tr><td>comestible</td>
<td>nickrart</td>
<td><a class="reference external" href="mailto:nickolas.g.russell&#64;gmail.com">nickolas.g.russell&#64;gmail.com</a></td>
</tr>
<tr><td>Rumrusher</td>
<td>rumrusher</td>
<td><a class="reference external" href="mailto:Anuleakage&#64;yahoo.com">Anuleakage&#64;yahoo.com</a></td>
</tr>
<tr><td>Rinin</td>
<td>Rinin</td>
<td><a class="reference external" href="mailto:RininS&#64;Gmail.com">RininS&#64;Gmail.com</a></td>
</tr>
<tr><td>Raoul van Putten</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr><td>John Beisley</td>
<td>huin</td>
<td><a class="reference external" href="mailto:greatred&#64;gmail.com">greatred&#64;gmail.com</a></td>
</tr>
<tr><td>Feng</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:nf_xp&#64;hotmail.com">nf_xp&#64;hotmail.com</a></td>
</tr>
<tr><td>Donald Ruegsegger</td>
<td>hashaash</td>
<td><a class="reference external" href="mailto:druegsegger&#64;gmail.com">druegsegger&#64;gmail.com</a></td>
</tr>
<tr><td>Caldfir</td>
<td>caldfir</td>
<td><a class="reference external" href="mailto:caldfir&#64;hotmail.com">caldfir&#64;hotmail.com</a></td>
</tr>
<tr><td>Antalia</td>
<td>tamarakorr</td>
<td><a class="reference external" href="mailto:tamarakorr&#64;gmail.com">tamarakorr&#64;gmail.com</a></td>
</tr>
<tr><td>Angus Mezick</td>
<td>amezick</td>
<td><a class="reference external" href="mailto:amezick&#64;gmail.com">amezick&#64;gmail.com</a></td>
</tr>
<tr><td>Japa</td>
<td>JapaMala</td>
<td><a class="reference external" href="mailto:japa.mala.illo&#64;gmail.com">japa.mala.illo&#64;gmail.com</a></td>
</tr>
<tr><td>Putnam</td>
<td>Putnam3145</td>
<td>&nbsp;</td>
</tr>
<tr><td>Lethosor</td>
<td>lethosor</td>
<td>&nbsp;</td>
</tr>
<tr><td>PeridexisErrant</td>
<td>PeridexisErrant</td>
<td><a class="reference external" href="mailto:PeridexisErrant&#64;gmail.com">PeridexisErrant&#64;gmail.com</a></td>
</tr>
<tr><td>Eswald</td>
<td>eswald</td>
<td>&nbsp;</td>
</tr>
<tr><td>Ramblurr</td>
<td>Ramblurr</td>
<td>&nbsp;</td>
</tr>
<tr><td>MithrilTuxedo</td>
<td>MithrilTuxedo</td>
<td>&nbsp;</td>
</tr>
<tr><td>AndreasPK</td>
<td>AndreasPK</td>
<td>&nbsp;</td>
</tr>
<tr><td>Chris Dombroski</td>
<td>cdombroski</td>
<td>&nbsp;</td>
</tr>
<tr><td>Ben Lubar</td>
<td>BenLubar</td>
<td>&nbsp;</td>
</tr>
<tr><td>miffedmap</td>
<td>miffedmap</td>
<td>&nbsp;</td>
</tr>
<tr><td>scamtank</td>
<td>scamtank</td>
<td>&nbsp;</td>
</tr>
<tr><td>Mason11987</td>
<td>Mason11987</td>
<td>&nbsp;</td>
</tr>
<tr><td>James Logsdon</td>
<td>jlogsdon</td>
<td>&nbsp;</td>
</tr>
<tr><td>melkor217</td>
<td>melkor217</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>And these are the cool people who made <strong>Stonesense</strong>.</p>
<table border="1" class="docutils">
<colgroup>
<col width="31%" />
<col width="27%" />
<col width="43%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Name</th>
<th class="head">Github</th>
<th class="head">Email</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Kris Parker</td>
<td>kaypy</td>
<td>&nbsp;</td>
</tr>
<tr><td>Japa</td>
<td>JapaMala</td>
<td><a class="reference external" href="mailto:japa.mala.illo&#64;gmail.com">japa.mala.illo&#64;gmail.com</a></td>
</tr>
<tr><td>Jonas Ask</td>
<td>&nbsp;</td>
<td><a class="reference external" href="mailto:jonask84&#64;gmail.com">jonask84&#64;gmail.com</a></td>
</tr>
<tr><td>Petr Mrázek</td>
<td>peterix</td>
<td><a class="reference external" href="mailto:peterix&#64;gmail.com">peterix&#64;gmail.com</a>&gt;</td>
</tr>
<tr><td>Caldfir</td>
<td>caldfir</td>
<td><a class="reference external" href="mailto:aitken.tim&#64;gmail.com">aitken.tim&#64;gmail.com</a></td>
</tr>
<tr><td>8Z</td>
<td>8Z</td>
<td><a class="reference external" href="mailto:git8z&#64;ya.ru">git8z&#64;ya.ru</a></td>
</tr>
<tr><td>Alexander Gavrilov</td>
<td>angavrilov</td>
<td><a class="reference external" href="mailto:angavrilov&#64;gmail.com">angavrilov&#64;gmail.com</a></td>
</tr>
<tr><td>Timothy Collett</td>
<td>danaris</td>
<td><a class="reference external" href="mailto:tcollett+github&#64;topazgryphon.org">tcollett+github&#64;topazgryphon.org</a></td>
</tr>
<tr><td>Lethosor</td>
<td>lethosor</td>
<td>&nbsp;</td>
</tr>
<tr><td>Eswald</td>
<td>eswald</td>
<td>&nbsp;</td>
</tr>
<tr><td>PeridexisErrant</td>
<td>PeridexisErrant</td>
<td><a class="reference external" href="mailto:PeridexisErrant&#64;gmail.com">PeridexisErrant&#64;gmail.com</a></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

@ -1,8 +1,8 @@
-------------------------------------------------------------------------------- License of DFHack
License of dfhack =================
https://github.com/peterix/dfhack https://github.com/peterix/dfhack
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com) Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
::
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -23,11 +23,13 @@ must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
--------------------------------------------------------------------------------
License of the used XML reader library License of the used XML reader library
======================================
http://www.sourceforge.net/projects/tinyxml
www.sourceforge.net/projects/tinyxml Original code, 2.0 and earlier, copyright 2000-2006 Lee Thomason (http://www.grinninglizard.com)
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) ::
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -48,43 +50,39 @@ must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
--------------------------------------------------------------------------------
* dirent.h - dirent API for Microsoft Visual Studio dirent.h - dirent API for Microsoft Visual Studio
* =================================================
* Copyright (C) 2006 Toni Ronkko Copyright (C) 2006 Toni Ronkko
* ::
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the Permission is hereby granted, free of charge, to any person obtaining
* ``Software''), to deal in the Software without restriction, including a copy of this software and associated documentation files (the
* without limitation the rights to use, copy, modify, merge, publish, "Software"), to deal in the Software without restriction, including
* distribute, sublicense, and/or sell copies of the Software, and to without limitation the rights to use, copy, modify, merge, publish,
* permit persons to whom the Software is furnished to do so, subject to distribute, sublicense, and/or sell copies of the Software, and to
* the following conditions: permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* OTHER DEALINGS IN THE SOFTWARE. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
Parts of dfhack are based on linenoise:
linenoise.c -- guerrilla line editing library against the idea that a linenoise.c
line editing lib needs to be 20,000 lines of C code. ===========
Parts of dfhack are based on linenoise: a line editing library against the
You can find the latest source code at: idea that a line editing lib needs to be 20,000 lines of C code.
http://github.com/antirez/linenoise You can find the latest source code at http://github.com/antirez/linenoise
::
Does a number of crazy assumptions that happen to be true in 99.9999% of
the 2010 UNIX computers around.
--------------------------------------------------------------------------------
Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
@ -114,9 +112,11 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
UTF-8 Decoder
=============
See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
::
Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
@ -137,9 +137,11 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
luafilesystem
=============
Parts of dfhack are based on luafilesystem: Parts of dfhack are based on luafilesystem:
::
Copyright (c) 2003-2014 Kepler Project. Copyright (c) 2003-2014 Kepler Project.
@ -163,8 +165,9 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
-------------------------------------------------------------------------------- jsoncpp
jsoncpp license ========
::
Copyright (c) 2007-2010 Baptiste Lepilleur Copyright (c) 2007-2010 Baptiste Lepilleur
@ -188,11 +191,10 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
--------------------------------------------------------------------------------
JSON.lua license
Copyright 2010-2014 Jeffrey Friedl JSON.lua
http://regex.info/blog/ ========
Copyright 2010-2014 Jeffrey Friedl, http://regex.info/blog/
Latest version: http://regex.info/blog/lua/json Latest version: http://regex.info/blog/lua/json

File diff suppressed because it is too large Load Diff

121
NEWS

@ -1,4 +1,14 @@
.. comment
This is the changelog file for DFHack. If you add or change anything, note
it here under the heading "DFHack Future", in the appropriate section.
Items within each section are listed in alphabetical order to minimise merge
conflicts. Try to match the style and level of detail of the other entries.
DFHack Future DFHack Future
=============
::
Internals Internals
A method for caching screen output is now available to Lua (and C++) A method for caching screen output is now available to Lua (and C++)
Developer plugins can be ignored on startup by setting the DFHACK_NO_DEV_PLUGINS environment variable Developer plugins can be ignored on startup by setting the DFHACK_NO_DEV_PLUGINS environment variable
@ -11,6 +21,7 @@ DFHack Future
Multiple contexts can now be specified when adding keybindings Multiple contexts can now be specified when adding keybindings
Keybindings can now use F10-F12 and 0-9 Keybindings can now use F10-F12 and 0-9
Plugin system is no longer restricted to plugins that exist on startup Plugin system is no longer restricted to plugins that exist on startup
dfhack.init file locations significantly generalized
Lua Lua
Scripts can be enabled with the built-in enable/disable commands Scripts can be enabled with the built-in enable/disable commands
A new function, reqscript(), is available as a safer alternative to script_environment() A new function, reqscript(), is available as a safer alternative to script_environment()
@ -30,12 +41,21 @@ DFHack Future
modtools/create-unit: create new units from nothing modtools/create-unit: create new units from nothing
modtools/equip-item: a script to equip items on units modtools/equip-item: a script to equip items on units
points: set number of points available at embark screen points: set number of points available at embark screen
Vjek's script collection:
- armoks-blessing: Adjust all attributes, personality, age and skills of all dwarves in play
- brainwash: brainwash a dwarf (modifying their personality)
- elevate-mental: elevate all the mental attributes of a unit
- elevate-physical: elevate all the physical attributes of a unit
- make-legendary: modify skill(s) of a single unit
- pref-adjust: Adjust all preferences of all dwarves in play
- rejuvenate: make any "old" dwarf 20 years old
New tweaks New tweaks
embark-profile-name: Allows the use of lowercase letters when saving embark profiles embark-profile-name: Allows the use of lowercase letters when saving embark profiles
kitchen-keys: Fixes DF kitchen meal keybindings kitchen-keys: Fixes DF kitchen meal keybindings
kitchen-prefs-color: Changes color of enabled items to green in kitchen preferences kitchen-prefs-color: Changes color of enabled items to green in kitchen preferences
kitchen-prefs-empty: Fixes a layout issue with empty kitchen tabs kitchen-prefs-empty: Fixes a layout issue with empty kitchen tabs
scripts/modtools/create-item: arguments are named more clearly, and you can specify the creator to be the unit with id df.global.unit_next_id-1 (useful in conjunction with modtools/create-unit) scripts/modtools/create-item: arguments are named more clearly, and you can specify the creator to be
the unit with id df.global.unit_next_id-1 (useful in conjunction with modtools/create-unit)
scripts/teleport.lua is now compatible with the script_environment/reqscript system. scripts/teleport.lua is now compatible with the script_environment/reqscript system.
Fixes Fixes
Plugins with vmethod hooks can now be reloaded on OS X Plugins with vmethod hooks can now be reloaded on OS X
@ -51,7 +71,9 @@ DFHack Future
help: now recognizes built-in commands, like "help" help: now recognizes built-in commands, like "help"
manipulator: fixed crash when selecting custom professions when none are found manipulator: fixed crash when selecting custom professions when none are found
remotefortressreader: fixed crash when attempting to send map info when no map was loaded remotefortressreader: fixed crash when attempting to send map info when no map was loaded
search: fixed crash in unit list after cancelling a job search:
- fixed crash in unit list after cancelling a job
- fixed crash when disabling stockpile category after searching in a subcategory
stockpiles: now checks/sanitizes filenames when saving stockpiles: now checks/sanitizes filenames when saving
stocks: fixed a crash when right-clicking stocks: fixed a crash when right-clicking
steam-engine: steam-engine:
@ -63,6 +85,12 @@ DFHack Future
- Note: Existing stuck jobs must be cancelled and re-added - Note: Existing stuck jobs must be cancelled and re-added
zone: Fixed a crash when using "zone set" (and a few other potential crashes) zone: Fixed a crash when using "zone set" (and a few other potential crashes)
Misc Improvements Misc Improvements
DFHack documentation:
- massively reorganised, into files of more readable size
- added many missing entries
- indexes, internal links, offline search all documents
- includes documentation of linked projects (df-structures, 3rdparty scripts)
- better HTML generation with Sphinx
autolabor: autolabor:
- Stopped modification of labors that shouldn't be modified for brokers/diplomats - Stopped modification of labors that shouldn't be modified for brokers/diplomats
- Prioritize skilled dwarves more efficiently - Prioritize skilled dwarves more efficiently
@ -103,6 +131,9 @@ DFHack Future
embark-tools nano: 1x1 embarks are now possible in vanilla 0.40.24 embark-tools nano: 1x1 embarks are now possible in vanilla 0.40.24
DFHack 0.40.24-r3 DFHack 0.40.24-r3
=================
::
Internals Internals
Ruby library now included on OS X - ruby scripts should work on OS X 10.10 Ruby library now included on OS X - ruby scripts should work on OS X 10.10
libstdc++ should work with older versions of OS X libstdc++ should work with older versions of OS X
@ -150,9 +181,9 @@ DFHack 0.40.24-r3
stockflow: Fixed ballistic arrow head orders stockflow: Fixed ballistic arrow head orders
stockflow: Now convinces the bookkeeper to update records more often stockflow: Now convinces the bookkeeper to update records more often
zone: Stopped crash when scrolling cage owner list zone: Stopped crash when scrolling cage owner list
Removed
Misc Improvements Misc Improvements
building-hacks: Added a way to allow building to work even if it consumes more power than is available. Added setPower/getPower functions. building-hacks: Added a way to allow building to work even if it consumes more power
than is available. Added setPower/getPower functions.
catsplosion: Can now trigger pregnancies in (most) other creatures catsplosion: Can now trigger pregnancies in (most) other creatures
exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities
manipulator: manipulator:
@ -162,10 +193,14 @@ DFHack 0.40.24-r3
remotefortressreader: Exposes more information remotefortressreader: Exposes more information
DFHack 0.40.24-r2 DFHack 0.40.24-r2
=================
::
Internals Internals
Lua scripts can set environment variables of each other with dfhack.run_script_with_env. Lua scripts can set environment variables of each other with dfhack.run_script_with_env.
Lua scripts can now call each others internal nonlocal functions with dfhack.script_environment(scriptName).functionName(arg1,arg2). Lua scripts can now call each others internal nonlocal functions with dfhack.script_environment(scriptName).functionName(arg1,arg2).
eventful Lua reactions no longer require LUA_HOOK as a prefix: you can register a callback for the completion of any reaction with a name eventful Lua reactions no longer require LUA_HOOK as a prefix: you can register a
callback for the completion of any reaction with a name
Filesystem module now provides file access/modification times and can list directories (normally and recursively) Filesystem module now provides file access/modification times and can list directories (normally and recursively)
Units Module: New functions: Units Module: New functions:
isWar isWar
@ -203,18 +238,21 @@ DFHack 0.40.24-r2
hfs-pit should work now hfs-pit should work now
Autobutcher takes gelding into account Autobutcher takes gelding into account
init.lua existence checks should be more reliable (notably when using non-English locales) init.lua existence checks should be more reliable (notably when using non-English locales)
New Plugins
New Scripts
New Tweaks
Removed
Misc Improvements Misc Improvements
Multiline commands are now possible inside dfhack.init scripts. See dfhack.init-example for example usage. Multiline commands are now possible inside dfhack.init scripts. See dfhack.init-example for example usage.
DFHack 0.40.24-r1 DFHack 0.40.24-r1
=================
::
Internals Internals
CMake shouldn't cache DFHACK_RELEASE anymore. People may need to manually update/delete their CMake cache files to get rid of it. CMake shouldn't cache DFHACK_RELEASE anymore. People may need to manually update/delete
their CMake cache files to get rid of it.
DFHack 0.40.24-r0 DFHack 0.40.24-r0
=================
::
Internals Internals
EventManager: fixed crash error with EQUIPMENT_CHANGE event. EventManager: fixed crash error with EQUIPMENT_CHANGE event.
key modifier state exposed to Lua key modifier state exposed to Lua
@ -227,11 +265,13 @@ DFHack 0.40.24-r0
Removed Removed
embark.lua embark.lua
needs_porting/* needs_porting/*
New Tweaks
Misc Improvements Misc Improvements
added support for searching more lists added support for searching more lists
DFHack 0.40.23-r1 DFHack 0.40.23-r1
=================
::
Internals Internals
plugins will not be loaded if globals they specify as required are not located (should prevent some crashes) plugins will not be loaded if globals they specify as required are not located (should prevent some crashes)
Fixes Fixes
@ -272,7 +312,9 @@ DFHack 0.40.23-r1
further work on needs_porting further work on needs_porting
DFHack 0.40.19-r1 DFHack 0.40.19-r1
Internals: =================
::
Fixes: Fixes:
typo fix in modtools/reaction-trigger typo fix in modtools/reaction-trigger
modtools/item-trigger should now work with item types modtools/item-trigger should now work with item types
@ -288,8 +330,12 @@ DFHack 0.40.19-r1
autolabor plugin: add an optional talent pool parameter autolabor plugin: add an optional talent pool parameter
DFHack 0.40.16-r1 DFHack 0.40.16-r1
=================
::
Internals: Internals:
EventManager should handle INTERACTION triggers a little better. It still can get confused about who did what but only rarely. EventManager should handle INTERACTION triggers a little better. It still can get confused
about who did what but only rarely.
EventManager should no longer trigger REPORT events for old reports after loading a save. EventManager should no longer trigger REPORT events for old reports after loading a save.
lua/persist-table.lua: a convenient way of using persistent tables of arbitrary structure and dimension in Lua lua/persist-table.lua: a convenient way of using persistent tables of arbitrary structure and dimension in Lua
Fixes: Fixes:
@ -329,6 +375,9 @@ DFHack 0.40.16-r1
No longer writes empty .history files No longer writes empty .history files
DFHack 0.40.15-r1 DFHack 0.40.15-r1
=================
::
Fixes: Fixes:
- mousequery: Fixed behavior when selecting a tile on the lowest z-level - mousequery: Fixed behavior when selecting a tile on the lowest z-level
Internals: Internals:
@ -340,6 +389,9 @@ DFHack 0.40.15-r1
- tweak fast-trade: Switching the fast-trade keybinding to Shift-Up/Shift-Down, due to Select All conflict - tweak fast-trade: Switching the fast-trade keybinding to Shift-Up/Shift-Down, due to Select All conflict
DFHack 0.40.14-r1 DFHack 0.40.14-r1
=================
::
Internals: Internals:
- The DFHack console can now be disabled by setting the DFHACK_DISABLE_CONSOLE - The DFHack console can now be disabled by setting the DFHACK_DISABLE_CONSOLE
environment variable: "DFHACK_DISABLE_CONSOLE=1 ./dfhack" environment variable: "DFHACK_DISABLE_CONSOLE=1 ./dfhack"
@ -363,11 +415,13 @@ DFHack 0.40.14-r1
- manager-quantity: Removes the limit of 30 jobs per manager order - manager-quantity: Removes the limit of 30 jobs per manager order
- civ-view-agreement: Fixes overlapping text on the "view agreement" screen - civ-view-agreement: Fixes overlapping text on the "view agreement" screen
- nestbox-color: Fixes the color of built nestboxes - nestbox-color: Fixes the color of built nestboxes
Misc Improvements: Misc Improvements:
- exportlegends.lua can now handle site maps - exportlegends.lua can now handle site maps
DFHack 0.40.13-r1 DFHack 0.40.13-r1
=================
::
Internals: Internals:
- unified spatter structs - unified spatter structs
- added ruby df.print_color(color, string) method for dfhack console - added ruby df.print_color(color, string) method for dfhack console
@ -376,6 +430,9 @@ DFHack 0.40.13-r1
- fixed superdwarf - fixed superdwarf
DFHack 0.40.12-r1 DFHack 0.40.12-r1
=================
::
Fixes: Fixes:
- possible crash fixed for hack-wish - possible crash fixed for hack-wish
- updated search to not conflict with BUILDJOB_SUSPEND - updated search to not conflict with BUILDJOB_SUSPEND
@ -383,7 +440,8 @@ DFHack 0.40.12-r1
New plugins: New plugins:
- hotkeys (by Falconne): Shows ingame viewscreen with all dfhack keybindings active in current mode. - hotkeys (by Falconne): Shows ingame viewscreen with all dfhack keybindings active in current mode.
- automelt: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting) - automelt: allows marking stockpiles for automelt
(i.e. any items placed in stocpile will be designated for melting)
Misc Improvements: Misc Improvements:
- now you can use @ to print things in interactive Lua with subtley different semantics - now you can use @ to print things in interactive Lua with subtley different semantics
@ -396,6 +454,8 @@ DFHack 0.40.12-r1
- Close file after loading a binary patch. - Close file after loading a binary patch.
DFHack 0.40.11-r1 DFHack 0.40.11-r1
=================
::
Internals: Internals:
- Plugins on OS X now use ".plug.dylib" as an extension instead of ".plug.so" - Plugins on OS X now use ".plug.dylib" as an extension instead of ".plug.so"
@ -408,10 +468,13 @@ DFHack 0.40.11-r1
- Various documentation fixes and updates - Various documentation fixes and updates
DFHack v0.40.10-r1 DFHack v0.40.10-r1
==================
A few bugfixes. A few bugfixes.
DFHack v0.40.08-r2 DFHack v0.40.08-r2
==================
::
Internals: Internals:
supported per save script folders supported per save script folders
@ -461,9 +524,12 @@ DFHack v0.40.08-r2
add-syndrome.lua add-syndrome.lua
add a syndrome to a unit or remove one add a syndrome to a unit or remove one
anonymous-script.lua anonymous-script.lua
execute an lua script defined by a string. For example, 'scripts/modtools/anonymous-script "print(args[2] .. args[1])" one two' will print 'twoone'. Useful for the *-trigger scripts. execute an lua script defined by a string. For example,
'scripts/modtools/anonymous-script "print(args[2] .. args[1])" one two'
will print 'twoone'. Useful for the *-trigger scripts.
force.lua force.lua
forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature forces events: caravan, migrants, diplomat, megabeast, curiousbeast,
mischievousbeast, flier, siege, nightcreature
item-trigger.lua item-trigger.lua
triggers commands based on equipping, unequipping, and wounding units with items triggers commands based on equipping, unequipping, and wounding units with items
interaction-trigger.lua interaction-trigger.lua
@ -493,12 +559,6 @@ DFHack v0.40.08-r2
transform-unit.lua transform-unit.lua
shapeshifts a unit, possibly permanently shapeshifts a unit, possibly permanently
New commands:
New tweaks:
New plugins:
Misc improvements: Misc improvements:
new function in utils.lua for standardized argument processing new function in utils.lua for standardized argument processing
@ -510,10 +570,13 @@ DFHack v0.40.08-r2
devel/printArgs plugin converted to scripts/devel/print-args.lua devel/printArgs plugin converted to scripts/devel/print-args.lua
DFHack v0.40.08-r1 DFHack v0.40.08-r1
==================
Was a mistake. Don't use it. Was a mistake. Don't use it.
DFHack v0.34.11-r5 DFHack v0.34.11-r5
==================
::
Internals: Internals:
- support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua). - support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua).
@ -548,7 +611,8 @@ DFHack v0.34.11-r5
- automelt: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting) - automelt: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting)
- embark-tools: implementations of Embark Anywhere, Nano Embark, and a few other embark-related utilities - embark-tools: implementations of Embark Anywhere, Nano Embark, and a few other embark-related utilities
- building-hacks: Allows to add custom functionality and/or animations to buildings. - building-hacks: Allows to add custom functionality and/or animations to buildings.
- petcapRemover: triggers pregnancies in creatures so that you can effectively raise the default pet population cap from the default 50 - petcapRemover: triggers pregnancies in creatures so that you can effectively raise the default
pet population cap from the default 50
Misc improvements: Misc improvements:
- plant: move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands - plant: move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands
@ -571,6 +635,8 @@ DFHack v0.34.11-r5
hungry/thirsty if there is a free replacement hungry/thirsty if there is a free replacement
DFHack v0.34.11-r4 DFHack v0.34.11-r4
==================
::
New commands: New commands:
- diggingInvaders - allows invaders to dig and/or deconstruct walls and buildings in order to get at your dwarves. - diggingInvaders - allows invaders to dig and/or deconstruct walls and buildings in order to get at your dwarves.
@ -592,7 +658,8 @@ DFHack v0.34.11-r4
disable by default disable by default
reorganized special tags reorganized special tags
minimized error spam minimized error spam
reset policies: if the target already has an instance of the syndrome you can skip, add another instance, reset the timer, or add the full duration to the time remaining reset policies: if the target already has an instance of the syndrome you can skip,
add another instance, reset the timer, or add the full duration to the time remaining
- core: fix SC_WORLD_(UN)LOADED event for arena mode - core: fix SC_WORLD_(UN)LOADED event for arena mode
- exterminate: renamed from slayrace, add help message, add butcher mode - exterminate: renamed from slayrace, add help message, add butcher mode
- fastdwarf: fixed bug involving fastdwarf and teledwarf being on at the same time - fastdwarf: fixed bug involving fastdwarf and teledwarf being on at the same time
@ -619,6 +686,8 @@ DFHack v0.34.11-r4
- Once: easy way to make sure something happens once per run of DF, such as an error message - Once: easy way to make sure something happens once per run of DF, such as an error message
DFHack v0.34.11-r3 DFHack v0.34.11-r3
==================
::
Internals: Internals:
- support for displaying active keybindings properly. - support for displaying active keybindings properly.
@ -698,6 +767,8 @@ DFHack v0.34.11-r3
Makes the game assign jobs every time you pause. Makes the game assign jobs every time you pause.
DFHack v0.34.11-r2 DFHack v0.34.11-r2
==================
::
Internals: Internals:
- full support for Mac OS X. - full support for Mac OS X.

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<!-- DO NOT CHANGE THIS FILE - it redirects to the actual documentation. -->
<!-- If the page is not found, you can read the raw docs in the docs folder. -->
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=./docs/html/README.html">
<script type="text/javascript">
window.location.href = "./docs/html/README.html"
</script>
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow the <a href='./docs/html/README.html'>link to the documentation.</a>
</body>
</html>

@ -0,0 +1,59 @@
Welcome to DFHack's documentation!
==================================
Introduction
============
DFHack is a Dwarf Fortress memory access library, distributed with scripts
and plugins implementing a wide variety of useful functions and tools.
For users, it provides a significant suite of bugfixes and interface
enhancements by default, and more can be enabled. There are also many tools
(such as `plugins/workflow` or `plugins/autodump`) which can make life easier.
You can even add third-party scripts and plugins to do almost anything!
For modders, DFHack makes many things possible. Custom reactions, new
interactions, magic creature abilities, and more can be set through `scripts <scripts/modtools>`
and custom raws. Non-standard DFHack scripts and inits can be stored in the
raw directory, making raws or saves fully self-contained for distribution -
or for coexistence in a single DF install, even with incompatible components.
For developers, DFHack unites the various ways tools access DF memory and
allows easier development of new tools. As an open-source project under
`various copyleft licences <license>`, contributions are welcome.
Documentation
=============
DFHack documentation is generated by Sphinx. Check out the table of contents
below, or the sources in the `docs folder`_!
.. _`docs folder`: ./docs
User Manual:
.. toctree::
:maxdepth: 2
docs/Core
docs/Plugins
docs/Scripts
Other Contents:
.. toctree::
:maxdepth: 1
docs/Authors
docs/Licenses
docs/Changelog
For Developers:
.. toctree::
:maxdepth: 1
docs/Contributing
docs/Compile
docs/Lua API
library/xml/SYNTAX
docs/Binpatches

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -241,6 +241,11 @@ log-region
# add information to item viewscreens # add information to item viewscreens
view-item-info enable view-item-info enable
gui/load-screen enable
#roses-init must be called on world load if you are using his persist-delay, class system, etc
#base/roses-init -all
####################################################### #######################################################
# Apply binary patches at runtime # # Apply binary patches at runtime #
####################################################### #######################################################

@ -1,12 +1,13 @@
Contributors List of Authors
============ ===============
If you belong here and are missing, please add yourself and send me (peterix) a pull request :-) The following is a list of people who have contributed to DFHack, in no
particular order.
The following is a list of people who have contributed to **DFHack**. If you should be here and aren't, please get in touch or make a pull request!
======================= ==================== =========================== ======================= ======================= ===========================
Name Github Email Name Github Email
======================= ==================== =========================== ======================= ======================= ===========================
Petr Mrázek peterix peterix@gmail.com Petr Mrázek peterix peterix@gmail.com
Alexander Gavrilov angavrilov angavrilov@gmail.com Alexander Gavrilov angavrilov angavrilov@gmail.com
doomchild doomchild lee.crabtree@gmail.com doomchild doomchild lee.crabtree@gmail.com
@ -81,22 +82,8 @@ acwatkins acwatkins
Wes Malone wesQ3 Wes Malone wesQ3
Michon van Dooren MaienM Michon van Dooren MaienM
Seth Woodworth sethwoodworth Seth Woodworth sethwoodworth
======================= ==================== =========================== Vjek
And these are the cool people who made **Stonesense**.
======================= ==================== ===========================
Name Github Email
======================= ==================== ===========================
Kris Parker kaypy Kris Parker kaypy
Japa JapaMala japa.mala.illo@gmail.com
Jonas Ask jonask84@gmail.com Jonas Ask jonask84@gmail.com
Petr Mrázek peterix peterix@gmail.com>
Caldfir caldfir aitken.tim@gmail.com
8Z 8Z git8z@ya.ru 8Z 8Z git8z@ya.ru
Alexander Gavrilov angavrilov angavrilov@gmail.com ======================= ======================= ===========================
Timothy Collett danaris tcollett+github@topazgryphon.org
Lethosor lethosor
Eswald eswald
PeridexisErrant PeridexisErrant PeridexisErrant@gmail.com
======================= ==================== ===========================

@ -0,0 +1,180 @@
.. _binpatches:
######################
Patching the DF binary
######################
Writing scripts and plugins for DFHack is not the only way to modify Dwarf
Fortress. Before DFHack, it was common for tools to manually patch the
binary to change behaviour, and DFHack still contains tools to do this via
the `scripts/binpatch` command.
.. warning::
We recommend using a script or plugin instead of a raw patch if
at all possible - that way your work will work for many versions
across multiple operating systems. There's a reason nobody has
written patches since ``0.34.11``!
.. contents::
Getting a patch
===============
There are no binary patches available for Dwarf Fortress versions after 0.34.11
This system is kept for the chance that someone will find it useful, so some
hints on how to write your own follow. This will require disassembly and
decent skill in `memory research <contributing-memory-research>`.
* The patches are expected to be encoded in text format used by IDA.
* See `this commit <https://github.com/DFHack/dfhack/commit/8a9e3d1a728>`_,
when the 0.34.11 patches were discarded, for example patches.
* `Issue #546 <https://github.com/DFHack/dfhack/issues/546>`_ is about the
future of the binpatches, and may be useful reading.
If you want to write a patch, the armory patches discussed here and documented
below would probably be the best place to start.
Using a patch
=============
There are two methods to apply a patch.
Patching at runtime
-------------------
The `scripts/binpatch` script checks, applies or removes binary patches
directly in memory at runtime::
binpatch [check|apply|remove] <patchname>
If the name of the patch has no extension or directory separators, the
script uses ``hack/patches/<df-version>/<name>.dif``, thus auto-selecting
the version appropriate for the currently loaded executable.
This is the preferred method; it's easier to debug, does not cause persistent
problems, and leaves file checksums alone. As with many other commands, users
can simply add it to ``dfhack.init`` to reapply the patch every time DF is run.
Patching on disk
----------------
.. warning::
This method of patching is deprecated, and may be removed without notice.
You should use the runtime patching option above.
DFHack includes a small stand-alone utility for applying and removing
binary patches from the game executable. Use it from the regular operating
system console:
``binpatch check "Dwarf Fortress.exe" patch.dif``
Checks and prints if the patch is currently applied.
``binpatch apply "Dwarf Fortress.exe" patch.dif``
Applies the patch, unless it is already applied or in conflict.
``binpatch remove "Dwarf Fortress.exe" patch.dif``
Removes the patch, unless it is already removed.
If you use a permanent patch under OSX or Linux, you must update
``symbols.xml`` with the new checksum of the executable. Find the relevant
section, and add a new line::
<md5-hash value='????????????????????????????????'/>
In order to find the correct value of the hash, look into stderr.log;
DFHack prints an error there if it does not recognize the hash.
.. _binpatches/needs-patch:
Tools reliant on binpatches
===========================
Some DFHack tools require the game to be patched to work. As no patches
are currently available, the full description of each is included here.
fix-armory
----------
Enables a fix for storage of squad equipment in barracks.
Specifically, it prevents your haulers from moving squad equipment
to stockpiles, and instead queues jobs to store it on weapon racks,
armor stands, and in containers.
.. note::
In order to actually be used, weapon racks have to be patched and
manually assigned to a squad. See `scripts/gui/assign-rack`.
Note that the buildings in the armory are used as follows:
* Weapon racks (when patched) are used to store any assigned weapons.
Each rack belongs to a specific squad, and can store up to 5 weapons.
* Armor stands belong to specific squad members and are used for
armor and shields.
* Cabinets are used to store assigned clothing for a specific squad member.
They are **never** used to store owned clothing.
* Chests (boxes, etc) are used for a flask, backpack or quiver assigned
to the squad member. Due to a probable bug, food is dropped out of the
backpack when it is stored.
.. warning::
Although armor stands, cabinets and chests properly belong only to one
squad member, the owner of the building used to create the barracks will
randomly use any containers inside the room. Thus, it is recommended to
always create the armory from a weapon rack.
Contrary to the common misconception, all these uses are controlled by the
*Individual Equipment* usage flag. The *Squad Equipment* flag is actually
intended for ammo, but the game does even less in that area than for armor
and weapons. This plugin implements the following rules almost from scratch:
* Combat ammo is stored in chests inside rooms with Squad Equipment enabled.
* If a chest is assigned to a squad member due to Individual Equipment also
being set, it is only used for that squad's ammo; otherwise, any squads
with Squad Equipment on the room will use all of the chests at random.
* Training ammo is stored in chests inside archery ranges designated from
archery targets, and controlled by the same Train flag as archery training
itself. This is inspired by some defunct code for weapon racks.
There are some minor traces in the game code to suggest that the first of
these rules is intended by Toady; the rest are invented by this plugin.
gui/assign-rack
---------------
Bind to a key (the example config uses P), and activate when viewing a weapon
rack in the ``q`` mode.
.. image:: images/assign-rack.png
This script is part of a group of related fixes to make the armory storage
work again. The existing issues are:
* Weapon racks have to each be assigned to a specific squad, like with
beds/boxes/armor stands and individual squad members, but nothing in
the game does this. This issue is what this script addresses.
* Even if assigned by the script, **the game will unassign the racks again
without a binary patch**. This patch is called ``weaponrack-unassign``,
and has not been updated since 0.34.11. See `the bug report`_ for more info.
.. _`the bug report`: http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
* Haulers still take equipment stored in the armory away to the stockpiles,
unless `plugins/fix-armory` is used.
The script interface simply lets you designate one of the squads that
are assigned to the barracks/armory containing the selected stand as
the intended user. In order to aid in the choice, it shows the number
of currently assigned racks for every valid squad.

@ -0,0 +1,7 @@
#########
Changelog
#########
.. contents::
.. include:: ../NEWS

@ -1,24 +1,29 @@
############### ################
Building DFHACK Compiling DFHack
############### ################
.. important::
You don't need to compile DFHack unless you're developing plugins or working on the core.
For users, modders, and authors of scripts it's better to download the latest release instead.
.. contents:: .. contents::
:depth: 2
=================== ===================
How to get the code How to get the code
=================== ===================
DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git. DFHack doesn't have any kind of system of code snapshots in place, so you will have to
The code resides here: https://github.com/DFHack/dfhack get code from the github repository using git.
The code resides at https://github.com/DFHack/dfhack
On Linux and OS X, having a 'git' package installed is the minimal requirement (see below for OS X instructions), On Linux and OS X, having a ``git`` package installed is the minimal requirement (see below for OS X instructions),
but some sort of git gui or git integration for your favorite text editor/IDE will certainly help. but some sort of git gui or git integration for your favorite text editor/IDE will certainly help.
On Windows, you will need some sort of Windows port of git, or a GUI. Some examples: On Windows, you will need some sort of Windows port of git, or a GUI. Some examples:
* http://msysgit.github.io/ - this is a command line version of git for windows. Most tutorials on git usage will apply. * http://msysgit.github.io - this is a command line version of git for windows.
* http://code.google.com/p/tortoisegit/ - this puts a pretty, graphical face on top of msysgit Most tutorials on git usage will apply.
* http://code.google.com/p/tortoisegit - this puts a pretty, graphical face on top of msysgit
The code resides here: https://github.com/DFHack/dfhack
To get the code:: To get the code::
@ -28,14 +33,30 @@ To get the code::
If your version of git does not support the ``--recursive`` flag, you will need to omit it and run If your version of git does not support the ``--recursive`` flag, you will need to omit it and run
``git submodule update --init`` after entering the dfhack directory. ``git submodule update --init`` after entering the dfhack directory.
If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address instead:: If you just want to compile DFHack or work on it by contributing patches, it's quite
enough to clone from the read-only address instead::
git clone --recursive git://github.com/DFHack/dfhack.git git clone --recursive git://github.com/DFHack/dfhack.git
cd dfhack cd dfhack
The tortoisegit GUI should have the equivalent options included. If you want to get really involved with the development, create an account on
Github, make a clone there and then use that as your remote repository instead.
Detailed instructions are beyond the scope of this document. If you need help,
join us on IRC (#dfhack channel on freenode).
If you want to get really involved with the development, create an account on Github, make a clone there and then use that as your remote repository instead. Detailed instructions are beyond the scope of this document. If you need help, join us on IRC (#dfhack channel on freenode). ===========
Build types
===========
``cmake`` allows you to pick a build type by changing this
variable: ``CMAKE_BUILD_TYPE`` ::
cmake .. -DCMAKE_BUILD_TYPE:string=BUILD_TYPE
Without specifying a build type or 'None', cmake uses the
``CMAKE_CXX_FLAGS`` variable for building.
Valid and useful build types include 'Release', 'Debug' and
'RelWithDebInfo'. 'Debug' is not available on Windows.
===== =====
Linux Linux
@ -55,15 +76,18 @@ Before you can build anything, you'll also need ``cmake``. It is advisable to al
``ccmake`` on distributions that split the cmake package into multiple parts. ``ccmake`` on distributions that split the cmake package into multiple parts.
You also need perl and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts). You also need perl and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts).
You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt') or through ``cpan``. You should be able to find them in your distro repositories (on Arch linux
``perl-xml-libxml`` and ``perl-xml-libxslt``) or through ``cpan``.
To build Stonesense, you'll also need OpenGL headers. To build Stonesense, you'll also need OpenGL headers.
Some additional dependencies for other distros are listed on the `wiki <https://github.com/DFHack/dfhack/wiki/Linux-dependencies>`_. Some additional dependencies for other distros are listed on the
`wiki <https://github.com/DFHack/dfhack/wiki/Linux-dependencies>`_.
Build Build
===== =====
Building is fairly straightforward. Enter the ``build`` folder (or create an empty folder in the DFHack directory to use instead) and start the build like this:: Building is fairly straightforward. Enter the ``build`` folder (or create an
empty folder in the DFHack directory to use instead) and start the build like this::
cd build cd build
cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/home/user/DF cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/home/user/DF
@ -185,7 +209,8 @@ Snow Leopard Changes
Yosemite Changes Yosemite Changes
================ ================
If you have issues building on OS X Yosemite (or above), try definining the following environment variable: If you have issues building on OS X Yosemite (or above), try definining the
following environment variable::
export MACOSX_DEPLOYMENT_TARGET=10.9 export MACOSX_DEPLOYMENT_TARGET=10.9
@ -207,9 +232,13 @@ Grab it from Microsoft's site.
You'll also need the Visual Studio 2010 SP1 update. You'll also need the Visual Studio 2010 SP1 update.
For the code generation parts, you'll need perl with XML::LibXML and XML::LibXSLT. Strawberry Perl works nicely for this: http://strawberryperl.com/ For the code generation parts, you'll need perl with XML::LibXML and XML::LibXSLT.
`Strawberry Perl <http://strawberryperl.com>`_ works nicely for this.
If you already have a different version of perl (for example the one from cygwin), you can run into some trouble. Either remove the other perl install from PATH, or install libxml and libxslt for it instead. Strawberry perl works though and has all the required packages. If you already have a different version of perl (for example the one from cygwin),
you can run into some trouble. Either remove the other perl install from PATH, or
install libxml and libxslt for it instead. Strawberry perl works though and has
all the required packages.
Build Build
===== =====
@ -233,65 +262,3 @@ binary-compatible with DF. If you try to use a debug build with DF, you'll only
So pick either Release or RelWithDebInfo build and build the INSTALL target. So pick either Release or RelWithDebInfo build and build the INSTALL target.
The ``debug`` scripts actually do RelWithDebInfo builds. The ``debug`` scripts actually do RelWithDebInfo builds.
===========
Build types
===========
``cmake`` allows you to pick a build type by changing this
variable: ``CMAKE_BUILD_TYPE``
::
cmake .. -DCMAKE_BUILD_TYPE:string=BUILD_TYPE
Without specifying a build type or 'None', cmake uses the
``CMAKE_CXX_FLAGS`` variable for building.
Valid and useful build types include 'Release', 'Debug' and
'RelWithDebInfo'. 'Debug' is not available on Windows.
================================
Using the library as a developer
================================
Currently, the most direct way to use the library is to write a plugin that can be loaded by it.
All the plugins can be found in the 'plugins' folder. There's no in-depth documentation
on how to write one yet, but it should be easy enough to copy one and just follow the pattern.
Other than through plugins, it is possible to use DFHack via remote access interface, or by writing Lua scripts.
The most important parts of DFHack are the Core, Console, Modules and Plugins.
* Core acts as the centerpiece of DFHack - it acts as a filter between DF and SDL and synchronizes the various plugins with DF.
* Console is a thread-safe console that can be used to invoke commands exported by Plugins.
* Modules actually describe the way to access information in DF's memory. You can get them from the Core. Most modules are split into two parts: high-level and low-level. High-level is mostly method calls, low-level publicly visible pointers to DF's data structures.
* Plugins are the tools that use all the other stuff to make things happen. A plugin can have a list of commands that it exports and an onupdate function that will be called each DF game tick.
Rudimentary API documentation can be built using doxygen (see build options with ``ccmake`` or ``cmake-gui``).
DFHack consists of variously licensed code, but invariably weak copyleft.
The main license is zlib/libpng, some bits are MIT licensed, and some are BSD licensed.
Feel free to add your own extensions and plugins. Contributing back to
the dfhack repository is welcome and the right thing to do :)
DF data structure definitions
=============================
DFHack uses information about the game data structures, represented via xml files in the library/xml/ submodule.
Data structure layouts are described in files following the df.\*.xml name pattern. This information is transformed by a perl script into C++ headers describing the structures, and associated metadata for the Lua wrapper. These headers and data are then compiled into the DFHack libraries, thus necessitating a compatibility break every time layouts change; in return it significantly boosts the efficiency and capabilities of DFHack code.
Global object addresses are stored in symbols.xml, which is copied to the dfhack release package and loaded as data at runtime.
Remote access interface
=======================
DFHack supports remote access by exchanging Google protobuf messages via a TCP socket. Both the core and plugins can define remotely accessible methods. The ``dfhack-run`` command uses this interface to invoke ordinary console commands.
Currently the supported set of requests is limited, because the developers don't know what exactly is most useful.
Protocol client implementations exist for Java and C#.

@ -0,0 +1,184 @@
###########################
How to contribute to DFHack
###########################
.. contents::
You can help without coding
===========================
DFHack is a software project, but there's a lot more to it than programming.
If you're not comfortable pregramming, you can help by:
* reporting bugs and incomplete documentation,
* improving the documentation,
* finding third-party scripts to add,
* writing tutorials for newbies
All those things are crucial, and all under-represented. So if that's
your thing, the rest of this document is about contributing code - go get started!
Documentation Standards
=======================
Whether you're adding new code or just fixing old documentation (and there's plenty),
there are a few important standards for completeness and consistent style. Treat
this section as a guide rather than iron law, match the surrounding text, and you'll
be fine.
Every script, plugin, or command should be documented. This is an active project,
and the best place to put this documentation might change. For now, it's usually
either ``docs/Scripts.rst`` or ``docs/Plugins.rst``.
Where the heading for a section is also the name of a command, the spelling
and case should exactly match the command to enter in the DFHack command line.
Try to keep lines within 80-100 characters, so it's readable in plain text -
Sphinx (our documentation system) will make sure paragraphs flow.
If there aren't many options or examples to show, they can go in a paragraph of
text. Use double-backticks to put commands in monospaced font, like this::
You can use ``cleanall scattered x`` to dump tattered or abandoned items.
If the command takes more than three arguments, format the list as a table
called Options. The table *only* lists arguments, not full commands.
Input values are specified in angle brackets. Example::
Options:
:arg1: A simple argument.
:arg2 <input>: Does something based on the input value.
:Very long argument:
Is very specific.
To demonstrate usage - useful mainly when the syntax is complicated, list the
full command with arguments in monospaced font, then indent the next line and
describe the effect::
``resume all``
Resumes all suspended constructions.
If it would be helpful to mention another DFHack command, don't just type the
name - add a hyperlink! Specify the link target in backticks, and it will be
replaced with the corresponding title and linked: eg ```plugins/autolabor```
=> `plugins/autolabor`. Link targets should be the path to the file
described (without file extension), and placed above the heading of that
section like this::
.. _plugins/autolabor:
autolabor
=========
Add link targets if you need them, but otherwise plain headings are preferred.
Contributing Code
=================
Several things should be kept in mind when contributing code to DFHack.
Code Format
-----------
* Four space indents for C++. Never use tabs for indentation in any language.
* LF (Unix style) line terminators
* Avoid trailing whitespace
* UTF-8 encoding
* For C++:
* Opening and closing braces on their own lines or opening brace at the end of the previous line
* Braces placed at original indent level if on their own lines
* #includes should be sorted. C++ libraries first, then dfhack modules, then df structures,
then local includes. Within each category they should be sorted alphabetically.
How to get new code into DFHack
-------------------------------
* Submit pull requests to the ``develop`` branch, not the master branch. The master branch always points at the most recent release.
* Use new branches for each feature/fix so that your changes can be merged independently (i.e. not the master or develop branch of your fork).
* If possible, compile on multiple platforms when changing anything that compiles
* Update NEWS and doc/Authors.rst when applicable
* Create a Github Pull Request once finished
* Work done against Github issues tagged "bug report" get priority
* Submit ideas and bug reports as issues on Github. Posts in the forum thread can easily get missed or forgotten.
.. _contributing-memory-research:
Memory research
---------------
If you want to do memory research, you'll need some tools and some knowledge.
In general, you'll need a good memory viewer and optionally something
to look at machine code without getting crazy :)
Using publicly known information and analyzing the game's data is preferred.
Good windows tools include:
* Cheat Engine
* IDA Pro 5.0 (freely available for non-commercial use)
Good linux tools:
* angavrilov's df-structures gui (visit us on IRC for details).
* edb (Evan's Debugger)
* IDA Pro 5.0 running under Wine
* Some of the tools residing in the ``legacy`` dfhack branch.
Using the library as a developer
================================
Currently, the most direct way to use the library is to write a script or plugin that can be loaded by it.
All the plugins can be found in the 'plugins' folder. There's no in-depth documentation
on how to write one yet, but it should be easy enough to copy one and just follow the pattern.
``plugins/skeleton/skeleton.cpp`` is provided for this purpose.
Other than through plugins, it is possible to use DFHack via remote access interface, or by writing Lua scripts.
The most important parts of DFHack are the Core, Console, Modules and Plugins.
* Core acts as the centerpiece of DFHack - it acts as a filter between DF and
SDL and synchronizes the various plugins with DF.
* Console is a thread-safe console that can be used to invoke commands exported by Plugins.
* Modules actually describe the way to access information in DF's memory. You
can get them from the Core. Most modules are split into two parts: high-level
and low-level. High-level is mostly method calls, low-level publicly visible
pointers to DF's data structures.
* Plugins are the tools that use all the other stuff to make things happen.
A plugin can have a list of commands that it exports and an onupdate function
that will be called each DF game tick.
Rudimentary API documentation can be built using doxygen (see build options
with ``ccmake`` or ``cmake-gui``). The full DFHack documentation is built
with Sphinx, which runs automatically at compile time.
DFHack consists of variously licensed code, but invariably weak copyleft.
The main license is zlib/libpng, some bits are MIT licensed, and some are
BSD licensed. See the `license` document for more information.
Feel free to add your own extensions and plugins. Contributing back to
the dfhack repository is welcome and the right thing to do :)
DF data structure definitions
-----------------------------
DFHack uses information about the game data structures, represented via xml files
in the ``library/xml/`` submodule.
See https://github.com/DFHack/df-structures, and the documentation linked in the index.
Data structure layouts are described in files following the ``df.\*.xml`` name pattern.
This information is transformed by a perl script into C++ headers describing the
structures, and associated metadata for the Lua wrapper. These headers and data
are then compiled into the DFHack libraries, thus necessitating a compatibility
break every time layouts change; in return it significantly boosts the efficiency
and capabilities of DFHack code.
Global object addresses are stored in ``symbols.xml``, which is copied to the dfhack
release package and loaded as data at runtime.
Remote access interface
-----------------------
DFHack supports remote access by exchanging Google protobuf messages via a TCP
socket. Both the core and plugins can define remotely accessible methods. The
``dfhack-run`` command uses this interface to invoke ordinary console commands.
Currently the supported set of requests is limited, because the developers don't
know what exactly is most useful. ``remotefortressreader`` provides a fairly
comprehensive interface for visualisers such as Armok Vision.

@ -0,0 +1,306 @@
###########
DFHack Core
###########
.. contents::
==============
Getting DFHack
==============
The project is currently hosted at http://www.github.com/
Recent releases are available in source and binary formats `on the releases
page`_, while the binaries for releases 0.40.15-r1 to 0.34.11-r4 are on DFFD_.
Even older versions are available here_.
.. _`on the releases page`: http://github.com/DFHack/dfhack/releases
.. _DFFD: http://dffd.bay12games.com/search.php?string=DFHack&id=15
.. _here: http://dethware.org/dfhack/download
All new releases are announced in `the bay12 forums thread`_, which is also a
good place for discussion and questions.
.. _`the Bay12 DFHack thread`:
.. _`the bay12 forums thread`: http://www.bay12forums.com/smf/index.php?topic=139553
If this sounds too complicated, you might prefer to `get a Starter Pack`_.
These are packages for new players or those who don't want to set up everything
themselves, and are available - with DFHack configured - for all OSes.
.. _`get a Starter Pack`: http://dwarffortresswiki.org/index.php/Utility:Lazy_Newb_Pack
Compatibility
=============
DFHack is available for Windows (XP or later), Linux (any modern distribution),
or OS X (10.6.8 to 10.9).
Most releases only support the version of DF mentioned in their title - for
example, DFHack 0.40.24-r2 only supports DF 0.40.24 - but some releases
support earlier DF versions as well. Wherever possible, use the latest version
built for the target version of DF.
On Windows, DFHack is compatible with the SDL version of DF, but not the legacy version.
It is also possible to use the Windows DFHack with Wine under Linux and OS X.
Installation/Removal
====================
Installing DFhack involves copying files into your DF folder.
Copy the files from a release archive so that:
* On Windows, ``SDL.dll`` is replaced
* On Linux or OSX, the ``dfhack`` script is placed in the same folder as the ``df`` script
Uninstalling is basically the same, in reverse:
* On Windows, first delete ``SDL.dll`` and rename ``SDLreal.dll`` to ``SDL.dll``,
then remove the other DFHack files
* On Linux, remove the DFHack files.
The stonesense plugin might require some additional libraries on Linux.
If any of the plugins or dfhack itself refuses to load, check the ``stderr.log``
file created in your DF folder.
===============
Getting started
===============
If DFHack is installed correctly, it will automatically pop up a console
window once DF is started as usual on windows. Linux and Mac OS X require
running the dfhack script from the terminal, and will use that terminal for
the console.
**NOTE**: The ``dfhack-run`` executable is there for calling DFHack commands in
an already running DF+DFHack instance from external OS scripts and programs,
and is *not* the way how you use DFHack normally.
DFHack has a lot of features, which can be accessed by typing commands in the
console, or by mapping them to keyboard shortcuts. Most of the newer and more
user-friendly tools are designed to be at least partially used via the latter
way.
In order to set keybindings, you have to create a text configuration file
called ``dfhack.init``; the installation comes with an example version called
``dfhack.init-example``, which is fully functional, covers all of the recent
features and can be simply renamed to ``dfhack.init``. You are encouraged to look
through it to learn which features it makes available under which key combinations.
Using DFHack
============
DFHack basically extends what DF can do with something similar to the drop-down
console found in Quake engine games. On Windows, this is a separate command line
window. On Linux, the terminal used to launch the dfhack script is taken over
(so, make sure you start from a terminal). Basic interaction with dfhack
involves entering commands into the console. For some basic instructions,
use the ``help`` command. To list all possible commands, use the ``ls`` command.
Many commands have their own help or detailed description. You can use
``command help`` or ``command ?`` to show that.
The command line has some nice line editing capabilities, including history
that's preserved between different runs of DF (use up/down keys to go through
the history).
The second way to interact with DFHack is to bind the available commands
to in-game hotkeys. The old way to do this is via the hotkey/zoom menu (normally
opened with the ``h`` key). Binding the commands is done by assigning a command as
a hotkey name (with ``n``).
A new and more flexible way is the keybinding command in the dfhack console.
However, bindings created this way are not automatically remembered between runs
of the game, so it becomes necessary to use the dfhack.init file to ensure that
they are re-created every time it is loaded.
Interactive commands like `plugins/liquids` cannot be used as hotkeys.
Many commands come from plugins, which are stored in ``hack/plugins/``
and must be compiled with the same version of DFHack. Others come
from scripts, which are stored in ``hack/scripts``. Scripts are much
more flexible about versions, and easier to distribute - so most third-party
DFHack addons are scripts.
Something doesn't work, help!
=============================
First, don't panic :)
Second, dfhack keeps a few log files in DF's folder (``stderr.log`` and
``stdout.log``). Looking at these might help you solve the problem.
If it doesn't, you can ask for help in the forum thread or on IRC.
If you found a bug, you can report it in `the Bay12 DFHack thread`_,
`the issues tracker on github <https://github.com/DFHack/dfhack/issues>`_,
or visit `the #dfhack IRC channel on freenode
<https://webchat.freenode.net/?channels=dfhack>`_.
=============
Core Commands
=============
DFHack command syntax consists of a command name, followed by arguments separated
by whitespace. To include whitespace in an argument, quote it in double quotes.
To include a double quote character, use ``\"`` inside double quotes.
If the first non-whitespace character of a line is ``#``, the line is treated
as a comment, i.e. a silent no-op command.
When reading commands from dfhack.init or with the ``script`` command, if the final
character on a line is a backslash then the next uncommented line is considered a
continuation of that line, with the backslash deleted. Commented lines are skipped,
so it is possible to comment out parts of a command with the ``#`` character.
If the first non-whitespace character is ``:``, the command is parsed in a special
alternative mode: first, non-whitespace characters immediately following the ``:``
are used as the command name; the remaining part of the line, starting with the first
non-whitespace character *after* the command name, is used verbatim as the first argument.
The following two command lines are exactly equivalent::
:foo a b "c d" e f
foo "a b \"c d\" e f"
This is intended for commands like ``rb_eval`` that evaluate script language statements.
Almost all the commands support using the ``help <command-name>`` built-in command
to retrieve further help without having to look at this document. Alternatively,
some accept a ``help`` or ``?`` as an option on their command line.
.. note::
Some tools work by displaying dialogs or overlays in the game window.
In order to avoid confusion, these tools display the word "DFHack" while active. If they
merely add keybinding hints to existing screens, they use red instead of green for the key.
Init files
==========
DFHack allows users to automatically run commonly-used DFHack commands when DF is first
loaded, when a game is loaded, and when a game is unloaded.
Init scripts function the same way they would if the user manually typed in their contents,
but are much more convenient. If your DF folder contains at least one file with a name
following the format ``dfhack*.init`` where ``*`` is a placeholder for any string (including
the empty string), then all such files are executed in alphabetical order as init scripts when
DF is first loaded.
If your DF folder does not contain any such files, then DFHack will execute ``dfhack.init-example``
as an example of useful commands to be run automatically. If you want DFHack to do nothing on
its own, then create an empty ``dfhack.init`` file in the main DF directory, or delete ``dfhack.init-example``.
The file ``dfhack.init-example`` is included as an example for users to follow if they need DFHack
command executed automatically. We recommend modifying or deleting ``dfhack.init-example`` as
its settings will not be optimal for all players.
In order to facilitate savegave portability, mod merging, and general organization of init files,
DFHack supports multiple init files both in the main DF directory and save-specific init files in
the save folders.
DFHack looks for init files in three places.
It will look for them in the main DF directory, and in ``data/save/_____/raw`` and
``data/save/_____/raw/objects`` where ``_____`` is the name of the current savegame.
When a game is loaded, DFHack looks for files of the form ``onLoad*.init``, where
``*`` can be any string, including the empty string.
When a game is unloaded, DFHack looks for files of the form ``onUnload*.init``. Again,
these files may be in any of the above three places. All matching init files will be
executed in alphebetical order.
Setting keybindings
===================
To set keybindings, use the built-in ``keybinding`` command. Like any other
command it can be used at any time from the console, but it is most useful
in the DFHack init file.
Currently, any combinations of Ctrl/Alt/Shift with A-Z, 0-9, or F1-F12 are supported.
Possible ways to call the command:
``keybinding list <key>``
List bindings active for the key combination.
``keybinding clear <key> <key>...``
Remove bindings for the specified keys.
``keybinding add <key> "cmdline" "cmdline"...``
Add bindings for the specified key.
``keybinding set <key> "cmdline" "cmdline"...``
Clear, and then add bindings for the specified key.
The ``<key>`` parameter above has the following *case-sensitive* syntax::
[Ctrl-][Alt-][Shift-]KEY[@context[|context...]]
where the *KEY* part can be any recognized key and [] denote optional parts.
When multiple commands are bound to the same key combination, DFHack selects
the first applicable one. Later ``add`` commands, and earlier entries within one
``add`` command have priority. Commands that are not specifically intended for use
as a hotkey are always considered applicable.
The ``context`` part in the key specifier above can be used to explicitly restrict
the UI state where the binding would be applicable. If called without parameters,
the ``keybinding`` command among other things prints the current context string.
Only bindings with a ``context`` tag that either matches the current context fully,
or is a prefix ending at a ``/`` boundary would be considered for execution, i.e.
for context ``foo/bar/baz``, possible matches are any of ``@foo/bar/baz``, ``@foo/bar``,
``@foo`` or none. Multiple contexts can be specified by separating them with a
pipe (``|``) - for example, ``@foo|bar|baz/foo``.
Hotkeys
=======
Opens an in-game screen showing DFHack keybindings that are active in the current context.
.. image:: images/hotkeys.png
Type ``hotkeys`` into the DFHack console to open the screen, or bind the command to a
globally active hotkey. The default keybinding is ``Ctrl-F1``.
In-game Console
===============
The ``command-prompt`` plugin adds an in-game DFHack terminal, where you
can enter other commands. It's default keybinding is Ctrl-Shift-P.
Enabling plugins
================
Many plugins can be in a distinct enabled or disabled state. Some of
them activate and deactivate automatically depending on the contents
of the world raws. Others store their state in world data. However a
number of them have to be enabled globally, and the init file is the
right place to do it.
Most such plugins or scripts support the built-in ``enable`` and ``disable``
commands. Calling them at any time without arguments prints a list
of enabled and disabled plugins, and shows whether that can be changed
through the same commands.
To enable or disable plugins that support this, use their names as
arguments for the command::
enable manipulator search
Game progress
=============
die
---
Instantly kills DF without saving.
quicksave
---------
Save immediately, without exiting. Only available in fortress mode.
forcepause
----------
Forces DF to pause. This is useful when your FPS drops below 1 and you lose
control of the game. Activate with ``forcepause 1``; deactivate with ``forcepause 0``.
hide / show
-----------
Hides or shows the DFHack terminal window, respectively. To use ``show``, use
the in-game console (default keybinding ``Ctrl-Shift-P``). Only available on Windows.
nopause
-------
Disables pausing (both manual and automatic) with the exception of pause forced
by 'reveal hell'. This is nice for digging under rivers.

@ -0,0 +1,11 @@
.. _license:
########
Licenses
########
DFHack is distributed under a range of permissive and weakly copyleft licenses.
The core uses the ZLib license; the others are described below.
.. include:: ../LICENSE

@ -194,6 +194,10 @@ A container field can associate an enum to the container
reference, which allows accessing elements using string keys reference, which allows accessing elements using string keys
instead of numerical indices. instead of numerical indices.
Note that two-dimensional arrays in C++ (ie pointers to pointers)
are exposed to lua as one-dimensional. The best way to handle this
is probably ``array[x].value:_displace(y)``.
Implemented features: Implemented features:
* ``ref._enum`` * ``ref._enum``

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,326 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# DFHack documentation build configuration file, created by
# sphinx-quickstart on Tue Sep 22 17:34:54 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import fnmatch
import sys
import os
import shlex
from os import listdir
from os.path import isfile, join, isdir
#import sys
currentDir = '@CMAKE_CURRENT_SOURCE_DIR@'
def makeIncludeAll(directory, extension):
outputFile = join(directory,'include-all.rst')
#print(outputFile)
files = [ f for f in listdir(directory) if isfile(join(directory,f)) and f.endswith(extension) ]
files.sort()
out = open(outputFile, 'w')
for f in files:
#TODO: check if the file contains the BEGIN_DOCS string
#print(join(directory,f))
fstream = open(join(directory,f), 'r', encoding='utf8')
data = fstream.read().replace('\n','')
fstream.close()
if 'BEGIN_DOCS' in data:
out.write('.. include:: ' + join(directory,f) + '\n :start-after: BEGIN_DOCS\n :end-before: END_DOCS\n\n')
out.close()
def makeAllIncludeAll(directory, extension):
for root, subdirs, files in os.walk(directory):
if isdir(root):
makeIncludeAll(root, extension)
makeAllIncludeAll(currentDir + '/scripts', '.lua')
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = []
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'README'
# General information about the project.
project = 'DFHack'
copyright = '2015, The DFHack Team'
author = 'The DFHack Team'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#def get_version():
# """Return the DFHack version string, from CMakeLists.txt"""
# version, release = '', ''
# with open('CMakeLists.txt') as f:
# for s in f.readlines():
# if fnmatch.fnmatch(s.upper(), 'SET(DF_VERSION "?.??.??")\n'):
# version = s.upper().replace('SET(DF_VERSION "', '')
# elif fnmatch.fnmatch(s.upper(), 'SET(DFHACK_RELEASE "r*")\n'):
# release = s.upper().replace('SET(DFHACK_RELEASE "', '').lower()
# return (version + '-' + release).replace('")\n', '')
# The short X.Y version.
version = '@DFHACK_VERSION@'
# The full version, including alpha/beta/rc tags.
release = '@DFHACK_VERSION@'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['docs/_build/*', 'depends/*']
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = 'any'
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = '@SPHINX_THEME@'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = 'dfhack-icon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['../images']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'DFHackdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'DFHack.tex', 'DFHack Documentation',
'The DFHack Team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'dfhack', 'DFHack Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'DFHack', 'DFHack Documentation',
author, 'DFHack', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

@ -1,57 +0,0 @@
#!/bin/bash
# regenerate documentation after editing the .rst files. Requires python and docutils.
force=
reset=
while [ $# -gt 0 ]
do
case "$1" in
--force) force=1
;;
--reset) reset=1
;;
esac
shift
done
rst2html=$(which rst2html || which rst2html.py)
if [[ -z "$rst2html" ]]; then
echo "Docutils not found: See http://docutils.sourceforge.net/"
exit 1
fi
rst2html_version=$("$rst2html" --version | cut -d' ' -f3)
if [[ $(echo $rst2html_version | cut -d. -f2) -lt 12 ]]; then
echo "You are using docutils $rst2html_version. Docutils 0.12+ is recommended
to build these documents."
read -r -n1 -p "Continue? [y/N] " reply
echo
if [[ ! $reply =~ ^[Yy]$ ]]; then
exit
fi
fi
cd `dirname $0`
status=0
function process() {
if [ -n "$reset" ]; then
git checkout -- "$2"
elif [ "$1" -nt "$2" ] || [ -n "$force" ]; then
echo -n "Updating $2... "
if "$rst2html" --no-generator --no-datestamp "$1" "$2"; then
echo "Done"
else
status=1
fi
else
echo "$2 - up to date."
fi
}
process Readme.rst Readme.html
process Compile.rst Compile.html
process Lua\ API.rst Lua\ API.html
process Contributors.rst Contributors.html
process Contributing.rst Contributing.html
exit $status

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

@ -1,6 +1,11 @@
PROJECT (dfapi) PROJECT (dfapi)
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
# prevent CMake warnings about INTERFACE_LINK_LIBRARIES vs LINK_INTERFACE_LIBRARIES
IF(CMAKE_VERSION VERSION_GREATER "2.8.12")
CMAKE_POLICY(SET CMP0022 OLD)
ENDIF()
## build options ## build options
OPTION(BUILD_DEVEL "Install/package files required for development (For SDK)." OFF) OPTION(BUILD_DEVEL "Install/package files required for development (For SDK)." OFF)
OPTION(BUILD_DOXYGEN "Create/install/package doxygen documentation for DFHack (For SDK)." OFF) OPTION(BUILD_DOXYGEN "Create/install/package doxygen documentation for DFHack (For SDK)." OFF)
@ -298,7 +303,7 @@ SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
IF(APPLE) IF(APPLE)
SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework) SET(SDL_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/SDL.framework)
IF(NOT EXISTS ${SDL_LIBRARY}) IF(NOT EXISTS ${SDL_LIBRARY})
MESSAGE(FATAL_ERROR "SDL framework not found. Make sure CMAKE_INSTALL_PREFIX is specified and correct.") MESSAGE(SEND_ERROR "SDL framework not found. Make sure CMAKE_INSTALL_PREFIX is specified and correct.")
ENDIF() ENDIF()
SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib) SET(CXX_LIBRARY ${CMAKE_INSTALL_PREFIX}/libs/libstdc++.6.dylib)
SET(ZIP_LIBRARY /usr/lib/libz.dylib) SET(ZIP_LIBRARY /usr/lib/libz.dylib)
@ -372,12 +377,12 @@ install(DIRECTORY lua/
DESTINATION ${DFHACK_LUA_DESTINATION} DESTINATION ${DFHACK_LUA_DESTINATION}
FILES_MATCHING PATTERN "*.lua") FILES_MATCHING PATTERN "*.lua")
install(DIRECTORY ${dfhack_SOURCE_DIR}/scripts #install(DIRECTORY ${dfhack_SOURCE_DIR}/scripts
DESTINATION ${DFHACK_DATA_DESTINATION} # DESTINATION ${DFHACK_DATA_DESTINATION}
FILES_MATCHING PATTERN "*.lua" # FILES_MATCHING PATTERN "*.lua"
PATTERN "*.rb" # PATTERN "*.rb"
PATTERN "3rdparty" EXCLUDE # PATTERN "3rdparty" EXCLUDE
) # )
install(DIRECTORY ${dfhack_SOURCE_DIR}/patches install(DIRECTORY ${dfhack_SOURCE_DIR}/patches
DESTINATION ${DFHACK_DATA_DESTINATION} DESTINATION ${DFHACK_DATA_DESTINATION}

@ -32,6 +32,9 @@ distribution.
#include <cstring> #include <cstring>
#include <iterator> #include <iterator>
#include <sstream> #include <sstream>
#include <forward_list>
#include <type_traits>
#include <cstdarg>
using namespace std; using namespace std;
#include "Error.h" #include "Error.h"
@ -85,6 +88,7 @@ using df::global::world;
// FIXME: A lot of code in one file, all doing different things... there's something fishy about it. // FIXME: A lot of code in one file, all doing different things... there's something fishy about it.
static bool parseKeySpec(std::string keyspec, int *psym, int *pmod, std::string *pfocus = NULL); static bool parseKeySpec(std::string keyspec, int *psym, int *pmod, std::string *pfocus = NULL);
size_t loadScriptFiles(Core* core, color_ostream& out, const vector<std::string>& prefix, const std::string& folder);
struct Core::Cond struct Core::Cond
{ {
@ -465,7 +469,7 @@ void Core::getScriptPaths(std::vector<std::string> *dest)
string df_path = this->p->getPath(); string df_path = this->p->getPath();
for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it) for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it)
dest->push_back(*it); dest->push_back(*it);
if (df::global::world) { if (df::global::world && isWorldLoaded()) {
string save = World::ReadWorldFolder(); string save = World::ReadWorldFolder();
if (save.size()) if (save.size())
dest->push_back(df_path + "/data/save/" + save + "/raw/scripts"); dest->push_back(df_path + "/data/save/" + save + "/raw/scripts");
@ -1210,7 +1214,9 @@ static void run_dfhack_init(color_ostream &out, Core *core)
return; return;
} }
if (!core->loadScriptFile(out, "dfhack.init", true)) std::vector<std::string> prefixes(1, "dfhack");
size_t count = loadScriptFiles(core, out, prefixes, ".");
if (!count)
{ {
core->runCommand(out, "gui/no-dfhack-init"); core->runCommand(out, "gui/no-dfhack-init");
core->loadScriptFile(out, "dfhack.init-example", true); core->loadScriptFile(out, "dfhack.init-example", true);
@ -1829,37 +1835,92 @@ void Core::onUpdate(color_ostream &out)
Lua::Core::onUpdate(out); Lua::Core::onUpdate(out);
} }
void Core::handleLoadAndUnloadScripts(color_ostream& out, state_change_event event) { void getFilesWithPrefixAndSuffix(const std::string& folder, const std::string& prefix, const std::string& suffix, std::vector<std::string>& result) {
if (!df::global::world) //DFHACK_EXPORT int listdir (std::string dir, std::vector<std::string> &files);
std::vector<std::string> files;
DFHack::Filesystem::listdir(folder, files);
for ( size_t a = 0; a < files.size(); a++ ) {
if ( prefix.length() > files[a].length() )
continue;
if ( suffix.length() > files[a].length() )
continue;
if ( files[a].compare(0, prefix.length(), prefix) != 0 )
continue;
if ( files[a].compare(files[a].length()-suffix.length(), suffix.length(), suffix) != 0 )
continue;
result.push_back(files[a]);
}
return; return;
//TODO: use different separators for windows }
#ifdef _WIN32
static const std::string separator = "\\"; size_t loadScriptFiles(Core* core, color_ostream& out, const vector<std::string>& prefix, const std::string& folder) {
#else vector<std::string> scriptFiles;
static const std::string separator = "/"; for ( size_t a = 0; a < prefix.size(); a++ ) {
#endif getFilesWithPrefixAndSuffix(folder, prefix[a], ".init", scriptFiles);
std::string rawFolder = "data" + separator + "save" + separator + (df::global::world->cur_savegame.save_dir) + separator + "raw" + separator; }
switch(event) { std::sort(scriptFiles.begin(), scriptFiles.end());
case SC_WORLD_LOADED: size_t result = 0;
loadScriptFile(out, "onLoadWorld.init", true); for ( size_t a = 0; a < scriptFiles.size(); a++ ) {
loadScriptFile(out, rawFolder + "onLoadWorld.init", true); result++;
loadScriptFile(out, rawFolder + "onLoad.init", true); core->loadScriptFile(out, folder + "/" + scriptFiles[a], true);
break; }
case SC_WORLD_UNLOADED: return result;
loadScriptFile(out, "onUnloadWorld.init", true); }
loadScriptFile(out, rawFolder + "onUnloadWorld.init", true);
loadScriptFile(out, rawFolder + "onUnload.init", true); namespace DFHack {
break; namespace X {
case SC_MAP_LOADED: typedef state_change_event Key;
loadScriptFile(out, "onLoadMap.init", true); typedef vector<string> Val;
loadScriptFile(out, rawFolder + "onLoadMap.init", true); typedef pair<Key,Val> Entry;
break; typedef vector<Entry> EntryVector;
case SC_MAP_UNLOADED: typedef map<Key,Val> InitVariationTable;
loadScriptFile(out, "onUnloadMap.init", true);
loadScriptFile(out, rawFolder + "onUnloadMap.init", true); EntryVector computeInitVariationTable(void* none, ...) {
va_list list;
va_start(list,none);
EntryVector result;
while(true) {
Key key = (Key)va_arg(list,int);
if ( key == SC_UNKNOWN )
break; break;
default: Val val;
while (true) {
const char *v = va_arg(list, const char *);
if (!v || !v[0])
break; break;
val.push_back(string(v));
}
result.push_back(Entry(key,val));
}
va_end(list);
return result;
}
InitVariationTable getTable(const EntryVector& vec) {
return InitVariationTable(vec.begin(),vec.end());
}
}
}
void Core::handleLoadAndUnloadScripts(color_ostream& out, state_change_event event) {
static const X::InitVariationTable table = X::getTable(X::computeInitVariationTable(0,
(int)SC_WORLD_LOADED, "onLoad", "onLoadWorld", "onWorldLoaded", "",
(int)SC_WORLD_UNLOADED, "onUnload", "onUnloadWorld", "onWorldUnloaded", "",
(int)SC_MAP_LOADED, "onMapLoad", "onLoadMap", "",
(int)SC_MAP_UNLOADED, "onMapUnload", "onUnloadMap", "",
(int)SC_UNKNOWN
));
if (!df::global::world)
return;
std::string rawFolder = "data/save/" + (df::global::world->cur_savegame.save_dir) + "/raw/";
auto i = table.find(event);
if ( i != table.end() ) {
const std::vector<std::string>& set = i->second;
loadScriptFiles(this, out, set, "." );
loadScriptFiles(this, out, set, rawFolder);
loadScriptFiles(this, out, set, rawFolder + "objects/");
} }
for (auto it = state_change_scripts.begin(); it != state_change_scripts.end(); ++it) for (auto it = state_change_scripts.begin(); it != state_change_scripts.end(); ++it)
@ -1914,11 +1975,13 @@ void Core::onStateChange(color_ostream &out, state_change_event event)
case SC_MAP_UNLOADED: case SC_MAP_UNLOADED:
if (world && world->cur_savegame.save_dir.size()) if (world && world->cur_savegame.save_dir.size())
{ {
std::string evtlogpath = "data/save/" + world->cur_savegame.save_dir + "/events-dfhack.log"; std::string save_dir = "data/save/" + world->cur_savegame.save_dir;
std::string evtlogpath = save_dir + "/events-dfhack.log";
std::ofstream evtlog; std::ofstream evtlog;
evtlog.open(evtlogpath, std::ios_base::app); // append evtlog.open(evtlogpath, std::ios_base::app); // append
if (evtlog.fail()) if (evtlog.fail())
{ {
if (DFHack::Filesystem::isdir(save_dir))
out.printerr("Could not append to %s\n", evtlogpath.c_str()); out.printerr("Could not append to %s\n", evtlogpath.c_str());
} }
else else

@ -103,6 +103,12 @@ Process::Process(VersionInfoFactory * factory)
my_descriptor = new VersionInfo(*vinfo); my_descriptor = new VersionInfo(*vinfo);
my_descriptor->rebaseTo(getBase()); my_descriptor->rebaseTo(getBase());
} }
else
{
fprintf(stderr, "Unable to retrieve version information.\nPE timestamp: 0x%x\n",
d->pe_header.FileHeader.TimeDateStamp);
fflush(stderr);
}
} }
Process::~Process() Process::~Process()

@ -149,6 +149,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
else if (type == "md5-hash") else if (type == "md5-hash")
{ {
const char *cstr_value = pMemEntry->Attribute("value"); const char *cstr_value = pMemEntry->Attribute("value");
fprintf(stderr, "%s: MD5: %s\n", cstr_name, cstr_value);
if(!cstr_value) if(!cstr_value)
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name); throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
mem->addMD5(cstr_value); mem->addMD5(cstr_value);
@ -156,6 +157,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
else if (type == "binary-timestamp") else if (type == "binary-timestamp")
{ {
const char *cstr_value = pMemEntry->Attribute("value"); const char *cstr_value = pMemEntry->Attribute("value");
fprintf(stderr, "%s: PE: %s\n", cstr_name, cstr_value);
if(!cstr_value) if(!cstr_value)
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name); throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
mem->addPE(strtol(cstr_value, 0, 16)); mem->addPE(strtol(cstr_value, 0, 16));

@ -1 +1 @@
Subproject commit 32960d38410e7caedf2b38cff7ef3f21c1785bbd Subproject commit 8fcb57a3223eca7826658d0c0c310171b8a3319e

@ -20,18 +20,37 @@ function socket:close( )
_funcs.lua_client_close(self.server_id,self.client_id) _funcs.lua_client_close(self.server_id,self.client_id)
end end
end end
function socket:isBlocking()
return _funcs.lua_socket_is_blocking(self.server_id,self.client_id)
end
function socket:setBlocking()
_funcs.lua_socket_set_blocking(self.server_id,self.client_id,true)
end
function socket:setNonblocking()
_funcs.lua_socket_set_blocking(self.server_id,self.client_id,false)
end
function socket:setTimeout( sec,msec ) function socket:setTimeout( sec,msec )
msec=msec or 0 msec=msec or 0
_funcs.lua_socket_set_timeout(self.server_id,self.client_id,sec,msec) _funcs.lua_socket_set_timeout(self.server_id,self.client_id,sec,msec)
self.timeout={s=sec,ms=msec}
end
function socket:select(sec,msec)
if sec == nil and msec==nil then
local timeout=self.timeout or {s=0,ms=0}
sec=timeout.s
msec=timeout.ms
end
return _funcs.lua_socket_select(self.server_id,self.client_id,sec,msec)
end end
local client=defclass(client,socket) local client=defclass(client,socket)
function client:receive( pattern ) function client:receive( pattern )
local pattern=pattern or "*l" local pattern=pattern or "*l"
local bytes=-1 local bytes=-1
if type(pattern)== number then if type(pattern)== number then
bytes=pattern bytes=pattern
end end
local ret=_funcs.lua_client_receive(self.server_id,self.client_id,bytes,pattern,false) local ret=_funcs.lua_client_receive(self.server_id,self.client_id,bytes,pattern,false)
if ret=="" then if ret=="" then
return return

@ -112,6 +112,8 @@ void handle_error(CSimpleSocket::CSocketError err,bool skip_timeout=true)
return; return;
if (err == CSimpleSocket::SocketTimedout && skip_timeout) if (err == CSimpleSocket::SocketTimedout && skip_timeout)
return; return;
if (err == CSimpleSocket::SocketEwouldblock && skip_timeout)
return;
throw std::runtime_error(translate_socket_error(err)); throw std::runtime_error(translate_socket_error(err));
} }
static int lua_socket_bind(std::string ip,int port) static int lua_socket_bind(std::string ip,int port)
@ -218,6 +220,7 @@ static std::string lua_client_receive(int server_id,int client_id,int bytes,std:
break; break;
} }
ret+=(char)*sock->GetData(); ret+=(char)*sock->GetData();
} }
return ret; return ret;
} }
@ -285,11 +288,12 @@ static int lua_socket_connect(std::string ip,int port)
delete sock; delete sock;
throw std::runtime_error(translate_socket_error(err)); throw std::runtime_error(translate_socket_error(err));
} }
sock->SetNonblocking();
last_client_id++; last_client_id++;
clients[last_client_id]=sock; clients[last_client_id]=sock;
return last_client_id; return last_client_id;
} }
static void lua_socket_set_timeout(int server_id,int client_id,int32_t sec,int32_t msec) CSimpleSocket* get_socket(int server_id, int client_id)
{ {
std::map<int, CActiveSocket*>* target = &clients; std::map<int, CActiveSocket*>* target = &clients;
if (server_id>0) if (server_id>0)
@ -301,10 +305,7 @@ static void lua_socket_set_timeout(int server_id,int client_id,int32_t sec,int32
server &cur_server = servers[server_id]; server &cur_server = servers[server_id];
if (client_id == -1) if (client_id == -1)
{ {
cur_server.socket->SetConnectTimeout(sec,msec); return cur_server.socket;
cur_server.socket->SetReceiveTimeout(sec,msec);
cur_server.socket->SetSendTimeout(sec,msec);
return;
} }
target = &cur_server.clients; target = &cur_server.clients;
} }
@ -314,13 +315,53 @@ static void lua_socket_set_timeout(int server_id,int client_id,int32_t sec,int32
throw std::runtime_error("Client does with this id not exist"); throw std::runtime_error("Client does with this id not exist");
} }
CActiveSocket *sock = (*target)[client_id]; CActiveSocket *sock = (*target)[client_id];
return sock;
}
static void lua_socket_set_timeout(int server_id,int client_id,int32_t sec,int32_t msec)
{
CSimpleSocket *sock = get_socket(server_id, client_id);
sock->SetConnectTimeout(sec,msec); sock->SetConnectTimeout(sec,msec);
sock->SetReceiveTimeout(sec,msec); if (!sock->SetReceiveTimeout(sec, msec) ||
sock->SetSendTimeout(sec,msec); !sock->SetSendTimeout(sec, msec))
{
CSimpleSocket::CSocketError err = sock->GetSocketError();
throw std::runtime_error(translate_socket_error(err));
}
}
static bool lua_socket_select(int server_id, int client_id, int32_t sec, int32_t msec)
{
CSimpleSocket *sock = get_socket(server_id, client_id);
return sock->Select(sec, msec);
}
static void lua_socket_set_blocking(int server_id, int client_id, bool value)
{
CSimpleSocket *sock = get_socket(server_id, client_id);
bool ok;
if (value)
{
ok = sock->SetBlocking();
}
else
{
ok = sock->SetNonblocking();
}
if (!ok)
{
CSimpleSocket::CSocketError err = sock->GetSocketError();
throw std::runtime_error(translate_socket_error(err));
}
}
static bool lua_socket_is_blocking(int server_id, int client_id)
{
CSimpleSocket *sock = get_socket(server_id, client_id);
return !sock->IsNonblocking();
} }
DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(lua_socket_bind), //spawn a server DFHACK_LUA_FUNCTION(lua_socket_bind), //spawn a server
DFHACK_LUA_FUNCTION(lua_socket_connect),//spawn a client (i.e. connection) DFHACK_LUA_FUNCTION(lua_socket_connect),//spawn a client (i.e. connection)
DFHACK_LUA_FUNCTION(lua_socket_select),
DFHACK_LUA_FUNCTION(lua_socket_set_blocking),
DFHACK_LUA_FUNCTION(lua_socket_is_blocking),
DFHACK_LUA_FUNCTION(lua_socket_set_timeout), DFHACK_LUA_FUNCTION(lua_socket_set_timeout),
DFHACK_LUA_FUNCTION(lua_server_accept), DFHACK_LUA_FUNCTION(lua_server_accept),
DFHACK_LUA_FUNCTION(lua_server_close), DFHACK_LUA_FUNCTION(lua_server_close),

@ -1262,7 +1262,17 @@ public:
return &viewscreen->item_status; return &viewscreen->item_status;
} }
bool should_check_input(set<df::interface_key> *input)
{
if (input->count(interface_key::STOCKPILE_SETTINGS_DISABLE) && !in_entry_mode() && !search_string.empty())
{
// Restore original list
clear_search();
reset_all();
}
return true;
}
}; };

@ -1 +1 @@
Subproject commit 600d171bb6eaf44f1a66a379b2f43000d84fab04 Subproject commit 4ba65d9db72fd48f99df23b92e7e356d7313f6c4

@ -0,0 +1 @@
Subproject commit 4353c10401ced7aec89f002947d1252f30237789

@ -0,0 +1 @@
Subproject commit 8cf05cc89782206235f4bef1b5ef98e1bc74e266

@ -1 +1 @@
Subproject commit ceed207e38220e21067a91b8d6f7b9680a476f69 Subproject commit 4fbced45c1ac18dba3a53804ee625cb8a666d460

@ -0,0 +1 @@
Subproject commit ac6dae2ff06d1576873b8e508017e8043e7aa701

@ -0,0 +1 @@
Subproject commit 0c32075d2205fe3aa80794fc45b2c49e3dace8dc

@ -0,0 +1 @@
Subproject commit 4b6e772654df6805b66f77900a4618bbf9b54dab

@ -1,2 +1,14 @@
include(Scripts.cmake) include(Scripts.cmake)
DFHACK_3RDPARTY_SCRIPT_REPO(dscorbett)
DFHACK_3RDPARTY_SCRIPT_REPO(kane-t)
DFHACK_3RDPARTY_SCRIPT_REPO(lethosor) DFHACK_3RDPARTY_SCRIPT_REPO(lethosor)
DFHACK_3RDPARTY_SCRIPT_REPO(maienm)
DFHACK_3RDPARTY_SCRIPT_REPO(maxthyme)
DFHACK_3RDPARTY_SCRIPT_REPO(roses)
install(DIRECTORY ${dfhack_SOURCE_DIR}/scripts
DESTINATION ${DFHACK_DATA_DESTINATION}
FILES_MATCHING PATTERN "*.lua"
PATTERN "*.rb"
PATTERN "3rdparty" EXCLUDE
)

@ -13,7 +13,7 @@ ENDMACRO()
MACRO(DFHACK_3RDPARTY_SCRIPT_REPO repo_path) MACRO(DFHACK_3RDPARTY_SCRIPT_REPO repo_path)
if(NOT EXISTS ${dfhack_SOURCE_DIR}/scripts/3rdparty/${repo_path}/CMakeLists.txt) if(NOT EXISTS ${dfhack_SOURCE_DIR}/scripts/3rdparty/${repo_path}/CMakeLists.txt)
MESSAGE(FATAL_ERROR "Script submodule scripts/3rdparty/${repo_path} does not exist - run `git submodule update`.") MESSAGE(SEND_ERROR "Script submodule scripts/3rdparty/${repo_path} does not exist - run `git submodule update`.")
endif() endif()
add_subdirectory(3rdparty/${repo_path}) add_subdirectory(3rdparty/${repo_path})
ENDMACRO() ENDMACRO()

@ -1,6 +1,19 @@
-- Adds emotions to creatures. -- Adds emotions to creatures.
--@ module = true --@ module = true
--[[
BEGIN_DOCS
.. _scripts/add-thought
add-thought
===========
Adds a thought or emotion to the selected unit. Can be used by other scripts,
or the gui invoked by running ``add-thought gui`` with a unit selected.
END_DOCS
]]
local utils=require('utils') local utils=require('utils')
function addEmotionToUnit(unit,thought,emotion,severity,strength,subthought) function addEmotionToUnit(unit,thought,emotion,severity,strength,subthought)

@ -0,0 +1,193 @@
-- Adjust all attributes, personality, age and skills of all dwarves in play
-- without arguments, all attributes, age & personalities are adjusted
-- arguments allow for skills to be adjusted as well
-- WARNING: USING THIS SCRIPT WILL ADJUST ALL DWARVES IN PLAY!
-- by vjek
function rejuvenate(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
local current_year=df.global.cur_year
local newbirthyear=current_year - 20
if unit.relations.birth_year < newbirthyear then
unit.relations.birth_year=newbirthyear
end
if unit.relations.old_year < current_year+100 then
unit.relations.old_year=current_year+100
end
end
-- ---------------------------------------------------------------------------
function brainwash_unit(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
local profile ={75,25,25,75,25,25,25,99,25,25,25,50,75,50,25,75,75,50,75,75,25,75,75,50,75,25,50,25,75,75,75,25,75,75,25,75,25,25,75,75,25,75,75,75,25,75,75,25,25,50}
local i
for i=1, #profile do
unit.status.current_soul.personality.traits[i-1]=profile[i]
end
end
-- ---------------------------------------------------------------------------
function elevate_attributes(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
local ok,f,t,k = pcall(pairs,unit.status.current_soul.mental_attrs)
if ok then
for k,v in f,t,k do
v.value=v.max_value
end
end
local ok,f,t,k = pcall(pairs,unit.body.physical_attrs)
if ok then
for k,v in f,t,k do
v.value=v.max_value
end
end
end
-- ---------------------------------------------------------------------------
-- this function will return the number of elements, starting at zero.
-- useful for counting things where #foo doesn't work
function count_this(to_be_counted)
local count = -1
local var1 = ""
while var1 ~= nil do
count = count + 1
var1 = (to_be_counted[count])
end
count=count-1
return count
end
-- ---------------------------------------------------------------------------
function make_legendary(skillname,unit)
local skillnamenoun,skillnum
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
if (df.job_skill[skillname]) then
skillnamenoun = df.job_skill.attrs[df.job_skill[skillname]].caption_noun
else
print ("The skill name provided is not in the list.")
return
end
if skillnamenoun ~= nil then
utils = require 'utils'
skillnum = df.job_skill[skillname]
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = skillnum, rating = 20 }, 'id')
print (unit.name.first_name.." is now a Legendary "..skillnamenoun)
else
print ("Empty skill name noun, bailing out!")
return
end
end
-- ---------------------------------------------------------------------------
function BreathOfArmok(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
local i
local count_max = count_this(df.job_skill)
utils = require 'utils'
for i=0, count_max do
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = i, rating = 20 }, 'id')
end
print ("The breath of Armok has engulfed "..unit.name.first_name)
end
-- ---------------------------------------------------------------------------
function LegendaryByClass(skilltype,v)
unit=v
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
utils = require 'utils'
local i
local skillclass
local count_max = count_this(df.job_skill)
for i=0, count_max do
skillclass = df.job_skill_class[df.job_skill.attrs[i].type]
if skilltype == skillclass then
print ("Skill "..df.job_skill.attrs[i].caption.." is type: "..skillclass.." and is now Legendary for "..unit.name.first_name)
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = i, rating = 20 }, 'id')
end
end
end
-- ---------------------------------------------------------------------------
function PrintSkillList()
local count_max = count_this(df.job_skill)
local i
for i=0, count_max do
print("'"..df.job_skill.attrs[i].caption.."' "..df.job_skill[i].." Type: "..df.job_skill_class[df.job_skill.attrs[i].type])
end
print ("Provide the UPPER CASE argument, for example: PROCESSPLANTS rather than Threshing")
end
-- ---------------------------------------------------------------------------
function PrintSkillClassList()
local i
local count_max = count_this(df.job_skill_class)
for i=0, count_max do
print(df.job_skill_class[i])
end
print ("Provide one of these arguments, and all skills of that type will be made Legendary")
print ("For example: Medical will make all medical skills legendary")
end
-- ---------------------------------------------------------------------------
function adjust_all_dwarves(skillname)
for _,v in ipairs(df.global.world.units.all) do
if v.race == df.global.ui.race_id then
print("Adjusting "..dfhack.TranslateName(dfhack.units.getVisibleName(v)))
brainwash_unit(v)
elevate_attributes(v)
rejuvenate(v)
if skillname then
if skillname=="Normal" or skillname=="Medical" or skillname=="Personal" or skillname=="Social" or skillname=="Cultural" or skillname=="MilitaryWeapon" or skillname=="MilitaryAttack" or skillname=="MilitaryDefense" or skillname=="MilitaryMisc" then
LegendaryByClass(skillname,v)
elseif skillname=="all" then
BreathOfArmok(v)
else
make_legendary(skillname,v)
end
end
end
end
end
-- ---------------------------------------------------------------------------
-- main script operation starts here
-- ---------------------------------------------------------------------------
local opt = ...
local skillname
if opt then
if opt=="list" then
PrintSkillList()
return
end
if opt=="classes" then
PrintSkillClassList()
return
end
skillname = opt
else
print ("No skillname supplied, no skills will be adjusted. Pass argument 'list' to see a skill list, 'classes' to show skill classes, or use 'all' if you want all skills legendary.")
end
adjust_all_dwarves(skillname)

@ -0,0 +1,61 @@
-- This script will brainwash a dwarf, modifying their personality
-- usage is: target a unit in DF, and execute this script in dfhack
-- by vjek
function brainwash_unit(profile)
local i,unit_name
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
unit_name=dfhack.TranslateName(dfhack.units.getVisibleName(unit))
print("Previous personality values for "..unit_name)
printall(unit.status.current_soul.personality.traits)
--now set new personality
for i=1, #profile do
unit.status.current_soul.personality.traits[i-1]=profile[i]
end
print("New personality values for "..unit_name)
printall(unit.status.current_soul.personality.traits)
print(unit_name.." has been brainwashed, praise Armok!")
end
-- main script starts here
-- profiles are listed here and passed to the brainwash function
--
local baseline={50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}
local ideal={75,25,25,75,25,25,25,99,25,25,25,50,75,50,25,75,75,50,75,75,25,75,75,50,75,25,50,25,75,75,75,25,75,75,25,75,25,25,75,75,25,75,75,75,25,75,75,25,25,50}
local stepford={99,1,1,99,1,1,1,99,1,1,1,1,50,50,1,99,99,50,50,50,1,1,99,50,50,50,50,50,50,99,50,1,1,99,1,99,1,1,99,99,1,99,99,99,1,50,50,1,1,1}
local wrecked={1,99,99,1,99,99,99,1,99,99,99,1,1,99,99,1,1,1,1,1,99,1,1,99,1,99,99,99,1,1,1,99,1,1,99,1,99,99,1,1,99,1,1,1,99,1,1,99,99,99}
local opt = ...
if opt then
if opt=="ideal" then
brainwash_unit(ideal)
return
end
if opt=="baseline" then
brainwash_unit(baseline)
return
end
if opt=="stepford" then
brainwash_unit(stepford)
return
end
if opt=="wrecked" then
brainwash_unit(wrecked)
return
end
else
print ("Invalid or missing personality argument.\nValid choices are ideal , baseline , stepford, and wrecked.")
print ("ideal will create a reliable dwarf with generally positive personality traits.")
print ("baseline will reset all personality traits to a default / the average.")
print ("stepford amplifies all good qualities to an excessive degree.")
print ("wrecked amplifies all bad qualities to an excessive degree.")
end

@ -0,0 +1,45 @@
-- This script will elevate all the mental attributes of a unit
-- usage is: target a unit in DF, and execute this script in dfhack
-- all physical attributes will be set to whatever the max value is
-- by vjek
function ElevateMentalAttributes(value)
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
--print name of dwarf
print("Adjusting "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)))
--walk through available attributes, adjust current to max
local ok,f,t,k = pcall(pairs,unit.status.current_soul.mental_attrs)
if ok then
for k,v in f,t,k do
if value ~= nil then
print("Adjusting current value for "..tostring(k).." of "..v.value.." to the value of "..value)
v.value=value
else
print("Adjusting current value for "..tostring(k).." of "..v.value.." to max value of "..v.max_value)
v.value=v.max_value
--below will reset values back to "normal"
--v.value=v.max_value/2
end
end
end
end
--script execution starts here
local opt = ...
opt = tonumber(opt)
if opt ~= nil then
if opt >=0 and opt <=5000 then
ElevateMentalAttributes(opt)
end
if opt <0 or opt >5000 then
print("Invalid Range or argument. This script accepts either no argument, in which case it will increase the attribute to the max_value for the unit, or an argument between 0 and 5000, which will set all attributes to that value.")
end
end
if opt == nil then
ElevateMentalAttributes()
end

@ -0,0 +1,45 @@
-- This script will elevate all the physical attributes of a unit
-- usage is: target a unit in DF, and execute this script in dfhack
-- all physical attributes will be set to whatever the max value is
-- by vjek
function ElevatePhysicalAttributes(value)
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
--print name of dwarf
print("Adjusting "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)))
--walk through available attributes, adjust current to max
local ok,f,t,k = pcall(pairs,unit.body.physical_attrs)
if ok then
for k,v in f,t,k do
if value ~= nil then
print("Adjusting current value for "..tostring(k).." of "..v.value.." to the value of "..value)
v.value=value
else
print("Adjusting current value for "..tostring(k).." of "..v.value.." to max value of "..v.max_value)
v.value=v.max_value
--below will reset values back to "normal"
--v.value=v.max_value/2
end
end
end
end
--script execution starts here
local opt = ...
opt = tonumber(opt)
if opt ~= nil then
if opt >=0 and opt <=5000 then
ElevatePhysicalAttributes(opt)
end
if opt <0 or opt >5000 then
print("Invalid Range or argument. This script accepts either no argument, in which case it will increase the attribute to the max_value for the unit, or an argument between 0 and 5000, which will set all attributes to that value.")
end
end
if opt == nil then
ElevatePhysicalAttributes()
end

@ -1,8 +1,25 @@
-- allows to do jobs in adv. mode. -- allows to do jobs in adv. mode.
--[==[ --[==[
version: 0.03 version: 0.044
changelog: changelog:
*0.044
- added output to clear_jobs of number of cleared jobs
- another failed attempt at gather plants fix
- added track stop configuration window
*0.043
- fixed track carving: up/down was reversed and removed (temp) requirements because they were not working correctly
- added checks for unsafe conditions (currently quite stupid). Should save few adventurers that are trying to work in dangerous conditions (e.g. fishing)
- unsafe checks disabled by "-u" ir "--unsafe"
*0.042
- fixed (probably for sure now) the crash bug.
- added --clear_jobs debug option. Will delete ALL JOBS!
*0.041
- fixed cooking allowing already cooked meals
*0.04
- add (-q)uick mode. Autoselects materials.
- fixed few(?) crash bugs
- fixed job errors not being shown in df
*0.031 *0.031
- make forbiding optional (-s)afe mode - make forbiding optional (-s)afe mode
*0.03 *0.03
@ -60,6 +77,7 @@ up_alt1={key="CUSTOM_CTRL_E",desc="Use job up"},
up_alt2={key="CURSOR_UP_Z_AUX",desc="Use job up"}, up_alt2={key="CURSOR_UP_Z_AUX",desc="Use job up"},
use_same={key="A_MOVE_SAME_SQUARE",desc="Use job at the tile you are standing"}, use_same={key="A_MOVE_SAME_SQUARE",desc="Use job at the tile you are standing"},
workshop={key="CHANGETAB",desc="Show building menu"}, workshop={key="CHANGETAB",desc="Show building menu"},
quick={key="CUSTOM_Q",desc="Toggle quick item select"},
} }
-- building filters -- building filters
build_filter={ build_filter={
@ -124,6 +142,10 @@ for k,v in ipairs({...}) do --setting parsing
if v=="-c" or v=="--cheat" then if v=="-c" or v=="--cheat" then
settings.build_by_items=true settings.build_by_items=true
settings.df_assign=false settings.df_assign=false
elseif v=="-q" or v=="--quick" then
settings.quick=true
elseif v=="-u" or v=="--unsafe" then --ignore pain and etc
settings.unsafe=true
elseif v=="-s" or v=="--safe" then elseif v=="-s" or v=="--safe" then
settings.safe=true settings.safe=true
elseif v=="-i" or v=="--inventory" then elseif v=="-i" or v=="--inventory" then
@ -133,6 +155,8 @@ for k,v in ipairs({...}) do --setting parsing
settings.df_assign=false settings.df_assign=false
elseif v=="-h" or v=="--help" then elseif v=="-h" or v=="--help" then
settings.help=true settings.help=true
elseif v=="--clear_jobs" then
settings.clear_jobs=true
else else
mode_name=v mode_name=v
end end
@ -257,6 +281,60 @@ function make_native_job(args)
args.unlinked=true args.unlinked=true
end end
end end
function smart_job_delete( job )
local gref_types=df.general_ref_type
--TODO: unmark items as in job
for i,v in ipairs(job.general_refs) do
if v:getType()==gref_types.BUILDING_HOLDER then
local b=v:getBuilding()
if b then
--remove from building
for i,v in ipairs(b.jobs) do
if v==job then
b.jobs:erase(i)
break
end
end
else
print("Warning: building holder ref was invalid while deleting job")
end
elseif v:getType()==gref_types.UNIT_WORKER then
local u=v:getUnit()
if u then
u.job.current_job =nil
else
print("Warning: unit worker ref was invalid while deleting job")
end
else
print("Warning: failed to remove link from job with type:",gref_types[v:getType()])
end
end
--unlink job
local link=job.list_link
if link.prev then
link.prev.next=link.next
end
if link.next then
link.next.prev=link.prev
end
link:delete()
--finally delete the job
job:delete()
end
--TODO: this logic might be better with other --starting logic--
if settings.clear_jobs then
print("Clearing job list!")
local counter=0
local job_link=df.global.world.job_list.next
while job_link and job_link.item do
local job=job_link.item
job_link=job_link.next
smart_job_delete(job)
counter=counter+1
end
print("Deleted: "..counter.." jobs")
return
end
function makeJob(args) function makeJob(args)
gscript.start(function () gscript.start(function ()
make_native_job(args) make_native_job(args)
@ -289,8 +367,10 @@ function makeJob(args)
addJobAction(args.job,args.unit) addJobAction(args.job,args.unit)
args.screen:wait_tick() args.screen:wait_tick()
else else
args.job:delete() if not args.no_job_delete then
dfhack.gui.showAnnouncement(msg,5,1) smart_job_delete(args.job)
end
dfhack.gui.showAnnouncement("Job failed:"..failed,5,1)
end end
end) end)
end end
@ -345,9 +425,9 @@ function SetCarveDir(args)
elseif pos.x<from_pos.x then elseif pos.x<from_pos.x then
job.item_category[dirs.left]=true job.item_category[dirs.left]=true
elseif pos.y>from_pos.y then elseif pos.y>from_pos.y then
job.item_category[dirs.up]=true
elseif pos.y<from_pos.y then
job.item_category[dirs.down]=true job.item_category[dirs.down]=true
elseif pos.y<from_pos.y then
job.item_category[dirs.up]=true
end end
end end
function MakePredicateWieldsItem(item_skill) function MakePredicateWieldsItem(item_skill)
@ -591,6 +671,9 @@ function isSuitableItem(job_item,item)
local matinfo=dfhack.matinfo.decode(item) local matinfo=dfhack.matinfo.decode(item)
--print(matinfo:getCraftClass()) --print(matinfo:getCraftClass())
--print("Matching ",item," vs ",job_item) --print("Matching ",item," vs ",job_item)
if job_item.flags1.cookable and item:getType()==df.item_type.FOOD then
return false,"already cooked"
end
if type(job_item) ~= "table" and not matinfo:matches(job_item) then if type(job_item) ~= "table" and not matinfo:matches(job_item) then
--[[ --[[
@ -784,6 +867,8 @@ function find_suitable_items(job,items,job_items)
--[[ --[[
if msg then if msg then
print(cur_item,msg) print(cur_item,msg)
else
print(cur_item,"ok")
end end
--]] --]]
if not settings.gui_item_select then if not settings.gui_item_select then
@ -817,6 +902,20 @@ function AssignJobItems(args)
if settings.gui_item_select and #job.job_items>0 then if settings.gui_item_select and #job.job_items>0 then
local item_dialog=require('hack.scripts.gui.advfort_items') local item_dialog=require('hack.scripts.gui.advfort_items')
if settings.quick then --TODO not so nice hack. instead of rewriting logic for job item filling i'm using one in gui dialog...
local item_editor=item_dialog.jobitemEditor{
job = job,
items = item_suitability,
}
if item_editor:jobValid() then
item_editor:commit()
finish_item_assign(args)
return true
else
return false, "Quick select items"
end
else
local ret=item_dialog.showItemEditor(job,item_suitability) local ret=item_dialog.showItemEditor(job,item_suitability)
if ret then if ret then
finish_item_assign(args) finish_item_assign(args)
@ -826,6 +925,7 @@ function AssignJobItems(args)
end end
--end) --end)
return false,"Selecting items" return false,"Selecting items"
end
else else
if not settings.build_by_items then if not settings.build_by_items then
for job_id, trg_job_item in ipairs(job.job_items) do for job_id, trg_job_item in ipairs(job.job_items) do
@ -846,6 +946,7 @@ CheckAndFinishBuilding=function (args,bld)
for idx,job in pairs(bld.jobs) do for idx,job in pairs(bld.jobs) do
if job.job_type==df.job_type.ConstructBuilding then if job.job_type==df.job_type.ConstructBuilding then
args.job=job args.job=job
args.no_job_delete=true
break break
end end
end end
@ -856,6 +957,7 @@ CheckAndFinishBuilding=function (args,bld)
local t={items=buildings.getFiltersByType({},bld:getType(),bld:getSubtype(),bld:getCustomType())} local t={items=buildings.getFiltersByType({},bld:getType(),bld:getSubtype(),bld:getCustomType())}
args.pre_actions={dfhack.curry(setFiltersUp,t),AssignBuildingRef}--,AssignJobItems args.pre_actions={dfhack.curry(setFiltersUp,t),AssignBuildingRef}--,AssignJobItems
end end
args.no_job_delete=true
makeJob(args) makeJob(args)
end end
function AssignJobToBuild(args) function AssignJobToBuild(args)
@ -1017,9 +1119,10 @@ function get_design_block_ev(blk)
end end
end end
function PlantGatherFix(args) function PlantGatherFix(args)
args.job.flags[17]=true --??
local pos=args.pos local pos=args.pos
--[[args.job.flags[17]=false --??
local block=dfhack.maps.getTileBlock(pos) local block=dfhack.maps.getTileBlock(pos)
local ev=get_design_block_ev(block) local ev=get_design_block_ev(block)
if ev==nil then if ev==nil then
@ -1029,12 +1132,20 @@ function PlantGatherFix(args)
ev.priority[pos.x % 16][pos.y % 16]=bit32.bor(ev.priority[pos.x % 16][pos.y % 16],4000) ev.priority[pos.x % 16][pos.y % 16]=bit32.bor(ev.priority[pos.x % 16][pos.y % 16],4000)
args.job.item_category:assign{furniture=true,corpses=true,ammo=true} --this is actually required in fort mode args.job.item_category:assign{furniture=true,corpses=true,ammo=true} --this is actually required in fort mode
]]
local path=args.unit.path
path.dest=pos
path.goal=df.unit_path_goal.GatherPlant
path.path.x:insert("#",pos.x)
path.path.y:insert("#",pos.y)
path.path.z:insert("#",pos.z)
printall(path)
end end
actions={ actions={
{"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMaterial}}, {"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMaterial}},
{"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMaterial}}, {"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMaterial}},
{"DetailFloor" ,df.job_type.DetailFloor,{IsFloor,IsHardMaterial,SameSquare}}, {"DetailFloor" ,df.job_type.DetailFloor,{IsFloor,IsHardMaterial,SameSquare}},
{"CarveTrack" ,df.job_type.CarveTrack,{IsFloor,IsHardMaterial} {"CarveTrack" ,df.job_type.CarveTrack,{} --TODO: check this- carving modifies standing tile but depends on direction!
,{SetCarveDir}}, ,{SetCarveDir}},
{"Dig" ,df.job_type.Dig,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}}, {"Dig" ,df.job_type.Dig,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}},
{"CarveUpwardStaircase" ,df.job_type.CarveUpwardStaircase,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}}, {"CarveUpwardStaircase" ,df.job_type.CarveUpwardStaircase,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}},
@ -1069,12 +1180,16 @@ usetool=defclass(usetool,gui.Screen)
usetool.focus_path = 'advfort' usetool.focus_path = 'advfort'
function usetool:getModeName() function usetool:getModeName()
local adv=df.global.world.units.active[0] local adv=df.global.world.units.active[0]
local ret
if adv.job.current_job then if adv.job.current_job then
return string.format("%s working(%d) ",(actions[(mode or 0)+1][1] or ""),adv.job.current_job.completion_timer) ret= string.format("%s working(%d) ",(actions[(mode or 0)+1][1] or ""),adv.job.current_job.completion_timer)
else else
return actions[(mode or 0)+1][1] or " " ret= actions[(mode or 0)+1][1] or " "
end end
if settings.quick then
ret=ret.."*"
end
return ret
end end
function usetool:update_site() function usetool:update_site()
@ -1299,6 +1414,37 @@ function usetool:openShopWindow(building)
qerror("No jobs for this workshop") qerror("No jobs for this workshop")
end end
end end
function track_stop_configure(bld) --TODO: dedicated widget with nice interface and current setting display
local dump_choices={
{text="no dumping"},
{text="N",x=0,y=-1},--{t="NE",x=1,y=-1},
{text="E",x=1,y=0},--{t="SE",x=1,y=1},
{text="S",x=0,y=1},--{t="SW",x=-1,y=1},
{text="W",x=-1,y=0},--{t="NW",x=-1,y=-1}
}
local choices={"Friction","Dumping"}
local function chosen(index,choice)
if choice.text=="Friction" then
dialog.showInputPrompt("Choose friction","Friction",nil,tostring(bld.friction),function ( txt )
local num=tonumber(txt) --TODO allow only vanilla friction settings
if num then
bld.friction=num
end
end)
else
dialog.showListPrompt("Dumping direction", "Choose dumping:",COLOR_WHITE,dump_choices,function ( index,choice)
if choice.x then
bld.use_dump=1 --??
bld.dump_x_shift=choice.x
bld.dump_y_shift=choice.y
else
bld.use_dump=0
end
end)
end
end
dialog.showListPrompt("Track stop configure", "Choose what to change:",COLOR_WHITE,choices,chosen)
end
function usetool:armCleanTrap(building) function usetool:armCleanTrap(building)
local adv=df.global.world.units.active[0] local adv=df.global.world.units.active[0]
--[[ --[[
@ -1332,9 +1478,12 @@ function usetool:armCleanTrap(building)
args.job_type=df.job_type.LoadStoneTrap args.job_type=df.job_type.LoadStoneTrap
local job_filter={items={{quantity=1,item_type=df.item_type.BOULDER}} } local job_filter={items={{quantity=1,item_type=df.item_type.BOULDER}} }
args.pre_actions={dfhack.curry(setFiltersUp,job_filter),AssignJobItems} args.pre_actions={dfhack.curry(setFiltersUp,job_filter),AssignJobItems}
elseif building.trap_type==df.trap_type.WeaponTrap then elseif building.trap_type==df.trap_type.TrackStop then
qerror("TODO") --set dump and friction
track_stop_configure(building)
return
else else
print("TODO: trap type:"..df.trap_type[building.trap_type])
return return
end end
args.screen=self args.screen=self
@ -1595,10 +1744,13 @@ function usetool:onInput(keys)
elseif keys["A_SHORT_WAIT"] then elseif keys["A_SHORT_WAIT"] then
--ContinueJob(adv) --ContinueJob(adv)
self:sendInputToParent("A_SHORT_WAIT") self:sendInputToParent("A_SHORT_WAIT")
elseif keys[keybinds.quick.key] then
settings.quick=not settings.quick
elseif keys[keybinds.continue.key] then elseif keys[keybinds.continue.key] then
--ContinueJob(adv) --ContinueJob(adv)
--self:sendInputToParent("A_SHORT_WAIT") --self:sendInputToParent("A_SHORT_WAIT")
self.long_wait=true self.long_wait=true
self.long_wait_timer=nil
else else
if self.mode~=nil then if self.mode~=nil then
if keys[keybinds.workshop.key] then if keys[keybinds.workshop.key] then
@ -1611,12 +1763,28 @@ function usetool:onInput(keys)
end end
end end
function usetool:cancel_wait()
self.long_wait_timer=nil
self.long_wait=false
end
function usetool:onIdle() function usetool:onIdle()
local adv=df.global.world.units.active[0] local adv=df.global.world.units.active[0]
local job_ptr=adv.job.current_job local job_ptr=adv.job.current_job
local job_action=findAction(adv,df.unit_action_type.Job) local job_action=findAction(adv,df.unit_action_type.Job)
--some heuristics for unsafe conditions
if self.long_wait and not settings.unsafe then --check if player wants for canceling to happen
local counters=adv.counters
local checked_counters={pain=true,winded=true,stunned=true,unconscious=true,suffocation=true,webbed=true,nausea=true,dizziness=true}
for k,v in pairs(checked_counters) do
if counters[k]>0 then
dfhack.gui.showAnnouncement("Job: canceled waiting because unsafe -"..k,5,1)
self:cancel_wait()
return
end
end
end
if self.long_wait and self.long_wait_timer==nil then if self.long_wait and self.long_wait_timer==nil then
self.long_wait_timer=1000 --TODO tweak this self.long_wait_timer=1000 --TODO tweak this
end end
@ -1624,8 +1792,8 @@ function usetool:onIdle()
if job_ptr and self.long_wait and not job_action then if job_ptr and self.long_wait and not job_action then
if self.long_wait_timer<=0 then --fix deadlocks with force-canceling of waiting if self.long_wait_timer<=0 then --fix deadlocks with force-canceling of waiting
self.long_wait_timer=nil self:cancel_wait()
self.long_wait=false return
else else
self.long_wait_timer=self.long_wait_timer-1 self.long_wait_timer=self.long_wait_timer-1
end end

@ -179,7 +179,11 @@ function jobitemEditor:commit()
self:dismiss() self:dismiss()
if self.on_okay then self.on_okay(self.slots) end if self.on_okay then self.on_okay(self.slots) end
end end
function jobitemEditor:onDestroy()
if self.on_close then
self.on_close()
end
end
function showItemEditor(job,item_selections) function showItemEditor(job,item_selections)
jobitemEditor{ jobitemEditor{
job = job, job = job,

@ -174,6 +174,7 @@ function GmEditorUi:getSelectedEnumType()
local trg=self:currentTarget() local trg=self:currentTarget()
local trg_key=trg.keys[self.subviews.list_main:getSelected()] local trg_key=trg.keys[self.subviews.list_main:getSelected()]
if trg.target._field==nil then return nil end if trg.target._field==nil then return nil end
if trg.target:_field(trg_key)==nil then return nil end
local enum=trg.target:_field(trg_key)._type local enum=trg.target:_field(trg_key)._type
if enum._kind=="enum-type" then if enum._kind=="enum-type" then
return enum return enum

@ -0,0 +1,130 @@
-- This script will modify a skill or the skills of a single unit
-- usage is: target a unit in DF, and execute this script in dfhack
-- the skill will be increased to 20 (Legendary +5)
-- arguments 'list', 'classes' and 'all' added
-- by vjek
-- this function will return the number of elements, starting at zero.
-- useful for counting things where #foo doesn't work
function count_this(to_be_counted)
local count = -1
local var1 = ""
while var1 ~= nil do
count = count + 1
var1 = (to_be_counted[count])
end
count=count-1
return count
end
function make_legendary(skillname)
local skillnamenoun,skillnum
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
if (df.job_skill[skillname]) then
skillnamenoun = df.job_skill.attrs[df.job_skill[skillname]].caption_noun
else
print ("The skill name provided is not in the list.")
return
end
if skillnamenoun ~= nil then
utils = require 'utils'
skillnum = df.job_skill[skillname]
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = skillnum, rating = 20 }, 'id')
print (dfhack.TranslateName(dfhack.units.getVisibleName(unit)).." is now a Legendary "..skillnamenoun)
else
print ("Empty skill name noun, bailing out!")
return
end
end
function PrintSkillList()
local count_max = count_this(df.job_skill)
local i
for i=0, count_max do
print("'"..df.job_skill.attrs[i].caption.."' "..df.job_skill[i].." Type: "..df.job_skill_class[df.job_skill.attrs[i].type])
end
print ("Provide the UPPER CASE argument, for example: PROCESSPLANTS rather than Threshing")
end
function BreathOfArmok()
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
local i
local count_max = count_this(df.job_skill)
utils = require 'utils'
for i=0, count_max do
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = i, rating = 20 }, 'id')
end
print ("The breath of Armok has engulfed "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)))
end
function LegendaryByClass(skilltype)
unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor! Aborting with extreme prejudice.")
return
end
utils = require 'utils'
local i
local skillclass
local count_max = count_this(df.job_skill)
for i=0, count_max do
skillclass = df.job_skill_class[df.job_skill.attrs[i].type]
if skilltype == skillclass then
print ("Skill "..df.job_skill.attrs[i].caption.." is type: "..skillclass.." and is now Legendary for "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)))
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = i, rating = 20 }, 'id')
end
end
end
function PrintSkillClassList()
local i
local count_max = count_this(df.job_skill_class)
for i=0, count_max do
print(df.job_skill_class[i])
end
print ("Provide one of these arguments, and all skills of that type will be made Legendary")
print ("For example: Medical will make all medical skills legendary")
end
--main script operation starts here
----
local opt = ...
local skillname
if opt then
if opt=="list" then
PrintSkillList()
return
end
if opt=="classes" then
PrintSkillClassList()
return
end
if opt=="all" then
BreathOfArmok()
return
end
if opt=="Normal" or opt=="Medical" or opt=="Personal" or opt=="Social" or opt=="Cultural" or opt=="MilitaryWeapon" or opt=="MilitaryAttack" or opt=="MilitaryDefense" or opt=="MilitaryMisc" then
LegendaryByClass(opt)
return
end
skillname = opt
else
print ("No skillname supplied.\nUse argument 'list' to see a list, 'classes' to show skill classes, or use 'all' if you want it all!")
print ("Example: To make a legendary miner, use make_legendary MINING")
return
end
make_legendary(skillname)

@ -0,0 +1,92 @@
-- Adjust all preferences of all dwarves in play
-- all preferences are cleared, then set
-- WARNING: USING THIS SCRIPT WILL ADJUST ALL DWARVES IN PLAY!
-- by vjek
-- ---------------------------------------------------------------------------
function brainwash_unit(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end
local pss_counter=31415926
local prefcount = #(unit.status.current_soul.preferences)
print ("Before, unit "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)).." has "..prefcount.." preferences")
utils = require 'utils'
-- below populates an array with all creature names and id's, used for 'detests...'
rtbl={}
vec=df.global.world.raws.creatures.all
for k=0,#vec-1 do
local name=vec[k].creature_id
rtbl[name]=k
end
-- Now iterate through for the type 3 detests...
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 3 , item_type = rtbl.TROLL , creature_id = rtbl.TROLL , color_id = rtbl.TROLL , shape_id = rtbl.TROLL , plant_id = rtbl.TROLL , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 3 , item_type = rtbl.BIRD_BUZZARD , creature_id = rtbl.BIRD_BUZZARD , color_id = rtbl.BIRD_BUZZARD , shape_id = rtbl.BIRD_BUZZARD , plant_id = rtbl.BIRD_BUZZARD , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 3 , item_type = rtbl.BIRD_VULTURE , creature_id = rtbl.BIRD_VULTURE , color_id = rtbl.BIRD_VULTURE , shape_id = rtbl.BIRD_VULTURE , plant_id = rtbl.BIRD_VULTURE , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 3 , item_type = rtbl.CRUNDLE , creature_id = rtbl.CRUNDLE , color_id = rtbl.CRUNDLE , shape_id = rtbl.CRUNDLE , plant_id = rtbl.CRUNDLE , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
-- and the type 4 likes
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 4 , item_type = df.item_type.WEAPON , creature_id = df.item_type.WEAPON , color_id = df.item_type.WEAPON , shape_id = df.item_type.WEAPON , plant_id = df.item_type.WEAPON , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 4 , item_type = df.item_type.ARMOR , creature_id = df.item_type.ARMOR , color_id = df.item_type.ARMOR , shape_id = df.item_type.ARMOR , plant_id = df.item_type.ARMOR , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 4 , item_type = df.item_type.SHIELD , creature_id = df.item_type.SHIELD , color_id = df.item_type.SHIELD , shape_id = df.item_type.SHIELD , plant_id = df.item_type.SHIELD , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
-- prefers plump helmets for their ...
local ph_mat_type=dfhack.matinfo.find("MUSHROOM_HELMET_PLUMP:STRUCTURAL").index
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 5 , item_type = ph_mat_type , creature_id = ph_mat_type , color_id = ph_mat_type , shape_id = ph_mat_type , plant_id = ph_mat_type , item_subtype = -1 , mattype = -1 , matindex = -1 , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
-- prefers to consume dwarven wine:
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 2 , item_type = 68 , creature_id = 68 , color_id = 68 , shape_id = 68 , plant_id = 68 , item_subtype = -1 , mattype = dfhack.matinfo.find("MUSHROOM_HELMET_PLUMP:DRINK").type , matindex = dfhack.matinfo.find("MUSHROOM_HELMET_PLUMP:DRINK").index , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
-- likes iron, steel (0,8) adam is 25
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 0 , item_type = -1 , creature_id = -1 , color_id = -1 , shape_id = -1 , plant_id = -1 , item_subtype = -1 , mattype = 0 , matindex = dfhack.matinfo.find("IRON").index , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 0 , item_type = -1 , creature_id = -1 , color_id = -1 , shape_id = -1 , plant_id = -1 , item_subtype = -1 , mattype = 0 , matindex = dfhack.matinfo.find("STEEL").index , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
prefcount = #(unit.status.current_soul.preferences)
print ("After, unit "..dfhack.TranslateName(dfhack.units.getVisibleName(unit)).." has "..prefcount.." preferences")
end
-- ---------------------------------------------------------------------------
function clear_preferences(v)
unit=v
local prefs=unit.status.current_soul.preferences
for index,pref in ipairs(prefs) do
pref:delete()
end
prefs:resize(0)
end
-- ---------------------------------------------------------------------------
function clearpref_all_dwarves()
for _,v in ipairs(df.global.world.units.active) do
if v.race == df.global.ui.race_id then
print("Clearing Preferences for "..dfhack.TranslateName(dfhack.units.getVisibleName(v)))
clear_preferences(v)
end
end
end
-- ---------------------------------------------------------------------------
function adjust_all_dwarves()
for _,v in ipairs(df.global.world.units.active) do
if v.race == df.global.ui.race_id then
print("Adjusting "..dfhack.TranslateName(dfhack.units.getVisibleName(v)))
brainwash_unit(v)
end
end
end
-- ---------------------------------------------------------------------------
-- main script operation starts here
-- ---------------------------------------------------------------------------
clearpref_all_dwarves()
adjust_all_dwarves()

@ -0,0 +1,24 @@
-- This script will make any "old" dwarf 20 years old
-- usage is: target a unit in DF, and execute this script in dfhack
-- the target will be changed to 20 years old
-- by vjek
function rejuvenate()
local current_year,newbirthyear
unit=dfhack.gui.getSelectedUnit()
if unit==nil then print ("No unit under cursor! Aborting.") return end
current_year=df.global.cur_year
newbirthyear=current_year - 20
if unit.relations.birth_year < newbirthyear then
unit.relations.birth_year=newbirthyear
end
if unit.relations.old_year < current_year+100 then
unit.relations.old_year=current_year+100
end
print (dfhack.TranslateName(dfhack.units.getVisibleName(unit)).." is now 20 years old and will live at least 100 years")
end
rejuvenate()

@ -19,8 +19,8 @@ try:
res = json.loads(urlopen('https://api.github.com/repos/%s/pulls/%i' % (repo, pr_id)).read().decode('utf-8')) res = json.loads(urlopen('https://api.github.com/repos/%s/pulls/%i' % (repo, pr_id)).read().decode('utf-8'))
except ValueError: except ValueError:
pass pass
except HTTPError: except HTTPError as e:
print('Failed to retrieve PR information from API') print('Failed to retrieve PR information from API: %s' % e)
sys.exit(2) sys.exit(2)
if 'base' not in res or 'ref' not in res['base']: if 'base' not in res or 'ref' not in res['base']:
print('Invalid JSON returned from API') print('Invalid JSON returned from API')

@ -0,0 +1,30 @@
import os, sys
scriptdir = 'scripts'
def is_script(fname):
if not os.path.isfile(fname):
return False
return fname.endswith('.lua') or fname.endswith('.rb')
def main():
files = []
for item in os.listdir(scriptdir):
path = os.path.join(scriptdir, item)
if is_script(path):
files.append(item)
elif os.path.isdir(path) and item not in ('devel', '3rdparty'):
files.extend([item + '/' + f for f in os.listdir(path)
if is_script(os.path.join(path, f))])
with open('docs/Scripts.rst') as f:
text = f.read()
error = 0
for f, _ in [os.path.splitext(p) for p in files]:
heading = '\n' + f + '\n' + '=' * len(f) + '\n'
if heading not in text:
print('WARNING: {:28} not documented in docs/Scripts'.format(f))
error = 1
sys.exit(error)
if __name__ == '__main__':
main()