Merge branch 'master' of git://github.com/peterix/dfhack

Conflicts:
	plugins/Dfusion/luafiles/xml_struct.lua
	plugins/Dfusion/luafiles/xml_types.lua
develop
Warmist 2012-03-11 13:50:14 +02:00
commit 792e48fb76
91 changed files with 2828 additions and 1752 deletions

@ -27,10 +27,10 @@ endif()
# set up versioning. # set up versioning.
set(DF_VERSION_MAJOR "0") set(DF_VERSION_MAJOR "0")
set(DF_VERSION_MINOR "34") set(DF_VERSION_MINOR "34")
set(DF_VERSION_PATCH "04") set(DF_VERSION_PATCH "05")
set(DF_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}") set(DF_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}")
set(DFHACK_RELEASE "1") set(DFHACK_RELEASE "1d")
set(DFHACK_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}-r${DFHACK_RELEASE}") set(DFHACK_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}-r${DFHACK_RELEASE}")
add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}") add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}")
@ -78,8 +78,21 @@ IF(UNIX)
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -march=i686 -mtune=generic") SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -march=i686 -mtune=generic")
ENDIF() ENDIF()
# find and make available libz
if(NOT UNIX)
SET(ZLIB_INCLUDE_DIRS ${dfhack_SOURCE_DIR}/library/depends/zlib/include/)
SET(ZLIB_LIBRARIES ${dfhack_SOURCE_DIR}/library/depends/zlib/lib/zlib.lib)
else()
find_package(ZLIB REQUIRED)
endif()
include_directories(${ZLIB_INCLUDE_DIRS})
#add depends to include path #add depends to include path
INCLUDE_DIRECTORIES ( library/depends ) INCLUDE_DIRECTORIES ( library/depends )
INCLUDE_DIRECTORIES ( library/depends/protobuf/ )
# use shared libraries for protobuf
ADD_DEFINITIONS(-DPROTOBUF_USE_DLLS)
# build the static lua for dfusion # build the static lua for dfusion
INCLUDE_DIRECTORIES ( lua/include ) INCLUDE_DIRECTORIES ( lua/include )

@ -27,7 +27,7 @@ Compatibility
DFHack works on Windows XP, Vista, 7 or any modern Linux distribution. DFHack works on Windows XP, Vista, 7 or any modern Linux distribution.
OSX is not supported due to lack of developers with a Mac. OSX is not supported due to lack of developers with a Mac.
Currently, only version 0.31.25 is supported. If you need DFHack Currently, only version 0.34.05 is supported. If you need DFHack
for older versions, look for older releases. for older versions, look for older releases.
On Windows, you have to use the SDL version of DF. On Windows, you have to use the SDL version of DF.
@ -441,6 +441,8 @@ reveal
====== ======
This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'. This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'.
Reveal also works in adventure mode, but any of its effects are negated once you move. When you use it this way, you don't need to run 'unreveal'.
unreveal unreveal
======== ========
Reverts the effects of 'reveal'. Reverts the effects of 'reveal'.
@ -489,6 +491,14 @@ You can also paint only over tiles that match a set of properties (filter)
For more details, see the 'help' command while using this. For more details, see the 'help' command while using this.
tweak
=====
Contains various tweaks for minor bugs (currently just one).
Options
-------
:tweak clear-missing: Remove the missing status from the selected unit. This allows engraving slabs for ghostly, but not yet found, creatures.
tubefill tubefill
======== ========
Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug). Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug).

@ -318,7 +318,7 @@ ul.auto-toc {
<div class="section" id="introduction"> <div class="section" id="introduction">
<h1><a class="toc-backref" href="#id17">Introduction</a></h1> <h1><a class="toc-backref" href="#id18">Introduction</a></h1>
<p>DFHack is a Dwarf Fortress memory access library and a set of basic <p>DFHack is a Dwarf Fortress memory access library and a set of basic
tools that use it. Tools come in the form of plugins or (not yet) tools that use it. Tools come in the form of plugins or (not yet)
external tools. It is an attempt to unite the various ways tools external tools. It is an attempt to unite the various ways tools
@ -326,165 +326,169 @@ access DF memory and allow for easier development of new tools.</p>
<div class="contents topic" id="contents"> <div class="contents topic" id="contents">
<p class="topic-title first">Contents</p> <p class="topic-title first">Contents</p>
<ul class="simple"> <ul class="simple">
<li><a class="reference internal" href="#introduction" id="id17">Introduction</a></li> <li><a class="reference internal" href="#introduction" id="id18">Introduction</a></li>
<li><a class="reference internal" href="#getting-dfhack" id="id18">Getting DFHack</a></li> <li><a class="reference internal" href="#getting-dfhack" id="id19">Getting DFHack</a></li>
<li><a class="reference internal" href="#compatibility" id="id19">Compatibility</a></li> <li><a class="reference internal" href="#compatibility" id="id20">Compatibility</a></li>
<li><a class="reference internal" href="#installation-removal" id="id20">Installation/Removal</a></li> <li><a class="reference internal" href="#installation-removal" id="id21">Installation/Removal</a></li>
<li><a class="reference internal" href="#using-dfhack" id="id21">Using DFHack</a></li> <li><a class="reference internal" href="#using-dfhack" id="id22">Using DFHack</a></li>
<li><a class="reference internal" href="#something-doesn-t-work-help" id="id22">Something doesn't work, help!</a></li> <li><a class="reference internal" href="#something-doesn-t-work-help" id="id23">Something doesn't work, help!</a></li>
<li><a class="reference internal" href="#the-init-file" id="id23">The init file</a></li> <li><a class="reference internal" href="#the-init-file" id="id24">The init file</a></li>
<li><a class="reference internal" href="#commands" id="id24">Commands</a><ul> <li><a class="reference internal" href="#commands" id="id25">Commands</a><ul>
<li><a class="reference internal" href="#adv-bodyswap" id="id25">adv-bodyswap</a><ul> <li><a class="reference internal" href="#adv-bodyswap" id="id26">adv-bodyswap</a><ul>
<li><a class="reference internal" href="#usage" id="id26">Usage</a></li> <li><a class="reference internal" href="#usage" id="id27">Usage</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#advtools" id="id27">advtools</a><ul> <li><a class="reference internal" href="#advtools" id="id28">advtools</a><ul>
<li><a class="reference internal" href="#id1" id="id28">Usage</a></li> <li><a class="reference internal" href="#id1" id="id29">Usage</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#changevein" id="id29">changevein</a></li> <li><a class="reference internal" href="#changevein" id="id30">changevein</a></li>
<li><a class="reference internal" href="#follow" id="id30">follow</a></li> <li><a class="reference internal" href="#follow" id="id31">follow</a></li>
<li><a class="reference internal" href="#forcepause" id="id31">forcepause</a></li> <li><a class="reference internal" href="#forcepause" id="id32">forcepause</a></li>
<li><a class="reference internal" href="#nopause" id="id32">nopause</a></li> <li><a class="reference internal" href="#nopause" id="id33">nopause</a></li>
<li><a class="reference internal" href="#die" id="id33">die</a></li> <li><a class="reference internal" href="#die" id="id34">die</a></li>
<li><a class="reference internal" href="#autodump" id="id34">autodump</a><ul> <li><a class="reference internal" href="#autodump" id="id35">autodump</a><ul>
<li><a class="reference internal" href="#options" id="id35">Options</a></li> <li><a class="reference internal" href="#options" id="id36">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#autodump-destroy-here" id="id36">autodump-destroy-here</a></li> <li><a class="reference internal" href="#autodump-destroy-here" id="id37">autodump-destroy-here</a></li>
<li><a class="reference internal" href="#autodump-destroy-item" id="id37">autodump-destroy-item</a></li> <li><a class="reference internal" href="#autodump-destroy-item" id="id38">autodump-destroy-item</a></li>
<li><a class="reference internal" href="#clean" id="id38">clean</a><ul> <li><a class="reference internal" href="#clean" id="id39">clean</a><ul>
<li><a class="reference internal" href="#id2" id="id39">Options</a></li> <li><a class="reference internal" href="#id2" id="id40">Options</a></li>
<li><a class="reference internal" href="#extra-options-for-map" id="id40">Extra options for 'map'</a></li> <li><a class="reference internal" href="#extra-options-for-map" id="id41">Extra options for 'map'</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#spotclean" id="id41">spotclean</a></li> <li><a class="reference internal" href="#spotclean" id="id42">spotclean</a></li>
<li><a class="reference internal" href="#cleanowned" id="id42">cleanowned</a><ul> <li><a class="reference internal" href="#cleanowned" id="id43">cleanowned</a><ul>
<li><a class="reference internal" href="#id3" id="id43">Options</a></li> <li><a class="reference internal" href="#id3" id="id44">Options</a></li>
<li><a class="reference internal" href="#example" id="id44">Example:</a></li> <li><a class="reference internal" href="#example" id="id45">Example:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#colonies" id="id45">colonies</a><ul> <li><a class="reference internal" href="#colonies" id="id46">colonies</a><ul>
<li><a class="reference internal" href="#id4" id="id46">Options</a></li> <li><a class="reference internal" href="#id4" id="id47">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#deramp-by-zilpin" id="id47">deramp (by zilpin)</a></li> <li><a class="reference internal" href="#deramp-by-zilpin" id="id48">deramp (by zilpin)</a></li>
<li><a class="reference internal" href="#df2minecraft" id="id48">df2minecraft</a></li> <li><a class="reference internal" href="#df2minecraft" id="id49">df2minecraft</a></li>
<li><a class="reference internal" href="#dfusion" id="id49">dfusion</a><ul> <li><a class="reference internal" href="#dfusion" id="id50">dfusion</a><ul>
<li><a class="reference internal" href="#confirmed-working-dfusion-plugins" id="id50">Confirmed working DFusion plugins:</a></li> <li><a class="reference internal" href="#confirmed-working-dfusion-plugins" id="id51">Confirmed working DFusion plugins:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#drybuckets" id="id51">drybuckets</a></li> <li><a class="reference internal" href="#drybuckets" id="id52">drybuckets</a></li>
<li><a class="reference internal" href="#fastdwarf" id="id52">fastdwarf</a></li> <li><a class="reference internal" href="#fastdwarf" id="id53">fastdwarf</a></li>
<li><a class="reference internal" href="#filltraffic" id="id53">filltraffic</a><ul> <li><a class="reference internal" href="#filltraffic" id="id54">filltraffic</a><ul>
<li><a class="reference internal" href="#traffic-type-codes" id="id54">Traffic Type Codes:</a></li> <li><a class="reference internal" href="#traffic-type-codes" id="id55">Traffic Type Codes:</a></li>
<li><a class="reference internal" href="#other-options" id="id55">Other Options:</a></li> <li><a class="reference internal" href="#other-options" id="id56">Other Options:</a></li>
<li><a class="reference internal" href="#id5" id="id56">Example:</a></li> <li><a class="reference internal" href="#id5" id="id57">Example:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#alltraffic" id="id57">alltraffic</a><ul> <li><a class="reference internal" href="#alltraffic" id="id58">alltraffic</a><ul>
<li><a class="reference internal" href="#id6" id="id58">Traffic Type Codes:</a></li> <li><a class="reference internal" href="#id6" id="id59">Traffic Type Codes:</a></li>
<li><a class="reference internal" href="#id7" id="id59">Example:</a></li> <li><a class="reference internal" href="#id7" id="id60">Example:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#fixdiplomats" id="id60">fixdiplomats</a></li> <li><a class="reference internal" href="#fixdiplomats" id="id61">fixdiplomats</a></li>
<li><a class="reference internal" href="#fixmerchants" id="id61">fixmerchants</a></li> <li><a class="reference internal" href="#fixmerchants" id="id62">fixmerchants</a></li>
<li><a class="reference internal" href="#fixveins" id="id62">fixveins</a></li> <li><a class="reference internal" href="#fixveins" id="id63">fixveins</a></li>
<li><a class="reference internal" href="#fixwagons" id="id63">fixwagons</a></li> <li><a class="reference internal" href="#fixwagons" id="id64">fixwagons</a></li>
<li><a class="reference internal" href="#flows" id="id64">flows</a></li> <li><a class="reference internal" href="#flows" id="id65">flows</a></li>
<li><a class="reference internal" href="#getplants" id="id65">getplants</a><ul> <li><a class="reference internal" href="#getplants" id="id66">getplants</a><ul>
<li><a class="reference internal" href="#id8" id="id66">Options</a></li> <li><a class="reference internal" href="#id8" id="id67">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#tidlers" id="id67">tidlers</a></li> <li><a class="reference internal" href="#tidlers" id="id68">tidlers</a></li>
<li><a class="reference internal" href="#twaterlvl" id="id68">twaterlvl</a></li> <li><a class="reference internal" href="#twaterlvl" id="id69">twaterlvl</a></li>
<li><a class="reference internal" href="#job" id="id69">job</a></li> <li><a class="reference internal" href="#job" id="id70">job</a></li>
<li><a class="reference internal" href="#job-material" id="id70">job-material</a></li> <li><a class="reference internal" href="#job-material" id="id71">job-material</a></li>
<li><a class="reference internal" href="#job-duplicate" id="id71">job-duplicate</a></li> <li><a class="reference internal" href="#job-duplicate" id="id72">job-duplicate</a></li>
<li><a class="reference internal" href="#keybinding" id="id72">keybinding</a><ul> <li><a class="reference internal" href="#keybinding" id="id73">keybinding</a><ul>
<li><a class="reference internal" href="#id9" id="id73">Options</a></li> <li><a class="reference internal" href="#id9" id="id74">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#liquids" id="id74">liquids</a></li> <li><a class="reference internal" href="#liquids" id="id75">liquids</a></li>
<li><a class="reference internal" href="#mode" id="id75">mode</a></li> <li><a class="reference internal" href="#mode" id="id76">mode</a></li>
<li><a class="reference internal" href="#extirpate" id="id76">extirpate</a><ul> <li><a class="reference internal" href="#extirpate" id="id77">extirpate</a><ul>
<li><a class="reference internal" href="#id10" id="id77">Options</a></li> <li><a class="reference internal" href="#id10" id="id78">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#grow" id="id78">grow</a></li> <li><a class="reference internal" href="#grow" id="id79">grow</a></li>
<li><a class="reference internal" href="#immolate" id="id79">immolate</a></li> <li><a class="reference internal" href="#immolate" id="id80">immolate</a></li>
<li><a class="reference internal" href="#probe" id="id80">probe</a></li> <li><a class="reference internal" href="#probe" id="id81">probe</a></li>
<li><a class="reference internal" href="#prospect" id="id81">prospect</a><ul> <li><a class="reference internal" href="#prospect" id="id82">prospect</a><ul>
<li><a class="reference internal" href="#id11" id="id82">Options</a></li> <li><a class="reference internal" href="#id11" id="id83">Options</a></li>
<li><a class="reference internal" href="#pre-embark-estimate" id="id83">Pre-embark estimate</a></li> <li><a class="reference internal" href="#pre-embark-estimate" id="id84">Pre-embark estimate</a></li>
<li><a class="reference internal" href="#id12" id="id84">Options</a></li> <li><a class="reference internal" href="#id12" id="id85">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#regrass" id="id85">regrass</a></li> <li><a class="reference internal" href="#regrass" id="id86">regrass</a></li>
<li><a class="reference internal" href="#rename" id="id86">rename</a><ul> <li><a class="reference internal" href="#rename" id="id87">rename</a><ul>
<li><a class="reference internal" href="#id13" id="id87">Options</a></li> <li><a class="reference internal" href="#id13" id="id88">Options</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#reveal" id="id88">reveal</a></li> <li><a class="reference internal" href="#reveal" id="id89">reveal</a></li>
<li><a class="reference internal" href="#unreveal" id="id89">unreveal</a></li> <li><a class="reference internal" href="#unreveal" id="id90">unreveal</a></li>
<li><a class="reference internal" href="#revtoggle" id="id90">revtoggle</a></li> <li><a class="reference internal" href="#revtoggle" id="id91">revtoggle</a></li>
<li><a class="reference internal" href="#revflood" id="id91">revflood</a></li> <li><a class="reference internal" href="#revflood" id="id92">revflood</a></li>
<li><a class="reference internal" href="#seedwatch" id="id92">seedwatch</a></li> <li><a class="reference internal" href="#seedwatch" id="id93">seedwatch</a></li>
<li><a class="reference internal" href="#showmood" id="id93">showmood</a></li> <li><a class="reference internal" href="#showmood" id="id94">showmood</a></li>
<li><a class="reference internal" href="#copystock" id="id94">copystock</a></li> <li><a class="reference internal" href="#copystock" id="id95">copystock</a></li>
<li><a class="reference internal" href="#ssense-stonesense" id="id95">ssense / stonesense</a></li> <li><a class="reference internal" href="#ssense-stonesense" id="id96">ssense / stonesense</a></li>
<li><a class="reference internal" href="#tiletypes" id="id96">tiletypes</a></li> <li><a class="reference internal" href="#tiletypes" id="id97">tiletypes</a></li>
<li><a class="reference internal" href="#tubefill" id="id97">tubefill</a></li> <li><a class="reference internal" href="#tweak" id="id98">tweak</a><ul>
<li><a class="reference internal" href="#vdig" id="id98">vdig</a></li> <li><a class="reference internal" href="#id14" id="id99">Options</a></li>
<li><a class="reference internal" href="#vdigx" id="id99">vdigx</a></li>
<li><a class="reference internal" href="#expdig" id="id100">expdig</a><ul>
<li><a class="reference internal" href="#patterns" id="id101">Patterns:</a></li>
<li><a class="reference internal" href="#filters" id="id102">Filters:</a></li>
<li><a class="reference internal" href="#examples" id="id103">Examples:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#digcircle" id="id104">digcircle</a><ul> <li><a class="reference internal" href="#tubefill" id="id100">tubefill</a></li>
<li><a class="reference internal" href="#shape" id="id105">Shape:</a></li> <li><a class="reference internal" href="#vdig" id="id101">vdig</a></li>
<li><a class="reference internal" href="#action" id="id106">Action:</a></li> <li><a class="reference internal" href="#vdigx" id="id102">vdigx</a></li>
<li><a class="reference internal" href="#designation-types" id="id107">Designation types:</a></li> <li><a class="reference internal" href="#expdig" id="id103">expdig</a><ul>
<li><a class="reference internal" href="#id14" id="id108">Examples:</a></li> <li><a class="reference internal" href="#patterns" id="id104">Patterns:</a></li>
<li><a class="reference internal" href="#filters" id="id105">Filters:</a></li>
<li><a class="reference internal" href="#examples" id="id106">Examples:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#weather" id="id109">weather</a><ul> <li><a class="reference internal" href="#digcircle" id="id107">digcircle</a><ul>
<li><a class="reference internal" href="#id15" id="id110">Options:</a></li> <li><a class="reference internal" href="#shape" id="id108">Shape:</a></li>
<li><a class="reference internal" href="#action" id="id109">Action:</a></li>
<li><a class="reference internal" href="#designation-types" id="id110">Designation types:</a></li>
<li><a class="reference internal" href="#id15" id="id111">Examples:</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#workflow" id="id111">workflow</a><ul> <li><a class="reference internal" href="#weather" id="id112">weather</a><ul>
<li><a class="reference internal" href="#id16" id="id112">Usage</a></li> <li><a class="reference internal" href="#id16" id="id113">Options:</a></li>
<li><a class="reference internal" href="#function" id="id113">Function</a></li>
<li><a class="reference internal" href="#constraint-examples" id="id114">Constraint examples</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#mapexport" id="id115">mapexport</a></li> <li><a class="reference internal" href="#workflow" id="id114">workflow</a><ul>
<li><a class="reference internal" href="#dwarfexport" id="id116">dwarfexport</a></li> <li><a class="reference internal" href="#id17" id="id115">Usage</a></li>
<li><a class="reference internal" href="#function" id="id116">Function</a></li>
<li><a class="reference internal" href="#constraint-examples" id="id117">Constraint examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#mapexport" id="id118">mapexport</a></li>
<li><a class="reference internal" href="#dwarfexport" id="id119">dwarfexport</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="section" id="getting-dfhack"> <div class="section" id="getting-dfhack">
<h1><a class="toc-backref" href="#id18">Getting DFHack</a></h1> <h1><a class="toc-backref" href="#id19">Getting DFHack</a></h1>
<p>The project is currently hosted on <a class="reference external" href="http://www.github.com/">github</a>, for both source and <p>The project is currently hosted on <a class="reference external" href="http://www.github.com/">github</a>, for both source and
binaries at <a class="reference external" href="http://github.com/peterix/dfhack">http://github.com/peterix/dfhack</a></p> binaries at <a class="reference external" href="http://github.com/peterix/dfhack">http://github.com/peterix/dfhack</a></p>
<p>Releases can be downloaded from here: <a class="reference external" href="https://github.com/peterix/dfhack/downloads">https://github.com/peterix/dfhack/downloads</a></p> <p>Releases can be downloaded from here: <a class="reference external" href="https://github.com/peterix/dfhack/downloads">https://github.com/peterix/dfhack/downloads</a></p>
<p>All new releases are announced in the bay12 thread: <a class="reference external" href="http://tinyurl.com/dfhack-ng">http://tinyurl.com/dfhack-ng</a></p> <p>All new releases are announced in the bay12 thread: <a class="reference external" href="http://tinyurl.com/dfhack-ng">http://tinyurl.com/dfhack-ng</a></p>
</div> </div>
<div class="section" id="compatibility"> <div class="section" id="compatibility">
<h1><a class="toc-backref" href="#id19">Compatibility</a></h1> <h1><a class="toc-backref" href="#id20">Compatibility</a></h1>
<p>DFHack works on Windows XP, Vista, 7 or any modern Linux distribution. <p>DFHack works on Windows XP, Vista, 7 or any modern Linux distribution.
OSX is not supported due to lack of developers with a Mac.</p> OSX is not supported due to lack of developers with a Mac.</p>
<p>Currently, only version 0.31.25 is supported. If you need DFHack <p>Currently, only version 0.34.05 is supported. If you need DFHack
for older versions, look for older releases.</p> for older versions, look for older releases.</p>
<p>On Windows, you have to use the SDL version of DF.</p> <p>On Windows, you have to use the SDL version of DF.</p>
<p>It is possible to use the Windows DFHack under wine/OSX.</p> <p>It is possible to use the Windows DFHack under wine/OSX.</p>
</div> </div>
<div class="section" id="installation-removal"> <div class="section" id="installation-removal">
<h1><a class="toc-backref" href="#id20">Installation/Removal</a></h1> <h1><a class="toc-backref" href="#id21">Installation/Removal</a></h1>
<p>Installing DFhack involves copying files into your DF folder. <p>Installing DFhack involves copying files into your DF folder.
Copy the files from a release archive so that:</p> Copy the files from a release archive so that:</p>
<blockquote> <blockquote>
@ -504,7 +508,7 @@ Copy the files from a release archive so that:</p>
<p>If any of the plugins or dfhack itself refuses to load, check the stderr.log file created in your DF folder.</p> <p>If any of the plugins or dfhack itself refuses to load, check the stderr.log file created in your DF folder.</p>
</div> </div>
<div class="section" id="using-dfhack"> <div class="section" id="using-dfhack">
<h1><a class="toc-backref" href="#id21">Using DFHack</a></h1> <h1><a class="toc-backref" href="#id22">Using DFHack</a></h1>
<p>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). <p>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 instroduction, use the 'help' command. To list all possible commands, use the 'ls' command. Basic interaction with dfhack involves entering commands into the console. For some basic instroduction, 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.</p> Many commands have their own help or detailed description. You can use 'command help' or 'command ?' to show that.</p>
@ -515,22 +519,22 @@ Many commands have their own help or detailed description. You can use 'command
<p>Most of the commands come from plugins. Those reside in 'hack/plugins/'.</p> <p>Most of the commands come from plugins. Those reside in 'hack/plugins/'.</p>
</div> </div>
<div class="section" id="something-doesn-t-work-help"> <div class="section" id="something-doesn-t-work-help">
<h1><a class="toc-backref" href="#id22">Something doesn't work, help!</a></h1> <h1><a class="toc-backref" href="#id23">Something doesn't work, help!</a></h1>
<p>First, don't panic :) Second, dfhack keeps a few log files in DF's folder - stderr.log and stdout.log. You can look at those and possibly find out what's happening. <p>First, don't panic :) Second, dfhack keeps a few log files in DF's folder - stderr.log and stdout.log. You can look at those and possibly find out what's happening.
If you found a bug, you can either report it in the bay12 DFHack thread, the issues tracker on github, contact me (<a class="reference external" href="mailto:peterix&#64;gmail.com">peterix&#64;gmail.com</a>) or visit the #dfhack IRC channel on freenode.</p> If you found a bug, you can either report it in the bay12 DFHack thread, the issues tracker on github, contact me (<a class="reference external" href="mailto:peterix&#64;gmail.com">peterix&#64;gmail.com</a>) or visit the #dfhack IRC channel on freenode.</p>
</div> </div>
<div class="section" id="the-init-file"> <div class="section" id="the-init-file">
<h1><a class="toc-backref" href="#id23">The init file</a></h1> <h1><a class="toc-backref" href="#id24">The init file</a></h1>
<p>If your DF folder contains a file named dfhack.init, its contents will be run every time you start DF. This allows setting up keybindings. An example file is provided as dfhack.init-example - you can tweak it and rename to dfhack.init if you want to use this functionality.</p> <p>If your DF folder contains a file named dfhack.init, its contents will be run every time you start DF. This allows setting up keybindings. An example file is provided as dfhack.init-example - you can tweak it and rename to dfhack.init if you want to use this functionality.</p>
</div> </div>
<div class="section" id="commands"> <div class="section" id="commands">
<h1><a class="toc-backref" href="#id24">Commands</a></h1> <h1><a class="toc-backref" href="#id25">Commands</a></h1>
<p>Almost all the commands support using the 'help &lt;command-name&gt;' built-in command to retrieve further help without having to look at this document. Alternatively, some accept a 'help'/'?' option on their command line.</p> <p>Almost all the commands support using the 'help &lt;command-name&gt;' built-in command to retrieve further help without having to look at this document. Alternatively, some accept a 'help'/'?' option on their command line.</p>
<div class="section" id="adv-bodyswap"> <div class="section" id="adv-bodyswap">
<h2><a class="toc-backref" href="#id25">adv-bodyswap</a></h2> <h2><a class="toc-backref" href="#id26">adv-bodyswap</a></h2>
<p>This allows taking control over your followers and other creatures in adventure mode. For example, you can make them pick up new arms and armor and equip them properly.</p> <p>This allows taking control over your followers and other creatures in adventure mode. For example, you can make them pick up new arms and armor and equip them properly.</p>
<div class="section" id="usage"> <div class="section" id="usage">
<h3><a class="toc-backref" href="#id26">Usage</a></h3> <h3><a class="toc-backref" href="#id27">Usage</a></h3>
<blockquote> <blockquote>
<ul class="simple"> <ul class="simple">
<li>When viewing unit details, body-swaps into that unit.</li> <li>When viewing unit details, body-swaps into that unit.</li>
@ -540,10 +544,10 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
</div> </div>
</div> </div>
<div class="section" id="advtools"> <div class="section" id="advtools">
<h2><a class="toc-backref" href="#id27">advtools</a></h2> <h2><a class="toc-backref" href="#id28">advtools</a></h2>
<p>A package of different adventure mode tools (currently just one)</p> <p>A package of different adventure mode tools (currently just one)</p>
<div class="section" id="id1"> <div class="section" id="id1">
<h3><a class="toc-backref" href="#id28">Usage</a></h3> <h3><a class="toc-backref" href="#id29">Usage</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -556,15 +560,15 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
</div> </div>
</div> </div>
<div class="section" id="changevein"> <div class="section" id="changevein">
<h2><a class="toc-backref" href="#id29">changevein</a></h2> <h2><a class="toc-backref" href="#id30">changevein</a></h2>
<p>Changes material of the vein under cursor to the specified inorganic RAW material.</p> <p>Changes material of the vein under cursor to the specified inorganic RAW material.</p>
</div> </div>
<div class="section" id="follow"> <div class="section" id="follow">
<h2><a class="toc-backref" href="#id30">follow</a></h2> <h2><a class="toc-backref" href="#id31">follow</a></h2>
<p>Makes the game view follow the currently highlighted unit after you exit from current menu/cursor mode. Handy for watching dwarves running around. Deactivated by moving the view manually.</p> <p>Makes the game view follow the currently highlighted unit after you exit from current menu/cursor mode. Handy for watching dwarves running around. Deactivated by moving the view manually.</p>
</div> </div>
<div class="section" id="forcepause"> <div class="section" id="forcepause">
<h2><a class="toc-backref" href="#id31">forcepause</a></h2> <h2><a class="toc-backref" href="#id32">forcepause</a></h2>
<p>Forces DF to pause. This is useful when your FPS drops below 1 and you lose control of the game.</p> <p>Forces DF to pause. This is useful when your FPS drops below 1 and you lose control of the game.</p>
<blockquote> <blockquote>
<ul class="simple"> <ul class="simple">
@ -574,23 +578,23 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
</blockquote> </blockquote>
</div> </div>
<div class="section" id="nopause"> <div class="section" id="nopause">
<h2><a class="toc-backref" href="#id32">nopause</a></h2> <h2><a class="toc-backref" href="#id33">nopause</a></h2>
<p>Disables pausing (both manual and automatic) with the exception of pause forced by 'reveal hell'. <p>Disables pausing (both manual and automatic) with the exception of pause forced by 'reveal hell'.
This is nice for digging under rivers.</p> This is nice for digging under rivers.</p>
</div> </div>
<div class="section" id="die"> <div class="section" id="die">
<h2><a class="toc-backref" href="#id33">die</a></h2> <h2><a class="toc-backref" href="#id34">die</a></h2>
<p>Instantly kills DF without saving.</p> <p>Instantly kills DF without saving.</p>
</div> </div>
<div class="section" id="autodump"> <div class="section" id="autodump">
<h2><a class="toc-backref" href="#id34">autodump</a></h2> <h2><a class="toc-backref" href="#id35">autodump</a></h2>
<p>This utility lets you quickly move all items designated to be dumped. <p>This utility lets you quickly move all items designated to be dumped.
Items are instantly moved to the cursor position, the dump flag is unset, Items are instantly moved to the cursor position, the dump flag is unset,
and the forbid flag is set, as if it had been dumped normally. and the forbid flag is set, as if it had been dumped normally.
Be aware that any active dump item tasks still point at the item.</p> Be aware that any active dump item tasks still point at the item.</p>
<p>Cursor must be placed on a floor tile so the items can be dumped there.</p> <p>Cursor must be placed on a floor tile so the items can be dumped there.</p>
<div class="section" id="options"> <div class="section" id="options">
<h3><a class="toc-backref" href="#id35">Options</a></h3> <h3><a class="toc-backref" href="#id36">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -610,20 +614,20 @@ Be aware that any active dump item tasks still point at the item.</p>
</div> </div>
</div> </div>
<div class="section" id="autodump-destroy-here"> <div class="section" id="autodump-destroy-here">
<h2><a class="toc-backref" href="#id36">autodump-destroy-here</a></h2> <h2><a class="toc-backref" href="#id37">autodump-destroy-here</a></h2>
<p>Destroy items marked for dumping under cursor. Identical to autodump destroy-here, but intended for use as keybinding.</p> <p>Destroy items marked for dumping under cursor. Identical to autodump destroy-here, but intended for use as keybinding.</p>
</div> </div>
<div class="section" id="autodump-destroy-item"> <div class="section" id="autodump-destroy-item">
<h2><a class="toc-backref" href="#id37">autodump-destroy-item</a></h2> <h2><a class="toc-backref" href="#id38">autodump-destroy-item</a></h2>
<p>Destroy the selected item. The item may be selected in the 'k' list, or inside a container. If called again before the game is resumed, cancels destroy.</p> <p>Destroy the selected item. The item may be selected in the 'k' list, or inside a container. If called again before the game is resumed, cancels destroy.</p>
</div> </div>
<div class="section" id="clean"> <div class="section" id="clean">
<h2><a class="toc-backref" href="#id38">clean</a></h2> <h2><a class="toc-backref" href="#id39">clean</a></h2>
<p>Cleans all the splatter that get scattered all over the map, items and creatures. <p>Cleans all the splatter that get scattered all over the map, items and creatures.
In an old fortress, this can significantly reduce FPS lag. It can also spoil your In an old fortress, this can significantly reduce FPS lag. It can also spoil your
!!FUN!!, so think before you use it.</p> !!FUN!!, so think before you use it.</p>
<div class="section" id="id2"> <div class="section" id="id2">
<h3><a class="toc-backref" href="#id39">Options</a></h3> <h3><a class="toc-backref" href="#id40">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -638,7 +642,7 @@ In an old fortress, this can significantly reduce FPS lag. It can also spoil you
</table> </table>
</div> </div>
<div class="section" id="extra-options-for-map"> <div class="section" id="extra-options-for-map">
<h3><a class="toc-backref" href="#id40">Extra options for 'map'</a></h3> <h3><a class="toc-backref" href="#id41">Extra options for 'map'</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -652,15 +656,15 @@ In an old fortress, this can significantly reduce FPS lag. It can also spoil you
</div> </div>
</div> </div>
<div class="section" id="spotclean"> <div class="section" id="spotclean">
<h2><a class="toc-backref" href="#id41">spotclean</a></h2> <h2><a class="toc-backref" href="#id42">spotclean</a></h2>
<p>Works like 'clean map snow mud', but only for the tile under the cursor. Ideal if you want to keep that bloody entrance 'clean map' would clean up.</p> <p>Works like 'clean map snow mud', but only for the tile under the cursor. Ideal if you want to keep that bloody entrance 'clean map' would clean up.</p>
</div> </div>
<div class="section" id="cleanowned"> <div class="section" id="cleanowned">
<h2><a class="toc-backref" href="#id42">cleanowned</a></h2> <h2><a class="toc-backref" href="#id43">cleanowned</a></h2>
<p>Confiscates items owned by dwarfs. <p>Confiscates items owned by dwarfs.
By default, owned food on the floor and rotten items are confistacted and dumped.</p> By default, owned food on the floor and rotten items are confistacted and dumped.</p>
<div class="section" id="id3"> <div class="section" id="id3">
<h3><a class="toc-backref" href="#id43">Options</a></h3> <h3><a class="toc-backref" href="#id44">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -679,15 +683,15 @@ By default, owned food on the floor and rotten items are confistacted and dumped
</table> </table>
</div> </div>
<div class="section" id="example"> <div class="section" id="example">
<h3><a class="toc-backref" href="#id44">Example:</a></h3> <h3><a class="toc-backref" href="#id45">Example:</a></h3>
<p><tt class="docutils literal">cleanowned scattered X</tt> : This will confiscate rotten and dropped food, garbage on the floors and any worn items with 'X' damage and above.</p> <p><tt class="docutils literal">cleanowned scattered X</tt> : This will confiscate rotten and dropped food, garbage on the floors and any worn items with 'X' damage and above.</p>
</div> </div>
</div> </div>
<div class="section" id="colonies"> <div class="section" id="colonies">
<h2><a class="toc-backref" href="#id45">colonies</a></h2> <h2><a class="toc-backref" href="#id46">colonies</a></h2>
<p>Allows listing all the vermin colonies on the map and optionally turning them into honey bee colonies.</p> <p>Allows listing all the vermin colonies on the map and optionally turning them into honey bee colonies.</p>
<div class="section" id="id4"> <div class="section" id="id4">
<h3><a class="toc-backref" href="#id46">Options</a></h3> <h3><a class="toc-backref" href="#id47">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -699,12 +703,12 @@ By default, owned food on the floor and rotten items are confistacted and dumped
</div> </div>
</div> </div>
<div class="section" id="deramp-by-zilpin"> <div class="section" id="deramp-by-zilpin">
<h2><a class="toc-backref" href="#id47">deramp (by zilpin)</a></h2> <h2><a class="toc-backref" href="#id48">deramp (by zilpin)</a></h2>
<p>Removes all ramps designated for removal from the map. This is useful for replicating the old channel digging designation. <p>Removes all ramps designated for removal from the map. This is useful for replicating the old channel digging designation.
It also removes any and all 'down ramps' that can remain after a cave-in (you don't have to designate anything for that to happen).</p> It also removes any and all 'down ramps' that can remain after a cave-in (you don't have to designate anything for that to happen).</p>
</div> </div>
<div class="section" id="df2minecraft"> <div class="section" id="df2minecraft">
<h2><a class="toc-backref" href="#id48">df2minecraft</a></h2> <h2><a class="toc-backref" href="#id49">df2minecraft</a></h2>
<p>This generates a minecraft world out of the currently loaded fortress. <p>This generates a minecraft world out of the currently loaded fortress.
Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p> Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
<div class="warning"> <div class="warning">
@ -718,11 +722,11 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</div> </div>
</div> </div>
<div class="section" id="dfusion"> <div class="section" id="dfusion">
<h2><a class="toc-backref" href="#id49">dfusion</a></h2> <h2><a class="toc-backref" href="#id50">dfusion</a></h2>
<p>This is the DFusion lua plugin system by warmist/darius, running as a DFHack plugin.</p> <p>This is the DFusion lua plugin system by warmist/darius, running as a DFHack plugin.</p>
<p>See the bay12 thread for details: <a class="reference external" href="http://www.bay12forums.com/smf/index.php?topic=69682.15">http://www.bay12forums.com/smf/index.php?topic=69682.15</a></p> <p>See the bay12 thread for details: <a class="reference external" href="http://www.bay12forums.com/smf/index.php?topic=69682.15">http://www.bay12forums.com/smf/index.php?topic=69682.15</a></p>
<div class="section" id="confirmed-working-dfusion-plugins"> <div class="section" id="confirmed-working-dfusion-plugins">
<h3><a class="toc-backref" href="#id50">Confirmed working DFusion plugins:</a></h3> <h3><a class="toc-backref" href="#id51">Confirmed working DFusion plugins:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -742,11 +746,11 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</div> </div>
</div> </div>
<div class="section" id="drybuckets"> <div class="section" id="drybuckets">
<h2><a class="toc-backref" href="#id51">drybuckets</a></h2> <h2><a class="toc-backref" href="#id52">drybuckets</a></h2>
<p>This utility removes water from all buckets in your fortress, allowing them to be safely used for making lye.</p> <p>This utility removes water from all buckets in your fortress, allowing them to be safely used for making lye.</p>
</div> </div>
<div class="section" id="fastdwarf"> <div class="section" id="fastdwarf">
<h2><a class="toc-backref" href="#id52">fastdwarf</a></h2> <h2><a class="toc-backref" href="#id53">fastdwarf</a></h2>
<p>Makes your minions move at ludicrous speeds.</p> <p>Makes your minions move at ludicrous speeds.</p>
<blockquote> <blockquote>
<ul class="simple"> <ul class="simple">
@ -756,10 +760,10 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</blockquote> </blockquote>
</div> </div>
<div class="section" id="filltraffic"> <div class="section" id="filltraffic">
<h2><a class="toc-backref" href="#id53">filltraffic</a></h2> <h2><a class="toc-backref" href="#id54">filltraffic</a></h2>
<p>Set traffic designations using flood-fill starting at the cursor.</p> <p>Set traffic designations using flood-fill starting at the cursor.</p>
<div class="section" id="traffic-type-codes"> <div class="section" id="traffic-type-codes">
<h3><a class="toc-backref" href="#id54">Traffic Type Codes:</a></h3> <h3><a class="toc-backref" href="#id55">Traffic Type Codes:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -776,7 +780,7 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</table> </table>
</div> </div>
<div class="section" id="other-options"> <div class="section" id="other-options">
<h3><a class="toc-backref" href="#id55">Other Options:</a></h3> <h3><a class="toc-backref" href="#id56">Other Options:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -791,15 +795,15 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</table> </table>
</div> </div>
<div class="section" id="id5"> <div class="section" id="id5">
<h3><a class="toc-backref" href="#id56">Example:</a></h3> <h3><a class="toc-backref" href="#id57">Example:</a></h3>
<p>'filltraffic H' - When used in a room with doors, it will set traffic to HIGH in just that room.</p> <p>'filltraffic H' - When used in a room with doors, it will set traffic to HIGH in just that room.</p>
</div> </div>
</div> </div>
<div class="section" id="alltraffic"> <div class="section" id="alltraffic">
<h2><a class="toc-backref" href="#id57">alltraffic</a></h2> <h2><a class="toc-backref" href="#id58">alltraffic</a></h2>
<p>Set traffic designations for every single tile of the map (useful for resetting traffic designations).</p> <p>Set traffic designations for every single tile of the map (useful for resetting traffic designations).</p>
<div class="section" id="id6"> <div class="section" id="id6">
<h3><a class="toc-backref" href="#id58">Traffic Type Codes:</a></h3> <h3><a class="toc-backref" href="#id59">Traffic Type Codes:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -816,35 +820,35 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</table> </table>
</div> </div>
<div class="section" id="id7"> <div class="section" id="id7">
<h3><a class="toc-backref" href="#id59">Example:</a></h3> <h3><a class="toc-backref" href="#id60">Example:</a></h3>
<p>'alltraffic N' - Set traffic to 'normal' for all tiles.</p> <p>'alltraffic N' - Set traffic to 'normal' for all tiles.</p>
</div> </div>
</div> </div>
<div class="section" id="fixdiplomats"> <div class="section" id="fixdiplomats">
<h2><a class="toc-backref" href="#id60">fixdiplomats</a></h2> <h2><a class="toc-backref" href="#id61">fixdiplomats</a></h2>
<p>Up to version 0.31.12, Elves only sent Diplomats to your fortress to propose tree cutting quotas due to a bug; once that bug was fixed, Elves stopped caring about excess tree cutting. This command adds a Diplomat position to all Elven civilizations, allowing them to negotiate tree cutting quotas (and allowing you to violate them and potentially start wars) in case you haven't already modified your raws accordingly.</p> <p>Up to version 0.31.12, Elves only sent Diplomats to your fortress to propose tree cutting quotas due to a bug; once that bug was fixed, Elves stopped caring about excess tree cutting. This command adds a Diplomat position to all Elven civilizations, allowing them to negotiate tree cutting quotas (and allowing you to violate them and potentially start wars) in case you haven't already modified your raws accordingly.</p>
</div> </div>
<div class="section" id="fixmerchants"> <div class="section" id="fixmerchants">
<h2><a class="toc-backref" href="#id61">fixmerchants</a></h2> <h2><a class="toc-backref" href="#id62">fixmerchants</a></h2>
<p>This command adds the Guild Representative position to all Human civilizations, allowing them to make trade agreements (just as they did back in 0.28.181.40d and earlier) in case you haven't already modified your raws accordingly.</p> <p>This command adds the Guild Representative position to all Human civilizations, allowing them to make trade agreements (just as they did back in 0.28.181.40d and earlier) in case you haven't already modified your raws accordingly.</p>
</div> </div>
<div class="section" id="fixveins"> <div class="section" id="fixveins">
<h2><a class="toc-backref" href="#id62">fixveins</a></h2> <h2><a class="toc-backref" href="#id63">fixveins</a></h2>
<p>Removes invalid references to mineral inclusions and restores missing ones. Use this if you broke your embark with tools like tiletypes, or if you accidentally placed a construction on top of a valuable mineral floor.</p> <p>Removes invalid references to mineral inclusions and restores missing ones. Use this if you broke your embark with tools like tiletypes, or if you accidentally placed a construction on top of a valuable mineral floor.</p>
</div> </div>
<div class="section" id="fixwagons"> <div class="section" id="fixwagons">
<h2><a class="toc-backref" href="#id63">fixwagons</a></h2> <h2><a class="toc-backref" href="#id64">fixwagons</a></h2>
<p>Due to a bug in all releases of version 0.31, merchants no longer bring wagons with their caravans. This command re-enables them for all appropriate civilizations.</p> <p>Due to a bug in all releases of version 0.31, merchants no longer bring wagons with their caravans. This command re-enables them for all appropriate civilizations.</p>
</div> </div>
<div class="section" id="flows"> <div class="section" id="flows">
<h2><a class="toc-backref" href="#id64">flows</a></h2> <h2><a class="toc-backref" href="#id65">flows</a></h2>
<p>A tool for checking how many tiles contain flowing liquids. If you suspect that your magma sea leaks into HFS, you can use this tool to be sure without revealing the map.</p> <p>A tool for checking how many tiles contain flowing liquids. If you suspect that your magma sea leaks into HFS, you can use this tool to be sure without revealing the map.</p>
</div> </div>
<div class="section" id="getplants"> <div class="section" id="getplants">
<h2><a class="toc-backref" href="#id65">getplants</a></h2> <h2><a class="toc-backref" href="#id66">getplants</a></h2>
<p>This tool allows plant gathering and tree cutting by RAW ID. Specify the types of trees to cut down and/or shrubs to gather by their plant names, separated by spaces.</p> <p>This tool allows plant gathering and tree cutting by RAW ID. Specify the types of trees to cut down and/or shrubs to gather by their plant names, separated by spaces.</p>
<div class="section" id="id8"> <div class="section" id="id8">
<h3><a class="toc-backref" href="#id66">Options</a></h3> <h3><a class="toc-backref" href="#id67">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -863,15 +867,15 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</div> </div>
</div> </div>
<div class="section" id="tidlers"> <div class="section" id="tidlers">
<h2><a class="toc-backref" href="#id67">tidlers</a></h2> <h2><a class="toc-backref" href="#id68">tidlers</a></h2>
<p>Toggle between all possible positions where the idlers count can be placed.</p> <p>Toggle between all possible positions where the idlers count can be placed.</p>
</div> </div>
<div class="section" id="twaterlvl"> <div class="section" id="twaterlvl">
<h2><a class="toc-backref" href="#id68">twaterlvl</a></h2> <h2><a class="toc-backref" href="#id69">twaterlvl</a></h2>
<p>Toggle between displaying/not displaying liquid depth as numbers.</p> <p>Toggle between displaying/not displaying liquid depth as numbers.</p>
</div> </div>
<div class="section" id="job"> <div class="section" id="job">
<h2><a class="toc-backref" href="#id69">job</a></h2> <h2><a class="toc-backref" href="#id70">job</a></h2>
<p>Command for general job query and manipulation.</p> <p>Command for general job query and manipulation.</p>
<dl class="docutils"> <dl class="docutils">
<dt>Options:</dt> <dt>Options:</dt>
@ -885,7 +889,7 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</dl> </dl>
</div> </div>
<div class="section" id="job-material"> <div class="section" id="job-material">
<h2><a class="toc-backref" href="#id70">job-material</a></h2> <h2><a class="toc-backref" href="#id71">job-material</a></h2>
<p>Alter the material of the selected job. Invoked as: job-material &lt;inorganic-token&gt;</p> <p>Alter the material of the selected job. Invoked as: job-material &lt;inorganic-token&gt;</p>
<dl class="docutils"> <dl class="docutils">
<dt>Intended to be used as a keybinding:</dt> <dt>Intended to be used as a keybinding:</dt>
@ -897,7 +901,7 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</dl> </dl>
</div> </div>
<div class="section" id="job-duplicate"> <div class="section" id="job-duplicate">
<h2><a class="toc-backref" href="#id71">job-duplicate</a></h2> <h2><a class="toc-backref" href="#id72">job-duplicate</a></h2>
<dl class="docutils"> <dl class="docutils">
<dt>Duplicate the selected job in a workshop:</dt> <dt>Duplicate the selected job in a workshop:</dt>
<dd><ul class="first last simple"> <dd><ul class="first last simple">
@ -907,10 +911,10 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</dl> </dl>
</div> </div>
<div class="section" id="keybinding"> <div class="section" id="keybinding">
<h2><a class="toc-backref" href="#id72">keybinding</a></h2> <h2><a class="toc-backref" href="#id73">keybinding</a></h2>
<p>Manages DFHack keybindings. Currently it supports any combination of Ctrl/Alt/Shift with F1-F9, or A-Z.</p> <p>Manages DFHack keybindings. Currently it supports any combination of Ctrl/Alt/Shift with F1-F9, or A-Z.</p>
<div class="section" id="id9"> <div class="section" id="id9">
<h3><a class="toc-backref" href="#id73">Options</a></h3> <h3><a class="toc-backref" href="#id74">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -933,7 +937,7 @@ Generated worlds are placed into your DF folder, named &quot;World #&quot;.</p>
</div> </div>
</div> </div>
<div class="section" id="liquids"> <div class="section" id="liquids">
<h2><a class="toc-backref" href="#id74">liquids</a></h2> <h2><a class="toc-backref" href="#id75">liquids</a></h2>
<p>Allows adding magma, water and obsidian to the game. It replaces the normal dfhack command line and can't be used from a hotkey. <p>Allows adding magma, water and obsidian to the game. It replaces the normal dfhack command line and can't be used from a hotkey.
For more information, refer to the command's internal help.</p> For more information, refer to the command's internal help.</p>
<div class="note"> <div class="note">
@ -943,7 +947,7 @@ temperatures (creating heat traps). You've been warned.</p>
</div> </div>
</div> </div>
<div class="section" id="mode"> <div class="section" id="mode">
<h2><a class="toc-backref" href="#id75">mode</a></h2> <h2><a class="toc-backref" href="#id76">mode</a></h2>
<p>This command lets you see and change the game mode directly. Not all combinations are good for every situation and most of them will produce undesirable results. <p>This command lets you see and change the game mode directly. Not all combinations are good for every situation and most of them will produce undesirable results.
There are a few good ones though.</p> There are a few good ones though.</p>
<div class="admonition-example admonition"> <div class="admonition-example admonition">
@ -955,11 +959,11 @@ You just lost a fortress and gained an adventurer.</p>
<p>I take no responsibility of anything that happens as a result of using this tool :P</p> <p>I take no responsibility of anything that happens as a result of using this tool :P</p>
</div> </div>
<div class="section" id="extirpate"> <div class="section" id="extirpate">
<h2><a class="toc-backref" href="#id76">extirpate</a></h2> <h2><a class="toc-backref" href="#id77">extirpate</a></h2>
<p>A tool for getting rid of trees and shrubs. By default, it only kills a tree/shrub under the cursor. <p>A tool for getting rid of trees and shrubs. By default, it only kills a tree/shrub under the cursor.
The plants are turned into ashes instantly.</p> The plants are turned into ashes instantly.</p>
<div class="section" id="id10"> <div class="section" id="id10">
<h3><a class="toc-backref" href="#id77">Options</a></h3> <h3><a class="toc-backref" href="#id78">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -975,22 +979,22 @@ The plants are turned into ashes instantly.</p>
</div> </div>
</div> </div>
<div class="section" id="grow"> <div class="section" id="grow">
<h2><a class="toc-backref" href="#id78">grow</a></h2> <h2><a class="toc-backref" href="#id79">grow</a></h2>
<p>Makes all saplings present on the map grow into trees (almost) instantly.</p> <p>Makes all saplings present on the map grow into trees (almost) instantly.</p>
</div> </div>
<div class="section" id="immolate"> <div class="section" id="immolate">
<h2><a class="toc-backref" href="#id79">immolate</a></h2> <h2><a class="toc-backref" href="#id80">immolate</a></h2>
<p>Very similar to extirpate, but additionally sets the plants on fire. The fires can and <em>will</em> spread ;)</p> <p>Very similar to extirpate, but additionally sets the plants on fire. The fires can and <em>will</em> spread ;)</p>
</div> </div>
<div class="section" id="probe"> <div class="section" id="probe">
<h2><a class="toc-backref" href="#id80">probe</a></h2> <h2><a class="toc-backref" href="#id81">probe</a></h2>
<p>Can be used to determine tile properties like temperature.</p> <p>Can be used to determine tile properties like temperature.</p>
</div> </div>
<div class="section" id="prospect"> <div class="section" id="prospect">
<h2><a class="toc-backref" href="#id81">prospect</a></h2> <h2><a class="toc-backref" href="#id82">prospect</a></h2>
<p>Prints a big list of all the present minerals and plants. By default, only the visible part of the map is scanned.</p> <p>Prints a big list of all the present minerals and plants. By default, only the visible part of the map is scanned.</p>
<div class="section" id="id11"> <div class="section" id="id11">
<h3><a class="toc-backref" href="#id82">Options</a></h3> <h3><a class="toc-backref" href="#id83">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1005,13 +1009,13 @@ The plants are turned into ashes instantly.</p>
</table> </table>
</div> </div>
<div class="section" id="pre-embark-estimate"> <div class="section" id="pre-embark-estimate">
<h3><a class="toc-backref" href="#id83">Pre-embark estimate</a></h3> <h3><a class="toc-backref" href="#id84">Pre-embark estimate</a></h3>
<p>If called during the embark selection screen, displays an estimate of layer stone availability. <p>If called during the embark selection screen, displays an estimate of layer stone availability.
If the 'all' option is specified, also estimates veins. The estimate is computed either If the 'all' option is specified, also estimates veins. The estimate is computed either
for 1 embark tile of the blinking biome, or for all tiles of the embark rectangle.</p> for 1 embark tile of the blinking biome, or for all tiles of the embark rectangle.</p>
</div> </div>
<div class="section" id="id12"> <div class="section" id="id12">
<h3><a class="toc-backref" href="#id84">Options</a></h3> <h3><a class="toc-backref" href="#id85">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1023,14 +1027,14 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl
</div> </div>
</div> </div>
<div class="section" id="regrass"> <div class="section" id="regrass">
<h2><a class="toc-backref" href="#id85">regrass</a></h2> <h2><a class="toc-backref" href="#id86">regrass</a></h2>
<p>Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.</p> <p>Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.</p>
</div> </div>
<div class="section" id="rename"> <div class="section" id="rename">
<h2><a class="toc-backref" href="#id86">rename</a></h2> <h2><a class="toc-backref" href="#id87">rename</a></h2>
<p>Allows renaming various things.</p> <p>Allows renaming various things.</p>
<div class="section" id="id13"> <div class="section" id="id13">
<h3><a class="toc-backref" href="#id87">Options</a></h3> <h3><a class="toc-backref" href="#id88">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1052,36 +1056,37 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl
</div> </div>
</div> </div>
<div class="section" id="reveal"> <div class="section" id="reveal">
<h2><a class="toc-backref" href="#id88">reveal</a></h2> <h2><a class="toc-backref" href="#id89">reveal</a></h2>
<p>This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'.</p> <p>This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'.</p>
<p>Reveal also works in adventure mode, but any of its effects are negated once you move. When you use it this way, you don't need to run 'unreveal'.</p>
</div> </div>
<div class="section" id="unreveal"> <div class="section" id="unreveal">
<h2><a class="toc-backref" href="#id89">unreveal</a></h2> <h2><a class="toc-backref" href="#id90">unreveal</a></h2>
<p>Reverts the effects of 'reveal'.</p> <p>Reverts the effects of 'reveal'.</p>
</div> </div>
<div class="section" id="revtoggle"> <div class="section" id="revtoggle">
<h2><a class="toc-backref" href="#id90">revtoggle</a></h2> <h2><a class="toc-backref" href="#id91">revtoggle</a></h2>
<p>Switches between 'reveal' and 'unreveal'.</p> <p>Switches between 'reveal' and 'unreveal'.</p>
</div> </div>
<div class="section" id="revflood"> <div class="section" id="revflood">
<h2><a class="toc-backref" href="#id91">revflood</a></h2> <h2><a class="toc-backref" href="#id92">revflood</a></h2>
<p>This command will hide the whole map and then reveal all the tiles that have a path to the in-game cursor.</p> <p>This command will hide the whole map and then reveal all the tiles that have a path to the in-game cursor.</p>
</div> </div>
<div class="section" id="seedwatch"> <div class="section" id="seedwatch">
<h2><a class="toc-backref" href="#id92">seedwatch</a></h2> <h2><a class="toc-backref" href="#id93">seedwatch</a></h2>
<p>Tool for turning cooking of seeds and plants on/off depending on how much you have of them.</p> <p>Tool for turning cooking of seeds and plants on/off depending on how much you have of them.</p>
<p>See 'seedwatch help' for detailed description.</p> <p>See 'seedwatch help' for detailed description.</p>
</div> </div>
<div class="section" id="showmood"> <div class="section" id="showmood">
<h2><a class="toc-backref" href="#id93">showmood</a></h2> <h2><a class="toc-backref" href="#id94">showmood</a></h2>
<p>Shows all items needed for the currently active strange mood.</p> <p>Shows all items needed for the currently active strange mood.</p>
</div> </div>
<div class="section" id="copystock"> <div class="section" id="copystock">
<h2><a class="toc-backref" href="#id94">copystock</a></h2> <h2><a class="toc-backref" href="#id95">copystock</a></h2>
<p>Copies the parameters of the currently highlighted stockpile to the custom stockpile settings and switches to custom stockpile placement mode, effectively allowing you to copy/paste stockpiles easily.</p> <p>Copies the parameters of the currently highlighted stockpile to the custom stockpile settings and switches to custom stockpile placement mode, effectively allowing you to copy/paste stockpiles easily.</p>
</div> </div>
<div class="section" id="ssense-stonesense"> <div class="section" id="ssense-stonesense">
<h2><a class="toc-backref" href="#id95">ssense / stonesense</a></h2> <h2><a class="toc-backref" href="#id96">ssense / stonesense</a></h2>
<p>An isometric visualizer that runs in a second window. This requires working graphics acceleration and at least a dual core CPU (otherwise it will slow down DF).</p> <p>An isometric visualizer that runs in a second window. This requires working graphics acceleration and at least a dual core CPU (otherwise it will slow down DF).</p>
<p>All the data resides in the 'stonesense' directory. For detailed instructions, see stonesense/README.txt</p> <p>All the data resides in the 'stonesense' directory. For detailed instructions, see stonesense/README.txt</p>
<p>Compatible with Windows &gt; XP SP3 and most modern Linux distributions.</p> <p>Compatible with Windows &gt; XP SP3 and most modern Linux distributions.</p>
@ -1091,31 +1096,47 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl
<a class="reference external" href="http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository">http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository</a></p> <a class="reference external" href="http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository">http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository</a></p>
</div> </div>
<div class="section" id="tiletypes"> <div class="section" id="tiletypes">
<h2><a class="toc-backref" href="#id96">tiletypes</a></h2> <h2><a class="toc-backref" href="#id97">tiletypes</a></h2>
<p>Can be used for painting map tiles and is a interactive command, much like liquids. <p>Can be used for painting map tiles and is a interactive command, much like liquids.
You can paint tiles by their properties - shape, general material and a few others (paint). You can paint tiles by their properties - shape, general material and a few others (paint).
You can also paint only over tiles that match a set of properties (filter)</p> You can also paint only over tiles that match a set of properties (filter)</p>
<p>For more details, see the 'help' command while using this.</p> <p>For more details, see the 'help' command while using this.</p>
</div> </div>
<div class="section" id="tweak">
<h2><a class="toc-backref" href="#id98">tweak</a></h2>
<p>Contains various tweaks for minor bugs (currently just one).</p>
<div class="section" id="id14">
<h3><a class="toc-backref" href="#id99">Options</a></h3>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name" colspan="2">tweak clear-missing:</th></tr>
<tr class="field"><td>&nbsp;</td><td class="field-body">Remove the missing status from the selected unit. This allows engraving slabs for ghostly, but not yet found, creatures.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section" id="tubefill"> <div class="section" id="tubefill">
<h2><a class="toc-backref" href="#id97">tubefill</a></h2> <h2><a class="toc-backref" href="#id100">tubefill</a></h2>
<p>Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug).</p> <p>Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug).</p>
</div> </div>
<div class="section" id="vdig"> <div class="section" id="vdig">
<h2><a class="toc-backref" href="#id98">vdig</a></h2> <h2><a class="toc-backref" href="#id101">vdig</a></h2>
<p>Designates a whole vein for digging. Requires an active in-game cursor placed over a vein tile. With the 'x' option, it will traverse z-levels (putting stairs between the same-material tiles).</p> <p>Designates a whole vein for digging. Requires an active in-game cursor placed over a vein tile. With the 'x' option, it will traverse z-levels (putting stairs between the same-material tiles).</p>
</div> </div>
<div class="section" id="vdigx"> <div class="section" id="vdigx">
<h2><a class="toc-backref" href="#id99">vdigx</a></h2> <h2><a class="toc-backref" href="#id102">vdigx</a></h2>
<p>A permanent alias for 'vdig x'.</p> <p>A permanent alias for 'vdig x'.</p>
</div> </div>
<div class="section" id="expdig"> <div class="section" id="expdig">
<h2><a class="toc-backref" href="#id100">expdig</a></h2> <h2><a class="toc-backref" href="#id103">expdig</a></h2>
<p>This command can be used for exploratory mining.</p> <p>This command can be used for exploratory mining.</p>
<p>See: <a class="reference external" href="http://df.magmawiki.com/index.php/DF2010:Exploratory_mining">http://df.magmawiki.com/index.php/DF2010:Exploratory_mining</a></p> <p>See: <a class="reference external" href="http://df.magmawiki.com/index.php/DF2010:Exploratory_mining">http://df.magmawiki.com/index.php/DF2010:Exploratory_mining</a></p>
<p>There are two variables that can be set: pattern and filter.</p> <p>There are two variables that can be set: pattern and filter.</p>
<div class="section" id="patterns"> <div class="section" id="patterns">
<h3><a class="toc-backref" href="#id101">Patterns:</a></h3> <h3><a class="toc-backref" href="#id104">Patterns:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1136,7 +1157,7 @@ You can also paint only over tiles that match a set of properties (filter)</p>
</table> </table>
</div> </div>
<div class="section" id="filters"> <div class="section" id="filters">
<h3><a class="toc-backref" href="#id102">Filters:</a></h3> <h3><a class="toc-backref" href="#id105">Filters:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1152,7 +1173,7 @@ You can also paint only over tiles that match a set of properties (filter)</p>
<p>After you have a pattern set, you can use 'expdig' to apply it again.</p> <p>After you have a pattern set, you can use 'expdig' to apply it again.</p>
</div> </div>
<div class="section" id="examples"> <div class="section" id="examples">
<h3><a class="toc-backref" href="#id103">Examples:</a></h3> <h3><a class="toc-backref" href="#id106">Examples:</a></h3>
<dl class="docutils"> <dl class="docutils">
<dt>designate the diagonal 5 patter over all hidden tiles:</dt> <dt>designate the diagonal 5 patter over all hidden tiles:</dt>
<dd><ul class="first last simple"> <dd><ul class="first last simple">
@ -1173,11 +1194,11 @@ You can also paint only over tiles that match a set of properties (filter)</p>
</div> </div>
</div> </div>
<div class="section" id="digcircle"> <div class="section" id="digcircle">
<h2><a class="toc-backref" href="#id104">digcircle</a></h2> <h2><a class="toc-backref" href="#id107">digcircle</a></h2>
<p>A command for easy designation of filled and hollow circles. <p>A command for easy designation of filled and hollow circles.
It has several types of options.</p> It has several types of options.</p>
<div class="section" id="shape"> <div class="section" id="shape">
<h3><a class="toc-backref" href="#id105">Shape:</a></h3> <h3><a class="toc-backref" href="#id108">Shape:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1192,7 +1213,7 @@ It has several types of options.</p>
</table> </table>
</div> </div>
<div class="section" id="action"> <div class="section" id="action">
<h3><a class="toc-backref" href="#id106">Action:</a></h3> <h3><a class="toc-backref" href="#id109">Action:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1207,7 +1228,7 @@ It has several types of options.</p>
</table> </table>
</div> </div>
<div class="section" id="designation-types"> <div class="section" id="designation-types">
<h3><a class="toc-backref" href="#id107">Designation types:</a></h3> <h3><a class="toc-backref" href="#id110">Designation types:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1229,8 +1250,8 @@ It has several types of options.</p>
<p>After you have set the options, the command called with no options <p>After you have set the options, the command called with no options
repeats with the last selected parameters.</p> repeats with the last selected parameters.</p>
</div> </div>
<div class="section" id="id14"> <div class="section" id="id15">
<h3><a class="toc-backref" href="#id108">Examples:</a></h3> <h3><a class="toc-backref" href="#id111">Examples:</a></h3>
<ul class="simple"> <ul class="simple">
<li>'digcircle filled 3' = Dig a filled circle with radius = 3.</li> <li>'digcircle filled 3' = Dig a filled circle with radius = 3.</li>
<li>'digcircle' = Do it again.</li> <li>'digcircle' = Do it again.</li>
@ -1238,11 +1259,11 @@ repeats with the last selected parameters.</p>
</div> </div>
</div> </div>
<div class="section" id="weather"> <div class="section" id="weather">
<h2><a class="toc-backref" href="#id109">weather</a></h2> <h2><a class="toc-backref" href="#id112">weather</a></h2>
<p>Prints the current weather map by default.</p> <p>Prints the current weather map by default.</p>
<p>Also lets you change the current weather to 'clear sky', 'rainy' or 'snowing'.</p> <p>Also lets you change the current weather to 'clear sky', 'rainy' or 'snowing'.</p>
<div class="section" id="id15"> <div class="section" id="id16">
<h3><a class="toc-backref" href="#id110">Options:</a></h3> <h3><a class="toc-backref" href="#id113">Options:</a></h3>
<table class="docutils field-list" frame="void" rules="none"> <table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
@ -1258,10 +1279,10 @@ repeats with the last selected parameters.</p>
</div> </div>
</div> </div>
<div class="section" id="workflow"> <div class="section" id="workflow">
<h2><a class="toc-backref" href="#id111">workflow</a></h2> <h2><a class="toc-backref" href="#id114">workflow</a></h2>
<p>Manage control of repeat jobs.</p> <p>Manage control of repeat jobs.</p>
<div class="section" id="id16"> <div class="section" id="id17">
<h3><a class="toc-backref" href="#id112">Usage</a></h3> <h3><a class="toc-backref" href="#id115">Usage</a></h3>
<dl class="docutils"> <dl class="docutils">
<dt><tt class="docutils literal">workflow enable <span class="pre">[option...],</span> workflow disable <span class="pre">[option...]</span></tt></dt> <dt><tt class="docutils literal">workflow enable <span class="pre">[option...],</span> workflow disable <span class="pre">[option...]</span></tt></dt>
<dd><p class="first">If no options are specified, enables or disables the plugin. <dd><p class="first">If no options are specified, enables or disables the plugin.
@ -1282,7 +1303,7 @@ Otherwise, enables or disables any of the following options:</p>
</dl> </dl>
</div> </div>
<div class="section" id="function"> <div class="section" id="function">
<h3><a class="toc-backref" href="#id113">Function</a></h3> <h3><a class="toc-backref" href="#id116">Function</a></h3>
<p>When the plugin is enabled, it protects all repeat jobs from removal. <p>When the plugin is enabled, it protects all repeat jobs from removal.
If they do disappear due to any cause, they are immediately re-added to their If they do disappear due to any cause, they are immediately re-added to their
workshop and suspended.</p> workshop and suspended.</p>
@ -1293,7 +1314,7 @@ the amount has to drop before jobs are resumed; this is intended to reduce
the frequency of jobs being toggled.</p> the frequency of jobs being toggled.</p>
</div> </div>
<div class="section" id="constraint-examples"> <div class="section" id="constraint-examples">
<h3><a class="toc-backref" href="#id114">Constraint examples</a></h3> <h3><a class="toc-backref" href="#id117">Constraint examples</a></h3>
<p>Keep metal bolts within 900-1000, and wood/bone within 150-200.</p> <p>Keep metal bolts within 900-1000, and wood/bone within 150-200.</p>
<pre class="literal-block"> <pre class="literal-block">
workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100 workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100
@ -1330,11 +1351,11 @@ the Mill Plants job to MUSHROOM_CUP_DIMPLE using the 'job item-material' command
</div> </div>
</div> </div>
<div class="section" id="mapexport"> <div class="section" id="mapexport">
<h2><a class="toc-backref" href="#id115">mapexport</a></h2> <h2><a class="toc-backref" href="#id118">mapexport</a></h2>
<p>Export the current loaded map as a file. This will be eventually usable with visualizers.</p> <p>Export the current loaded map as a file. This will be eventually usable with visualizers.</p>
</div> </div>
<div class="section" id="dwarfexport"> <div class="section" id="dwarfexport">
<h2><a class="toc-backref" href="#id116">dwarfexport</a></h2> <h2><a class="toc-backref" href="#id119">dwarfexport</a></h2>
<p>Export dwarves to RuneSmith-compatible XML.</p> <p>Export dwarves to RuneSmith-compatible XML.</p>
</div> </div>
</div> </div>

@ -29,6 +29,7 @@ include/Internal.h
include/DFHack.h include/DFHack.h
include/Console.h include/Console.h
include/Core.h include/Core.h
include/ColorText.h
include/DataDefs.h include/DataDefs.h
include/Error.h include/Error.h
include/Export.h include/Export.h
@ -66,6 +67,7 @@ include/modules/Graphic.h
SET(PROJECT_SRCS SET(PROJECT_SRCS
Core.cpp Core.cpp
ColorText.cpp
DataDefs.cpp DataDefs.cpp
DataStatics.cpp DataStatics.cpp
DataStaticsCtor.cpp DataStaticsCtor.cpp
@ -101,6 +103,7 @@ modules/Vegetation.cpp
modules/Vermin.cpp modules/Vermin.cpp
modules/World.cpp modules/World.cpp
modules/Graphic.cpp modules/Graphic.cpp
modules/Windows.cpp
) )
SET(PROJECT_HDRS_WINDOWS SET(PROJECT_HDRS_WINDOWS
@ -140,6 +143,26 @@ ELSE()
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS}) LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS})
ENDIF() ENDIF()
# Protobuf
FILE(GLOB PROJECT_PROTOS ${CMAKE_CURRENT_SOURCE_DIR}/proto/*.proto)
STRING(REPLACE ".proto" ".pb.cc" PROJECT_PROTO_SRCS ${PROJECT_PROTOS})
STRING(REPLACE ".proto" ".pb.h" PROJECT_PROTO_HDRS ${PROJECT_PROTOS})
LIST(APPEND PROJECT_HDRS ${PROJECT_PROTO_HDRS})
LIST(APPEND PROJECT_SRCS ${PROJECT_PROTO_SRCS})
ADD_CUSTOM_COMMAND(
OUTPUT ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_HDRS}
COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/
--cpp_out=dllexport_decl=DFHACK_EXPORT:${CMAKE_CURRENT_SOURCE_DIR}/proto/
${PROJECT_PROTOS}
DEPENDS protoc-bin ${PROJECT_PROTOS}
)
#
SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE )
LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS})
@ -192,10 +215,16 @@ else()
ENDIF() ENDIF()
endif() endif()
IF(WIN32)
SET_TARGET_PROPERTIES(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
ELSE()
SET_TARGET_PROPERTIES(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" )
ENDIF()
#effectively disables debug builds... #effectively disables debug builds...
SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" ) SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
TARGET_LINK_LIBRARIES(dfhack ${PROJECT_LIBS}) TARGET_LINK_LIBRARIES(dfhack protobuf-lite ${PROJECT_LIBS})
IF(UNIX) IF(UNIX)
# On linux, copy our version of the df launch script which sets LD_PRELOAD # On linux, copy our version of the df launch script which sets LD_PRELOAD

@ -0,0 +1,190 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2011 Petr Mrázek <peterix@gmail.com>
A thread-safe logging console with a line editor for windows.
Based on linenoise win32 port,
copyright 2010, Jon Griffiths <jon_p_griffiths at yahoo dot com>.
All rights reserved.
Based on linenoise, copyright 2010, Salvatore Sanfilippo <antirez at gmail dot com>.
The original linenoise can be found at: http://github.com/antirez/linenoise
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Redis nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <istream>
#include <string>
#include "ColorText.h"
#include "MiscUtils.h"
#include <cstdio>
#include <cstdlib>
#include <sstream>
using namespace DFHack;
#include "tinythread.h"
using namespace tthread;
void color_ostream::flush_buffer(bool flush)
{
auto buffer = buf();
auto str = buffer->str();
if (!str.empty()) {
add_text(cur_color, buffer->str());
buffer->str(std::string());
}
if (flush)
flush_proxy();
}
void color_ostream::begin_batch()
{
flush_buffer(false);
}
void color_ostream::end_batch()
{
flush_proxy();
}
color_ostream::color_ostream() : ostream(new buffer(this)), cur_color(COLOR_RESET)
{
//
}
color_ostream::~color_ostream()
{
delete buf();
}
void color_ostream::print(const char *format, ...)
{
va_list args;
va_start(args, format);
vprint(format, args);
va_end(args);
}
void color_ostream::vprint(const char *format, va_list args)
{
std::string str = stl_vsprintf(format, args);
if (!str.empty()) {
flush_buffer(false);
add_text(cur_color, str);
if (str[str.size()-1] == '\n')
flush_proxy();
}
}
void color_ostream::printerr(const char * format, ...)
{
va_list args;
va_start(args, format);
vprinterr(format, args);
va_end(args);
}
void color_ostream::vprinterr(const char *format, va_list args)
{
color_value save = cur_color;
fprintf(stderr, format, args);
color(COLOR_LIGHTRED);
vprint(format, args);
color(save);
}
void color_ostream::color(color_value c)
{
if (c == cur_color)
return;
flush_buffer(false);
cur_color = c;
}
void color_ostream::reset_color(void)
{
color(COLOR_RESET);
}
void buffered_color_ostream::add_text(color_value color, const std::string &text)
{
if (text.empty())
return;
if (buffer.empty())
{
buffer.push_back(fragment_type(color, text));
}
else
{
auto &back = buffer.back();
if (back.first != color || std::max(back.second.size(), text.size()) > 128)
buffer.push_back(fragment_type(color, text));
else
buffer.back().second += text;
}
}
void color_ostream_proxy::flush_proxy()
{
if (!buffer.empty())
{
target->begin_batch();
for (auto it = buffer.begin(); it != buffer.end(); ++it)
target->add_text(it->first, it->second);
buffer.clear();
target->end_batch();
}
}
color_ostream_proxy::color_ostream_proxy(color_ostream &target)
: target(&target)
{
//
}
color_ostream_proxy::~color_ostream_proxy()
{
*this << std::flush;
}

@ -126,13 +126,14 @@ const char * getANSIColor(const int c)
namespace DFHack namespace DFHack
{ {
class Private : public std::stringbuf class Private
{ {
public: public:
Private() Private()
{ {
dfout_C = NULL; dfout_C = NULL;
rawmode = false; rawmode = false;
in_batch = false;
supported_terminal = false; supported_terminal = false;
state = con_unclaimed; state = con_unclaimed;
}; };
@ -164,68 +165,71 @@ namespace DFHack
return true; return true;
} }
} }
protected:
int sync()
{
print(str().c_str());
str(std::string()); // Clear the string buffer
return 0;
}
public: public:
/// Print a formatted string, like printf void print(const char *data)
int print(const char * format, ...)
{ {
va_list args; fputs(data, dfout_C);
va_start( args, format );
int ret = vprint( format, args );
va_end( args );
return ret;
} }
int vprint(const char * format, va_list vl)
void print_text(color_ostream::color_value clr, const std::string &chunk)
{ {
if(state == con_lineedit) if(!in_batch && state == con_lineedit)
{ {
disable_raw(); disable_raw();
fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[1G");
fprintf(dfout_C,"\x1b[0K"); fprintf(dfout_C,"\x1b[0K");
int ret = vfprintf( dfout_C, format, vl );
color(clr);
print(chunk.c_str());
reset_color();
enable_raw(); enable_raw();
prompt_refresh(); prompt_refresh();
return ret;
} }
else return vfprintf( dfout_C, format, vl ); else
{
color(clr);
print(chunk.c_str());
}
} }
int vprinterr(const char * format, va_list vl)
void begin_batch()
{ {
if(state == con_lineedit) assert(!in_batch);
in_batch = true;
if (state == con_lineedit)
{ {
disable_raw(); disable_raw();
color(Console::COLOR_LIGHTRED);
fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[1G");
fprintf(dfout_C,"\x1b[0K"); fprintf(dfout_C,"\x1b[0K");
int ret = vfprintf( dfout_C, format, vl );
reset_color();
enable_raw();
prompt_refresh();
return ret;
} }
else }
void end_batch()
{
assert(in_batch);
flush();
in_batch = false;
if (state == con_lineedit)
{ {
color(Console::COLOR_LIGHTRED);
int ret = vfprintf( dfout_C, format, vl );
reset_color(); reset_color();
return ret; enable_raw();
prompt_refresh();
} }
} }
/// Print a formatted string, like printf, in red
int printerr(const char * format, ...) void flush()
{ {
va_list args; if (!rawmode)
va_start( args, format ); fflush(dfout_C);
int ret = vprinterr( format, args );
va_end( args );
return ret;
} }
/// Clear the console, along with its scrollback /// Clear the console, along with its scrollback
void clear() void clear()
{ {
@ -243,7 +247,9 @@ namespace DFHack
/// Position cursor at x,y. 1,1 = top left corner /// Position cursor at x,y. 1,1 = top left corner
void gotoxy(int x, int y) void gotoxy(int x, int y)
{ {
print("\033[%d;%dH", y,x); char tmp[64];
sprintf(tmp,"\033[%d;%dH", y,x);
print(tmp);
} }
/// Set color (ANSI color number) /// Set color (ANSI color number)
void color(Console::color_value index) void color(Console::color_value index)
@ -291,18 +297,19 @@ namespace DFHack
/// beep. maybe? /// beep. maybe?
//void beep (void); //void beep (void);
/// A simple line edit (raw mode) /// A simple line edit (raw mode)
int lineedit(const std::string& prompt, std::string& output, mutex * lock, CommandHistory & ch) int lineedit(const std::string& prompt, std::string& output, recursive_mutex * lock, CommandHistory & ch)
{ {
output.clear(); output.clear();
reset_color();
this->prompt = prompt; this->prompt = prompt;
if (!supported_terminal) if (!supported_terminal)
{ {
print(prompt.c_str()); print(prompt.c_str());
fflush(dfout_C); fflush(dfout_C);
// FIXME: what do we do here??? // FIXME: what do we do here???
//SDL_mutexV(lock); //SDL_recursive_mutexV(lock);
std::getline(std::cin, output); std::getline(std::cin, output);
//SDL_mutexP(lock); //SDL_recursive_mutexP(lock);
return output.size(); return output.size();
} }
else else
@ -396,7 +403,7 @@ namespace DFHack
if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return; if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return;
} }
int prompt_loop(mutex * lock, CommandHistory & history) int prompt_loop(recursive_mutex * lock, CommandHistory & history)
{ {
int fd = STDIN_FILENO; int fd = STDIN_FILENO;
size_t plen = prompt.size(); size_t plen = prompt.size();
@ -606,6 +613,7 @@ namespace DFHack
con_unclaimed, con_unclaimed,
con_lineedit con_lineedit
} state; } state;
bool in_batch;
std::string prompt; // current prompt string std::string prompt; // current prompt string
std::string raw_buffer; // current raw mode buffer std::string raw_buffer; // current raw mode buffer
int raw_cursor; // cursor position in the buffer int raw_cursor; // cursor position in the buffer
@ -615,12 +623,12 @@ namespace DFHack
}; };
} }
Console::Console():std::ostream(0), std::ios(0) Console::Console()
{ {
d = 0; d = 0;
inited = false; inited = false;
// we can't create the mutex at this time. the SDL functions aren't hooked yet. // we can't create the mutex at this time. the SDL functions aren't hooked yet.
wlock = new mutex(); wlock = new recursive_mutex();
} }
Console::~Console() Console::~Console()
{ {
@ -643,7 +651,6 @@ bool Console::init(bool sharing)
d = new Private(); d = new Private();
// make our own weird streams so our IO isn't redirected // make our own weird streams so our IO isn't redirected
d->dfout_C = fopen("/dev/tty", "w"); d->dfout_C = fopen("/dev/tty", "w");
rdbuf(d);
std::cin.tie(this); std::cin.tie(this);
clear(); clear();
d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO); d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO);
@ -660,7 +667,7 @@ bool Console::shutdown(void)
{ {
if(!d) if(!d)
return true; return true;
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(d->rawmode) if(d->rawmode)
d->disable_raw(); d->disable_raw();
d->print("\n"); d->print("\n");
@ -670,46 +677,41 @@ bool Console::shutdown(void)
return true; return true;
} }
int Console::print( const char* format, ... ) void Console::begin_batch()
{ {
va_list args; //color_ostream::begin_batch();
lock_guard <mutex> g(*wlock);
int ret; wlock->lock();
if(!inited) ret = -1;
else if (inited)
{ d->begin_batch();
va_start( args, format );
ret = d->vprint(format, args);
va_end(args);
}
return ret;
} }
int Console::printerr( const char* format, ... ) void Console::end_batch()
{ {
va_list args; if (inited)
lock_guard <mutex> g(*wlock); d->end_batch();
int ret;
// also mirror in error log wlock->unlock();
if(!inited) }
{
va_start( args, format ); void Console::flush_proxy()
ret = vfprintf(stderr, format, args); {
va_end(args); lock_guard <recursive_mutex> g(*wlock);
} if (inited)
else d->flush();
{ }
va_start( args, format );
ret = d->vprinterr(format, args); void Console::add_text(color_value color, const std::string &text)
vfprintf(stderr, format, args); {
va_end(args); lock_guard <recursive_mutex> g(*wlock);
} if (inited)
return ret; d->print_text(color, text);
} }
int Console::get_columns(void) int Console::get_columns(void)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
int ret = -1; int ret = -1;
if(inited) if(inited)
ret = d->get_columns(); ret = d->get_columns();
@ -718,7 +720,7 @@ int Console::get_columns(void)
int Console::get_rows(void) int Console::get_rows(void)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
int ret = -1; int ret = -1;
if(inited) if(inited)
ret = d->get_rows(); ret = d->get_rows();
@ -727,42 +729,28 @@ int Console::get_rows(void)
void Console::clear() void Console::clear()
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->clear(); d->clear();
} }
void Console::gotoxy(int x, int y) void Console::gotoxy(int x, int y)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->gotoxy(x,y); d->gotoxy(x,y);
} }
void Console::color(color_value index)
{
lock_guard <mutex> g(*wlock);
if(inited)
d->color(index);
}
void Console::reset_color( void )
{
lock_guard <mutex> g(*wlock);
if(inited)
d->reset_color();
}
void Console::cursor(bool enable) void Console::cursor(bool enable)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->cursor(enable); d->cursor(enable);
} }
int Console::lineedit(const std::string & prompt, std::string & output, CommandHistory & ch) int Console::lineedit(const std::string & prompt, std::string & output, CommandHistory & ch)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
int ret = -2; int ret = -2;
if(inited) if(inited)
ret = d->lineedit(prompt,output,wlock,ch); ret = d->lineedit(prompt,output,wlock,ch);

@ -66,10 +66,10 @@ using namespace tthread;
namespace DFHack namespace DFHack
{ {
class Private : public std::stringbuf class Private
{ {
public: public:
Private() : basic_stringbuf<char>::basic_stringbuf() Private()
{ {
dfout_C = 0; dfout_C = 0;
rawmode = 0; rawmode = 0;
@ -78,69 +78,70 @@ namespace DFHack
ConsoleWindow = 0; ConsoleWindow = 0;
default_attributes = 0; default_attributes = 0;
state = con_unclaimed; state = con_unclaimed;
in_batch = false;
raw_cursor = 0; raw_cursor = 0;
}; };
virtual ~Private() virtual ~Private()
{ {
//sync(); //sync();
} }
protected:
int sync()
{
print (str().c_str());
// Clear the string buffer
str(std::string());
return 0;
}
public: public:
/// Print a formatted string, like printf void print(const char *data)
int print(const char * format, ...)
{ {
va_list args; fputs(data, dfout_C);
va_start( args, format );
int ret = vprint( format, args );
va_end( args );
return ret;
} }
int vprint(const char * format, va_list vl)
void print_text(color_ostream::color_value clr, const std::string &chunk)
{ {
if(state == con_lineedit) if(!in_batch && state == con_lineedit)
{ {
clearline(); clearline();
int ret = vfprintf( dfout_C, format, vl );
color(clr);
print(chunk.c_str());
reset_color();
prompt_refresh(); prompt_refresh();
return ret;
} }
else return vfprintf( dfout_C, format, vl ); else
{
color(clr);
print(chunk.c_str());
} }
int vprinterr(const char * format, va_list vl) }
void begin_batch()
{ {
if(state == con_lineedit) assert(!in_batch);
in_batch = true;
if (state == con_lineedit)
{ {
color(Console::COLOR_LIGHTRED);
clearline(); clearline();
int ret = vfprintf( dfout_C, format, vl );
reset_color();
prompt_refresh();
return ret;
} }
else }
void end_batch()
{
assert(in_batch);
flush();
in_batch = false;
if (state == con_lineedit)
{ {
color(Console::COLOR_LIGHTRED);
int ret = vfprintf( dfout_C, format, vl );
reset_color(); reset_color();
return ret; prompt_refresh();
} }
} }
/// Print a formatted string, like printf, in red
int printerr(const char * format, ...) void flush()
{ {
va_list args; fflush(dfout_C);
va_start( args, format );
int ret = vprinterr( format, args );
va_end( args );
return ret;
} }
int get_columns(void) int get_columns(void)
{ {
CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; CONSOLE_SCREEN_BUFFER_INFO inf = { 0 };
@ -250,7 +251,7 @@ namespace DFHack
SetConsoleCursorPosition(console_out, inf.dwCursorPosition); SetConsoleCursorPosition(console_out, inf.dwCursorPosition);
} }
int prompt_loop(mutex * lock, CommandHistory & history) int prompt_loop(recursive_mutex * lock, CommandHistory & history)
{ {
raw_buffer.clear(); // make sure the buffer is empty! raw_buffer.clear(); // make sure the buffer is empty!
size_t plen = prompt.size(); size_t plen = prompt.size();
@ -359,9 +360,10 @@ namespace DFHack
} }
} }
} }
int lineedit(const std::string & prompt, std::string & output, mutex * lock, CommandHistory & ch) int lineedit(const std::string & prompt, std::string & output, recursive_mutex * lock, CommandHistory & ch)
{ {
output.clear(); output.clear();
reset_color();
int count; int count;
state = con_lineedit; state = con_lineedit;
this->prompt = prompt; this->prompt = prompt;
@ -386,6 +388,7 @@ namespace DFHack
con_unclaimed, con_unclaimed,
con_lineedit con_lineedit
} state; } state;
bool in_batch;
std::string prompt; // current prompt string std::string prompt; // current prompt string
std::string raw_buffer; // current raw mode buffer std::string raw_buffer; // current raw mode buffer
int raw_cursor; // cursor position in the buffer int raw_cursor; // cursor position in the buffer
@ -393,7 +396,7 @@ namespace DFHack
} }
Console::Console():std::ostream(0), std::ios(0) Console::Console()
{ {
d = 0; d = 0;
wlock = 0; wlock = 0;
@ -453,7 +456,7 @@ bool Console::init(bool)
// Allocate a console! // Allocate a console!
AllocConsole(); AllocConsole();
d->ConsoleWindow = GetConsoleWindow(); d->ConsoleWindow = GetConsoleWindow();
wlock = new mutex(); wlock = new recursive_mutex();
HMENU hm = GetSystemMenu(d->ConsoleWindow,false); HMENU hm = GetSystemMenu(d->ConsoleWindow,false);
DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND); DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND);
@ -484,7 +487,6 @@ bool Console::init(bool)
std::ios::sync_with_stdio(); std::ios::sync_with_stdio();
// make our own weird streams so our IO isn't redirected // make our own weird streams so our IO isn't redirected
rdbuf(d);
std::cin.tie(this); std::cin.tie(this);
clear(); clear();
inited = true; inited = true;
@ -495,51 +497,47 @@ bool Console::init(bool)
// FIXME: looks awfully empty, doesn't it? // FIXME: looks awfully empty, doesn't it?
bool Console::shutdown(void) bool Console::shutdown(void)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
FreeConsole(); FreeConsole();
inited = false; inited = false;
return true; return true;
} }
int Console::print( const char* format, ... )
void Console::begin_batch()
{ {
va_list args; //color_ostream::begin_batch();
lock_guard <mutex> g(*wlock);
int ret; wlock->lock();
if(!inited) ret = -1;
else if (inited)
{ d->begin_batch();
va_start( args, format );
ret = d->vprint(format, args);
va_end(args);
}
return ret;
} }
int Console::printerr( const char* format, ... ) void Console::end_batch()
{ {
va_list args; if (inited)
lock_guard <mutex> g(*wlock); d->end_batch();
int ret;
// also mirror in error log wlock->unlock();
if(!inited) }
{
va_start( args, format ); void Console::flush_proxy()
ret = vfprintf(stderr, format, args); {
va_end(args); lock_guard <recursive_mutex> g(*wlock);
} if (inited)
else d->flush();
{ }
va_start( args, format );
ret = d->vprinterr(format, args); void Console::add_text(color_value color, const std::string &text)
vfprintf(stderr, format, args); {
va_end(args); lock_guard <recursive_mutex> g(*wlock);
} if (inited)
return ret; d->print_text(color, text);
} }
int Console::get_columns(void) int Console::get_columns(void)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
int ret = -1; int ret = -1;
if(inited) if(inited)
ret = d->get_columns(); ret = d->get_columns();
@ -548,7 +546,7 @@ int Console::get_columns(void)
int Console::get_rows(void) int Console::get_rows(void)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
int ret = -1; int ret = -1;
if(inited) if(inited)
ret = d->get_rows(); ret = d->get_rows();
@ -557,35 +555,21 @@ int Console::get_rows(void)
void Console::clear() void Console::clear()
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->clear(); d->clear();
} }
void Console::gotoxy(int x, int y) void Console::gotoxy(int x, int y)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->gotoxy(x,y); d->gotoxy(x,y);
} }
void Console::color(color_value index)
{
lock_guard <mutex> g(*wlock);
if(inited)
d->color(index);
}
void Console::reset_color( void )
{
lock_guard <mutex> g(*wlock);
if(inited)
d->reset_color();
}
void Console::cursor(bool enable) void Console::cursor(bool enable)
{ {
lock_guard <mutex> g(*wlock); lock_guard <recursive_mutex> g(*wlock);
if(inited) if(inited)
d->cursor(enable); d->cursor(enable);
} }

@ -47,11 +47,9 @@ using namespace std;
#include "modules/Gui.h" #include "modules/Gui.h"
#include "modules/World.h" #include "modules/World.h"
#include "modules/Graphic.h" #include "modules/Graphic.h"
//#include "modules/Windows.h" #include "modules/Windows.h"
using namespace DFHack; using namespace DFHack;
#include "SDL_events.h"
#include "df/ui.h" #include "df/ui.h"
#include "df/world.h" #include "df/world.h"
#include "df/world_data.h" #include "df/world_data.h"
@ -156,20 +154,22 @@ void fHKthread(void * iodata)
std::string stuff = core->getHotkeyCmd(); // waits on mutex! std::string stuff = core->getHotkeyCmd(); // waits on mutex!
if(!stuff.empty()) if(!stuff.empty())
{ {
color_ostream_proxy out(core->getConsole());
vector <string> args; vector <string> args;
cheap_tokenise(stuff, args); cheap_tokenise(stuff, args);
if (args.empty()) { if (args.empty()) {
core->con.printerr("Empty hotkey command.\n"); out.printerr("Empty hotkey command.\n");
continue; continue;
} }
string first = args[0]; string first = args[0];
args.erase(args.begin()); args.erase(args.begin());
command_result cr = plug_mgr->InvokeCommand(first, args, false); command_result cr = plug_mgr->InvokeCommand(out, first, args, false);
if(cr == CR_WOULD_BREAK) if(cr == CR_WOULD_BREAK)
{ {
core->con.printerr("It isn't possible to run an interactive command outside the console.\n"); out.printerr("It isn't possible to run an interactive command outside the console.\n");
} }
} }
} }
@ -192,7 +192,7 @@ struct sortable
static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clueless_counter, const string &command) static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clueless_counter, const string &command)
{ {
Console & con = core->con; Console & con = core->getConsole();
if (!command.empty()) if (!command.empty())
{ {
@ -471,7 +471,7 @@ static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clue
} }
else else
{ {
command_result res = plug_mgr->InvokeCommand(first, parts); command_result res = plug_mgr->InvokeCommand(con, first, parts);
if(res == CR_NOT_IMPLEMENTED) if(res == CR_NOT_IMPLEMENTED)
{ {
con.printerr("%s is not a recognized command.\n", first.c_str()); con.printerr("%s is not a recognized command.\n", first.c_str());
@ -506,7 +506,7 @@ void fIOthread(void * iodata)
CommandHistory main_history; CommandHistory main_history;
main_history.load("dfhack.history"); main_history.load("dfhack.history");
Console & con = core->con; Console & con = core->getConsole();
if(plug_mgr == 0 || core == 0) if(plug_mgr == 0 || core == 0)
{ {
con.printerr("Something horrible happened in Core's constructor...\n"); con.printerr("Something horrible happened in Core's constructor...\n");
@ -572,6 +572,7 @@ Core::Core()
misc_data_mutex=0; misc_data_mutex=0;
last_world_data_ptr = NULL; last_world_data_ptr = NULL;
top_viewscreen = NULL; top_viewscreen = NULL;
screen_window = NULL;
}; };
void Core::fatal (std::string output, bool deactivate) void Core::fatal (std::string output, bool deactivate)
@ -677,6 +678,8 @@ bool Core::Init()
HotkeyMutex = new mutex(); HotkeyMutex = new mutex();
HotkeyCond = new condition_variable(); HotkeyCond = new condition_variable();
thread * HK = new thread(fHKthread, (void *) temp); thread * HK = new thread(fHKthread, (void *) temp);
screen_window = new Windows::top_level_window();
screen_window->addChild(new Windows::dfhack_dummy(5,10));
started = true; started = true;
cerr << "DFHack is running.\n"; cerr << "DFHack is running.\n";
return true; return true;
@ -710,6 +713,16 @@ std::string Core::getHotkeyCmd( void )
return returner; return returner;
} }
void Core::printerr(const char *format, ...)
{
color_ostream_proxy proxy(getInstance().con);
va_list args;
va_start(args,format);
proxy.vprinterr(format,args);
va_end(args);
}
void Core::RegisterData( void *p, std::string key ) void Core::RegisterData( void *p, std::string key )
{ {
misc_data_mutex->lock(); misc_data_mutex->lock();
@ -755,29 +768,11 @@ void Core::Resume()
AccessMutex->unlock(); AccessMutex->unlock();
} }
struct screen_tile
{
unsigned char symbol;
unsigned char front;
unsigned char back;
unsigned char bright;
};
void screen_paint (int x, int y, uint8_t symbol)
{
int tile = x * df::global::gps->dimy + y;
screen_tile *s = (screen_tile *) (df::global::gps->screen + tile*4);
s->symbol = symbol;
}
int Core::TileUpdate() int Core::TileUpdate()
{ {
screen_paint(0,0,'D'); if(!started)
screen_paint(1,0,'F'); return false;
screen_paint(2,0,'H'); screen_window->paint();
screen_paint(3,0,'a');
screen_paint(4,0,'c');
screen_paint(5,0,'k');
return true; return true;
} }
@ -789,6 +784,8 @@ int Core::Update()
if(errorstate) if(errorstate)
return -1; return -1;
color_ostream_proxy out(con);
// detect if the game was loaded or unloaded in the meantime // detect if the game was loaded or unloaded in the meantime
void *new_wdata = NULL; void *new_wdata = NULL;
if (df::global::world) { if (df::global::world) {
@ -800,7 +797,7 @@ int Core::Update()
if (new_wdata != last_world_data_ptr) { if (new_wdata != last_world_data_ptr) {
last_world_data_ptr = new_wdata; last_world_data_ptr = new_wdata;
plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED); plug_mgr->OnStateChange(out, new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED);
} }
// detect if the viewscreen changed // detect if the viewscreen changed
@ -812,12 +809,14 @@ int Core::Update()
if (screen != top_viewscreen) if (screen != top_viewscreen)
{ {
top_viewscreen = screen; top_viewscreen = screen;
plug_mgr->OnStateChange(SC_VIEWSCREEN_CHANGED); plug_mgr->OnStateChange(out, SC_VIEWSCREEN_CHANGED);
} }
} }
// notify all the plugins that a game tick is finished // notify all the plugins that a game tick is finished
plug_mgr->OnUpdate(); plug_mgr->OnUpdate(out);
out << std::flush;
// wake waiting tools // wake waiting tools
// do not allow more tools to join in while we process stuff here // do not allow more tools to join in while we process stuff here
@ -897,6 +896,40 @@ bool Core::ncurses_wgetch(int in, int & out)
return true; return true;
} }
int Core::UnicodeAwareSym(const SDL::KeyboardEvent& ke)
{
// Assume keyboard layouts don't change the order of numbers:
if( '0' <= ke.ksym.sym && ke.ksym.sym <= '9') return ke.ksym.sym;
int unicode = ke.ksym.unicode;
// convert Ctrl characters to their 0x40-0x5F counterparts:
if (unicode < ' ')
{
unicode += 'A' - 1;
}
// convert A-Z to their a-z counterparts:
if('A' < unicode && unicode < 'Z')
{
unicode += 'a' - 'A';
}
// convert various other punctuation marks:
if('\"' == unicode) unicode = '\'';
if('+' == unicode) unicode = '=';
if(':' == unicode) unicode = ';';
if('<' == unicode) unicode = ',';
if('>' == unicode) unicode = '.';
if('?' == unicode) unicode = '/';
if('{' == unicode) unicode = '[';
if('|' == unicode) unicode = '\\';
if('}' == unicode) unicode = ']';
if('~' == unicode) unicode = '`';
return unicode;
}
//MEMO: return false if event is consumed //MEMO: return false if event is consumed
int Core::SDL_Event(SDL::Event* ev) int Core::SDL_Event(SDL::Event* ev)
{ {
@ -917,8 +950,19 @@ int Core::SDL_Event(SDL::Event* ev)
if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2; if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2;
if (ke->ksym.mod & SDL::KMOD_ALT) mod |= 4; if (ke->ksym.mod & SDL::KMOD_ALT) mod |= 4;
// Use unicode so Windows gives the correct value for the
// user's Input Language
if((ke->ksym.unicode & 0xff80) == 0)
{
int key = UnicodeAwareSym(*ke);
SelectHotkey(key, mod);
}
else
{
// Pretend non-ascii characters don't happen:
SelectHotkey(ke->ksym.sym, mod); SelectHotkey(ke->ksym.sym, mod);
} }
}
else if(ke->state == SDL::BTN_RELEASED) else if(ke->state == SDL::BTN_RELEASED)
{ {
hotkey_states[ke->ksym.sym] = false; hotkey_states[ke->ksym.sym] = false;

@ -404,6 +404,10 @@ DFhackCExport int SDL_EnableKeyRepeat(int delay, int interval)
static int (*_SDL_EnableUNICODE)(int enable) = 0; static int (*_SDL_EnableUNICODE)(int enable) = 0;
DFhackCExport int SDL_EnableUNICODE(int enable) DFhackCExport int SDL_EnableUNICODE(int enable)
{ {
if(!enable)
{
fprintf(stderr, "SDL_EnableUNICODE turned off. Keybindings may break.\n");
}
return _SDL_EnableUNICODE(enable); return _SDL_EnableUNICODE(enable);
} }
@ -800,6 +804,8 @@ bool FirstCall()
_SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait"); _SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait");
_SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID"); _SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID");
_SDL_EnableUNICODE(1);
fprintf(stderr,"Initized HOOKS!\n"); fprintf(stderr,"Initized HOOKS!\n");
inited = true; inited = true;
return 1; return 1;

@ -140,7 +140,6 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f
break; break;
name.append(1,ch); name.append(1,ch);
} }
Console & con = core->con;
plugin_lib = 0; plugin_lib = 0;
plugin_init = 0; plugin_init = 0;
plugin_shutdown = 0; plugin_shutdown = 0;
@ -172,7 +171,7 @@ bool Plugin::load()
return true; return true;
} }
Core & c = Core::getInstance(); Core & c = Core::getInstance();
Console & con = c.con; Console & con = c.getConsole();
DFLibrary * plug = OpenPlugin(filename.c_str()); DFLibrary * plug = OpenPlugin(filename.c_str());
if(!plug) if(!plug)
{ {
@ -197,7 +196,7 @@ bool Plugin::load()
state = PS_BROKEN; state = PS_BROKEN;
return false; return false;
} }
plugin_init = (command_result (*)(Core *, std::vector <PluginCommand> &)) LookupPlugin(plug, "plugin_init"); plugin_init = (command_result (*)(color_ostream &, std::vector <PluginCommand> &)) LookupPlugin(plug, "plugin_init");
if(!plugin_init) if(!plugin_init)
{ {
con.printerr("Plugin %s has no init function.\n", filename.c_str()); con.printerr("Plugin %s has no init function.\n", filename.c_str());
@ -205,13 +204,13 @@ bool Plugin::load()
state = PS_BROKEN; state = PS_BROKEN;
return false; return false;
} }
plugin_status = (command_result (*)(Core *, std::string &)) LookupPlugin(plug, "plugin_status"); plugin_status = (command_result (*)(color_ostream &, std::string &)) LookupPlugin(plug, "plugin_status");
plugin_onupdate = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_onupdate"); plugin_onupdate = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_onupdate");
plugin_shutdown = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_shutdown"); plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(Core *, state_change_event)) LookupPlugin(plug, "plugin_onstatechange"); plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
this->name = *plug_name; this->name = *plug_name;
plugin_lib = plug; plugin_lib = plug;
if(plugin_init(&c,commands) == CR_OK) if(plugin_init(con,commands) == CR_OK)
{ {
state = PS_LOADED; state = PS_LOADED;
parent->registerCommands(this); parent->registerCommands(this);
@ -229,14 +228,14 @@ bool Plugin::load()
bool Plugin::unload() bool Plugin::unload()
{ {
Core & c = Core::getInstance(); Core & c = Core::getInstance();
Console & con = c.con; Console & con = c.getConsole();
// get the mutex // get the mutex
access->lock(); access->lock();
// if we are actually loaded // if we are actually loaded
if(state == PS_LOADED) if(state == PS_LOADED)
{ {
// notify plugin about shutdown // notify plugin about shutdown
command_result cr = plugin_shutdown(&Core::getInstance()); command_result cr = plugin_shutdown(con);
// wait for all calls to finish // wait for all calls to finish
access->wait(); access->wait();
// cleanup... // cleanup...
@ -276,7 +275,7 @@ bool Plugin::reload()
return true; return true;
} }
command_result Plugin::invoke( std::string & command, std::vector <std::string> & parameters, bool interactive_) command_result Plugin::invoke(color_ostream &out, std::string & command, std::vector <std::string> & parameters, bool interactive_)
{ {
Core & c = Core::getInstance(); Core & c = Core::getInstance();
command_result cr = CR_NOT_IMPLEMENTED; command_result cr = CR_NOT_IMPLEMENTED;
@ -289,7 +288,7 @@ command_result Plugin::invoke( std::string & command, std::vector <std::string>
if(cmd.name == command) if(cmd.name == command)
{ {
// running interactive things from some other source than the console would break it // running interactive things from some other source than the console would break it
if(!interactive_ && cmd.interactive) if(!(interactive_ && out.is_console()) && cmd.interactive)
cr = CR_WOULD_BREAK; cr = CR_WOULD_BREAK;
else if (cmd.guard) else if (cmd.guard)
{ {
@ -300,22 +299,22 @@ command_result Plugin::invoke( std::string & command, std::vector <std::string>
CoreSuspender suspend(&c); CoreSuspender suspend(&c);
df::viewscreen *top = c.getTopViewscreen(); df::viewscreen *top = c.getTopViewscreen();
if (!cmd.guard(&c, top)) if (!cmd.guard(top))
{ {
c.con.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str()); out.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str());
cr = CR_WRONG_USAGE; cr = CR_WRONG_USAGE;
} }
else else
{ {
cr = cmd.function(&c, parameters); cr = cmd.function(out, parameters);
} }
} }
else else
{ {
cr = cmd.function(&c, parameters); cr = cmd.function(out, parameters);
} }
if (cr == CR_WRONG_USAGE && !cmd.usage.empty()) if (cr == CR_WRONG_USAGE && !cmd.usage.empty())
c.con << "Usage:\n" << cmd.usage << flush; out << "Usage:\n" << cmd.usage << flush;
break; break;
} }
} }
@ -339,9 +338,9 @@ bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top )
if (cmd.interactive) if (cmd.interactive)
cr = false; cr = false;
else if (cmd.guard) else if (cmd.guard)
cr = cmd.guard(&c, top); cr = cmd.guard(top);
else else
cr = Gui::default_hotkey(&c, top); cr = Gui::default_hotkey(top);
break; break;
} }
} }
@ -350,27 +349,25 @@ bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top )
return cr; return cr;
} }
command_result Plugin::on_update() command_result Plugin::on_update(color_ostream &out)
{ {
Core & c = Core::getInstance();
command_result cr = CR_NOT_IMPLEMENTED; command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add(); access->lock_add();
if(state == PS_LOADED && plugin_onupdate) if(state == PS_LOADED && plugin_onupdate)
{ {
cr = plugin_onupdate(&c); cr = plugin_onupdate(out);
} }
access->lock_sub(); access->lock_sub();
return cr; return cr;
} }
command_result Plugin::on_state_change(state_change_event event) command_result Plugin::on_state_change(color_ostream &out, state_change_event event)
{ {
Core & c = Core::getInstance();
command_result cr = CR_NOT_IMPLEMENTED; command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add(); access->lock_add();
if(state == PS_LOADED && plugin_onstatechange) if(state == PS_LOADED && plugin_onstatechange)
{ {
cr = plugin_onstatechange(&c, event); cr = plugin_onstatechange(out, event);
} }
access->lock_sub(); access->lock_sub();
return cr; return cr;
@ -436,10 +433,10 @@ Plugin *PluginManager::getPluginByCommand(const std::string &command)
} }
// FIXME: handle name collisions... // FIXME: handle name collisions...
command_result PluginManager::InvokeCommand( std::string & command, std::vector <std::string> & parameters, bool interactive) command_result PluginManager::InvokeCommand(color_ostream &out, std::string & command, std::vector <std::string> & parameters, bool interactive)
{ {
Plugin *plugin = getPluginByCommand(command); Plugin *plugin = getPluginByCommand(command);
return plugin ? plugin->invoke(command, parameters, interactive) : CR_NOT_IMPLEMENTED; return plugin ? plugin->invoke(out, command, parameters, interactive) : CR_NOT_IMPLEMENTED;
} }
bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top) bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top)
@ -448,19 +445,19 @@ bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top)
return plugin ? plugin->can_invoke_hotkey(command, top) : false; return plugin ? plugin->can_invoke_hotkey(command, top) : false;
} }
void PluginManager::OnUpdate( void ) void PluginManager::OnUpdate(color_ostream &out)
{ {
for(size_t i = 0; i < all_plugins.size(); i++) for(size_t i = 0; i < all_plugins.size(); i++)
{ {
all_plugins[i]->on_update(); all_plugins[i]->on_update(out);
} }
} }
void PluginManager::OnStateChange( state_change_event event ) void PluginManager::OnStateChange(color_ostream &out, state_change_event event)
{ {
for(size_t i = 0; i < all_plugins.size(); i++) for(size_t i = 0; i < all_plugins.size(); i++)
{ {
all_plugins[i]->on_state_change(event); all_plugins[i]->on_state_change(out, event);
} }
} }

@ -91,6 +91,8 @@ google/protobuf/wire_format_lite.h
google/protobuf/wire_format_lite_inl.h google/protobuf/wire_format_lite_inl.h
google/protobuf/io/zero_copy_stream.h google/protobuf/io/zero_copy_stream.h
google/protobuf/io/zero_copy_stream_impl_lite.h google/protobuf/io/zero_copy_stream_impl_lite.h
google/protobuf/io/gzip_stream.h
google/protobuf/io/zero_copy_stream_impl.h
) )
SET(LIBPROTOBUF_FULL_HDRS SET(LIBPROTOBUF_FULL_HDRS
@ -99,7 +101,6 @@ google/protobuf/descriptor.pb.h
google/protobuf/descriptor_database.h google/protobuf/descriptor_database.h
google/protobuf/dynamic_message.h google/protobuf/dynamic_message.h
google/protobuf/generated_message_reflection.h google/protobuf/generated_message_reflection.h
google/protobuf/io/gzip_stream.h
google/protobuf/compiler/importer.h google/protobuf/compiler/importer.h
google/protobuf/message.h google/protobuf/message.h
google/protobuf/compiler/parser.h google/protobuf/compiler/parser.h
@ -112,7 +113,6 @@ google/protobuf/text_format.h
google/protobuf/io/tokenizer.h google/protobuf/io/tokenizer.h
google/protobuf/unknown_field_set.h google/protobuf/unknown_field_set.h
google/protobuf/wire_format.h google/protobuf/wire_format.h
google/protobuf/io/zero_copy_stream_impl.h
) )
LIST(APPEND LIBPROTOBUF_FULL_HDRS ${LIBPROTOBUF_LITE_HDRS}) LIST(APPEND LIBPROTOBUF_FULL_HDRS ${LIBPROTOBUF_LITE_HDRS})
@ -128,6 +128,8 @@ google/protobuf/repeated_field.cc
google/protobuf/wire_format_lite.cc google/protobuf/wire_format_lite.cc
google/protobuf/io/zero_copy_stream.cc google/protobuf/io/zero_copy_stream.cc
google/protobuf/io/zero_copy_stream_impl_lite.cc google/protobuf/io/zero_copy_stream_impl_lite.cc
google/protobuf/io/gzip_stream.cc
google/protobuf/io/zero_copy_stream_impl.cc
) )
SET(LIBPROTOBUF_FULL_SRCS SET(LIBPROTOBUF_FULL_SRCS
@ -137,8 +139,8 @@ google/protobuf/descriptor_database.cc
google/protobuf/dynamic_message.cc google/protobuf/dynamic_message.cc
google/protobuf/extension_set_heavy.cc google/protobuf/extension_set_heavy.cc
google/protobuf/generated_message_reflection.cc google/protobuf/generated_message_reflection.cc
google/protobuf/io/gzip_stream.cc
google/protobuf/compiler/importer.cc google/protobuf/compiler/importer.cc
google/protobuf/io/gzip_stream.cc
google/protobuf/message.cc google/protobuf/message.cc
google/protobuf/compiler/parser.cc google/protobuf/compiler/parser.cc
google/protobuf/io/printer.cc google/protobuf/io/printer.cc
@ -199,11 +201,33 @@ google/protobuf/compiler/zip_writer.cc
LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS}) LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${dfhack_SOURCE_DIR}/library/depends/zlib) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
# Protobuf shared libraries
ADD_LIBRARY(protobuf SHARED ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS})
ADD_LIBRARY(protobuf-lite SHARED ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS})
SET_TARGET_PROPERTIES(protobuf PROPERTIES COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS)
SET_TARGET_PROPERTIES(protobuf-lite PROPERTIES COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS)
TARGET_LINK_LIBRARIES(protobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
TARGET_LINK_LIBRARIES(protobuf-lite ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
install(TARGETS protobuf-lite
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}/deplibs
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION}/deplibs)
# Protobuf compiler shared library
ADD_LIBRARY(protoc SHARED ${LIBPROTOC_SRCS} ${LIBPROTOC_HDRS})
SET_TARGET_PROPERTIES(protoc PROPERTIES COMPILE_DEFINITIONS LIBPROTOC_EXPORTS)
TARGET_LINK_LIBRARIES(protoc protobuf)
# Protobuf compiler executable
ADD_LIBRARY(protobuf-lite ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS})
ADD_LIBRARY(protobuf ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS})
ADD_LIBRARY(protoc ${LIBPROTOC_SRCS} ${LIBPROTOC_HDRS})
ADD_EXECUTABLE(protoc-bin google/protobuf/compiler/main.cc google/protobuf/compiler/command_line_interface.h google/protobuf/compiler/cpp/cpp_generator.h) ADD_EXECUTABLE(protoc-bin google/protobuf/compiler/main.cc google/protobuf/compiler/command_line_interface.h google/protobuf/compiler/cpp/cpp_generator.h)
SET_TARGET_PROPERTIES(protoc-bin PROPERTIES OUTPUT_NAME protoc) SET_TARGET_PROPERTIES(protoc-bin PROPERTIES OUTPUT_NAME protoc)
TARGET_LINK_LIBRARIES(protoc-bin protoc protobuf ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(protoc-bin protoc)

@ -72,7 +72,7 @@ double Infinity();
double NaN(); double NaN();
// Constant used for empty default strings. // Constant used for empty default strings.
extern const ::std::string kEmptyString; extern LIBPROTOBUF_EXPORT const ::std::string kEmptyString;
} // namespace internal } // namespace internal

@ -305,7 +305,7 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
static void Merge(const string& from, string* to) { *to = from; } static void Merge(const string& from, string* to) { *to = from; }
}; };
class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase { class StringTypeHandler : public StringTypeHandlerBase {
public: public:
static int SpaceUsed(const string& value) { static int SpaceUsed(const string& value) {
return sizeof(value) + StringSpaceUsedExcludingSelf(value); return sizeof(value) + StringSpaceUsedExcludingSelf(value);

@ -96,6 +96,9 @@ namespace protobuf {
#else #else
#define LIBPROTOC_EXPORT __declspec(dllimport) #define LIBPROTOC_EXPORT __declspec(dllimport)
#endif #endif
#elif defined(PROTOBUF_USE_DLLS)
#define LIBPROTOBUF_EXPORT __attribute__ ((visibility("default")))
#define LIBPROTOC_EXPORT __attribute__ ((visibility("default")))
#else #else
#define LIBPROTOBUF_EXPORT #define LIBPROTOBUF_EXPORT
#define LIBPROTOC_EXPORT #define LIBPROTOC_EXPORT

@ -67,6 +67,7 @@ freely, subject to the following restrictions:
// Platform specific includes // Platform specific includes
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
#define NOMINMAX
#include <windows.h> #include <windows.h>
#else #else
#include <pthread.h> #include <pthread.h>

@ -0,0 +1,145 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#include "Pragma.h"
#include "Export.h"
#include <list>
#include <fstream>
#include <assert.h>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <sstream>
namespace DFHack
{
class DFHACK_EXPORT color_ostream : public std::ostream
{
public:
enum color_value
{
COLOR_RESET = -1,
COLOR_BLACK = 0,
COLOR_BLUE,
COLOR_GREEN,
COLOR_CYAN,
COLOR_RED,
COLOR_MAGENTA,
COLOR_BROWN,
COLOR_GREY,
COLOR_DARKGREY,
COLOR_LIGHTBLUE,
COLOR_LIGHTGREEN,
COLOR_LIGHTCYAN,
COLOR_LIGHTRED,
COLOR_LIGHTMAGENTA,
COLOR_YELLOW,
COLOR_WHITE,
COLOR_MAX = COLOR_WHITE
};
private:
color_value cur_color;
class buffer : public std::stringbuf
{
public:
color_ostream *owner;
buffer(color_ostream *owner) : owner(owner) {}
virtual ~buffer() { }
protected:
virtual int sync() {
owner->flush_buffer(true);
return 0;
}
};
buffer *buf() { return (buffer*)rdbuf(); }
void flush_buffer(bool flush);
protected:
// These must be strictly balanced, because
// they might grab and hold mutexes.
virtual void begin_batch();
virtual void end_batch();
virtual void add_text(color_value color, const std::string &text) = 0;
virtual void flush_proxy() {};
friend class color_ostream_proxy;
public:
color_ostream();
virtual ~color_ostream();
/// Print a formatted string, like printf
void print(const char *format, ...);
void vprint(const char *format, va_list args);
/// Print a formatted string, like printf, in red
void printerr(const char *format, ...);
void vprinterr(const char *format, va_list args);
/// Set color (ANSI color number)
void color(color_value c);
/// Reset color to default
void reset_color(void);
virtual bool is_console() { return false; }
};
class DFHACK_EXPORT buffered_color_ostream : public color_ostream
{
protected:
virtual void add_text(color_value color, const std::string &text);
public:
typedef std::pair<color_value,std::string> fragment_type;
buffered_color_ostream() {}
~buffered_color_ostream() {}
const std::list<fragment_type> &fragments() { return buffer; }
protected:
std::list<fragment_type> buffer;
};
class DFHACK_EXPORT color_ostream_proxy : public buffered_color_ostream
{
protected:
color_ostream *target;
virtual void flush_proxy();
public:
color_ostream_proxy(color_ostream &target);
~color_ostream_proxy();
};
}

@ -25,6 +25,7 @@ distribution.
#pragma once #pragma once
#include "Pragma.h" #include "Pragma.h"
#include "Export.h" #include "Export.h"
#include "ColorText.h"
#include <deque> #include <deque>
#include <fstream> #include <fstream>
#include <assert.h> #include <assert.h>
@ -33,6 +34,7 @@ distribution.
namespace tthread namespace tthread
{ {
class mutex; class mutex;
class recursive_mutex;
class condition_variable; class condition_variable;
class thread; class thread;
} }
@ -106,31 +108,18 @@ namespace DFHack
std::size_t capacity; std::size_t capacity;
std::deque <std::string> history; std::deque <std::string> history;
}; };
class Private; class Private;
class DFHACK_EXPORT Console : public std::ostream class DFHACK_EXPORT Console : public color_ostream
{ {
protected:
virtual void begin_batch();
virtual void add_text(color_value color, const std::string &text);
virtual void end_batch();
virtual void flush_proxy();
public: public:
enum color_value
{
COLOR_RESET = -1,
COLOR_BLACK = 0,
COLOR_BLUE,
COLOR_GREEN,
COLOR_CYAN,
COLOR_RED,
COLOR_MAGENTA,
COLOR_BROWN,
COLOR_GREY,
COLOR_DARKGREY,
COLOR_LIGHTBLUE,
COLOR_LIGHTGREEN,
COLOR_LIGHTCYAN,
COLOR_LIGHTRED,
COLOR_LIGHTMAGENTA,
COLOR_YELLOW,
COLOR_WHITE,
COLOR_MAX = COLOR_WHITE
};
///ctor, NOT thread-safe ///ctor, NOT thread-safe
Console(); Console();
///dtor, NOT thread-safe ///dtor, NOT thread-safe
@ -140,18 +129,10 @@ namespace DFHack
/// shutdown the console. NOT thread-safe /// shutdown the console. NOT thread-safe
bool shutdown( void ); bool shutdown( void );
/// Print a formatted string, like printf
int print(const char * format, ...);
/// Print a formatted string, like printf, in red
int printerr(const char * format, ...);
/// Clear the console, along with its scrollback /// Clear the console, along with its scrollback
void clear(); void clear();
/// Position cursor at x,y. 1,1 = top left corner /// Position cursor at x,y. 1,1 = top left corner
void gotoxy(int x, int y); void gotoxy(int x, int y);
/// Set color (ANSI color number)
void color(color_value c);
/// Reset color to default
void reset_color(void);
/// Enable or disable the caret/cursor /// Enable or disable the caret/cursor
void cursor(bool enable = true); void cursor(bool enable = true);
/// Waits given number of milliseconds before continuing. /// Waits given number of milliseconds before continuing.
@ -165,9 +146,11 @@ namespace DFHack
/// A simple line edit (raw mode) /// A simple line edit (raw mode)
int lineedit(const std::string& prompt, std::string& output, CommandHistory & history ); int lineedit(const std::string& prompt, std::string& output, CommandHistory & history );
bool isInited (void) { return inited; }; bool isInited (void) { return inited; };
bool is_console() { return true; }
private: private:
Private * d; Private * d;
tthread::mutex * wlock; tthread::recursive_mutex * wlock;
bool inited; bool inited;
}; };
} }

@ -33,6 +33,7 @@ distribution.
#include <stdint.h> #include <stdint.h>
#include "Console.h" #include "Console.h"
#include "modules/Graphic.h" #include "modules/Graphic.h"
#include "SDL_events.h"
struct WINDOW; struct WINDOW;
@ -59,6 +60,10 @@ namespace DFHack
class VersionInfoFactory; class VersionInfoFactory;
class PluginManager; class PluginManager;
class Core; class Core;
namespace Windows
{
class df_window;
}
// anon type, pretty much // anon type, pretty much
struct DFLibrary; struct DFLibrary;
@ -120,12 +125,20 @@ namespace DFHack
std::vector<std::string> ListKeyBindings(std::string keyspec); std::vector<std::string> ListKeyBindings(std::string keyspec);
bool isWorldLoaded() { return (last_world_data_ptr != NULL); } bool isWorldLoaded() { return (last_world_data_ptr != NULL); }
df::viewscreen *getTopViewscreen() { return top_viewscreen; }
static df::viewscreen *getTopViewscreen() { return getInstance().top_viewscreen; }
DFHack::Console &getConsole() { return con; }
DFHack::Process * p; DFHack::Process * p;
DFHack::VersionInfo * vinfo; DFHack::VersionInfo * vinfo;
DFHack::Console con; DFHack::Windows::df_window * screen_window;
static void printerr(const char *format, ...);
private: private:
DFHack::Console con;
Core(); Core();
bool Init(); bool Init();
int Update (void); int Update (void);
@ -172,6 +185,7 @@ namespace DFHack
tthread::mutex * HotkeyMutex; tthread::mutex * HotkeyMutex;
tthread::condition_variable * HotkeyCond; tthread::condition_variable * HotkeyCond;
int UnicodeAwareSym(const SDL::KeyboardEvent& ke);
bool SelectHotkey(int key, int modifiers); bool SelectHotkey(int key, int modifiers);
void *last_world_data_ptr; // for state change tracking void *last_world_data_ptr; // for state change tracking
@ -186,6 +200,7 @@ namespace DFHack
class CoreSuspender { class CoreSuspender {
Core *core; Core *core;
public: public:
CoreSuspender() : core(&Core::getInstance()) { core->Suspend(); }
CoreSuspender(Core *core) : core(core) { core->Suspend(); } CoreSuspender(Core *core) : core(core) { core->Suspend(); }
~CoreSuspender() { core->Resume(); } ~CoreSuspender() { core->Resume(); }
}; };

@ -35,7 +35,7 @@ distribution.
using namespace std; using namespace std;
template <typename T> template <typename T>
void print_bits ( T val, DFHack::Console& out ) void print_bits ( T val, ostream& out )
{ {
stringstream strs; stringstream strs;
T n_bits = sizeof ( val ) * CHAR_BIT; T n_bits = sizeof ( val ) * CHAR_BIT;
@ -63,7 +63,7 @@ void print_bits ( T val, DFHack::Console& out )
val >>= 1; val >>= 1;
} }
strs << endl; strs << endl;
out.print(strs.str().c_str()); out << strs.str();
} }
/* /*

@ -26,6 +26,7 @@ distribution.
#include "Export.h" #include "Export.h"
#include "Hooks.h" #include "Hooks.h"
#include "ColorText.h"
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -61,8 +62,8 @@ namespace DFHack
}; };
struct DFHACK_EXPORT PluginCommand struct DFHACK_EXPORT PluginCommand
{ {
typedef command_result (*command_function)(Core *, std::vector <std::string> &); typedef command_result (*command_function)(color_ostream &out, std::vector <std::string> &);
typedef bool (*command_hotkey_guard)(Core *, df::viewscreen *); typedef bool (*command_hotkey_guard)(df::viewscreen *);
/// create a command with a name, description, function pointer to its code /// create a command with a name, description, function pointer to its code
/// and saying if it needs an interactive terminal /// and saying if it needs an interactive terminal
@ -112,13 +113,13 @@ namespace DFHack
friend class PluginManager; friend class PluginManager;
Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm); Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm);
~Plugin(); ~Plugin();
command_result on_update(); command_result on_update(color_ostream &out);
command_result on_state_change(state_change_event event); command_result on_state_change(color_ostream &out, state_change_event event);
public: public:
bool load(); bool load();
bool unload(); bool unload();
bool reload(); bool reload();
command_result invoke( std::string & command, std::vector <std::string> & parameters, bool interactive ); command_result invoke(color_ostream &out, std::string & command, std::vector <std::string> & parameters, bool interactive );
bool can_invoke_hotkey( std::string & command, df::viewscreen *top ); bool can_invoke_hotkey( std::string & command, df::viewscreen *top );
plugin_state getState () const; plugin_state getState () const;
const PluginCommand& operator[] (std::size_t index) const const PluginCommand& operator[] (std::size_t index) const
@ -141,11 +142,11 @@ namespace DFHack
DFLibrary * plugin_lib; DFLibrary * plugin_lib;
PluginManager * parent; PluginManager * parent;
plugin_state state; plugin_state state;
command_result (*plugin_init)(Core *, std::vector <PluginCommand> &); command_result (*plugin_init)(color_ostream &, std::vector <PluginCommand> &);
command_result (*plugin_status)(Core *, std::string &); command_result (*plugin_status)(color_ostream &, std::string &);
command_result (*plugin_shutdown)(Core *); command_result (*plugin_shutdown)(color_ostream &);
command_result (*plugin_onupdate)(Core *); command_result (*plugin_onupdate)(color_ostream &);
command_result (*plugin_onstatechange)(Core *, state_change_event); command_result (*plugin_onstatechange)(color_ostream &, state_change_event);
}; };
class DFHACK_EXPORT PluginManager class DFHACK_EXPORT PluginManager
{ {
@ -154,15 +155,15 @@ namespace DFHack
friend class Plugin; friend class Plugin;
PluginManager(Core * core); PluginManager(Core * core);
~PluginManager(); ~PluginManager();
void OnUpdate( void ); void OnUpdate(color_ostream &out);
void OnStateChange( state_change_event event ); void OnStateChange(color_ostream &out, state_change_event event);
void registerCommands( Plugin * p ); void registerCommands( Plugin * p );
void unregisterCommands( Plugin * p ); void unregisterCommands( Plugin * p );
// PUBLIC METHODS // PUBLIC METHODS
public: public:
Plugin *getPluginByName (const std::string & name); Plugin *getPluginByName (const std::string & name);
Plugin *getPluginByCommand (const std::string &command); Plugin *getPluginByCommand (const std::string &command);
command_result InvokeCommand( std::string & command, std::vector <std::string> & parameters, bool interactive = true ); command_result InvokeCommand(color_ostream &out, std::string & command, std::vector <std::string> & parameters, bool interactive = true );
bool CanInvokeHotkey(std::string &command, df::viewscreen *top); bool CanInvokeHotkey(std::string &command, df::viewscreen *top);
Plugin* operator[] (std::size_t index) Plugin* operator[] (std::size_t index)
{ {
@ -185,9 +186,9 @@ namespace DFHack
namespace Gui namespace Gui
{ {
// Predefined hotkey guards // Predefined hotkey guards
DFHACK_EXPORT bool default_hotkey(Core *, df::viewscreen *); DFHACK_EXPORT bool default_hotkey(df::viewscreen *);
DFHACK_EXPORT bool dwarfmode_hotkey(Core *, df::viewscreen *); DFHACK_EXPORT bool dwarfmode_hotkey(df::viewscreen *);
DFHACK_EXPORT bool cursor_hotkey(Core *, df::viewscreen *); DFHACK_EXPORT bool cursor_hotkey(df::viewscreen *);
} }
}; };

@ -24,9 +24,6 @@ distribution.
#pragma once #pragma once
#ifndef TILETYPES_H_INCLUDED
#define TILETYPES_H_INCLUDED
#include "Pragma.h" #include "Pragma.h"
#include "Export.h" #include "Export.h"
#include "DataDefs.h" #include "DataDefs.h"
@ -276,4 +273,3 @@ namespace DFHack
DFHACK_EXPORT df::tiletype findRandomVariant(const df::tiletype tile); DFHACK_EXPORT df::tiletype findRandomVariant(const df::tiletype tile);
} }
#endif // TILETYPES_H_INCLUDED

@ -27,6 +27,7 @@ distribution.
#include "Module.h" #include "Module.h"
#include "Virtual.h" #include "Virtual.h"
#include "BitArray.h" #include "BitArray.h"
#include "ColorText.h"
#include <string> #include <string>
#include "DataDefs.h" #include "DataDefs.h"
@ -56,37 +57,37 @@ namespace DFHack
namespace Gui namespace Gui
{ {
// Full-screen item details view // Full-screen item details view
DFHACK_EXPORT bool item_details_hotkey(Core *, df::viewscreen *top); DFHACK_EXPORT bool item_details_hotkey(df::viewscreen *top);
// 'u'nits or 'j'obs full-screen view // 'u'nits or 'j'obs full-screen view
DFHACK_EXPORT bool unitjobs_hotkey(Core *, df::viewscreen *top); DFHACK_EXPORT bool unitjobs_hotkey(df::viewscreen *top);
// A job is selected in a workshop // A job is selected in a workshop
DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool workshop_job_hotkey(df::viewscreen *top);
// Building material selection mode // Building material selection mode
DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool build_selector_hotkey(df::viewscreen *top);
// A unit is selected in the 'v' mode // A unit is selected in the 'v' mode
DFHACK_EXPORT bool view_unit_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool view_unit_hotkey(df::viewscreen *top);
// Above + the inventory page is selected. // Above + the inventory page is selected.
DFHACK_EXPORT bool unit_inventory_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool unit_inventory_hotkey(df::viewscreen *top);
// In workshop_job_hotkey, returns the job // In workshop_job_hotkey, returns the job
DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); DFHACK_EXPORT df::job *getSelectedWorkshopJob(color_ostream &out, bool quiet = false);
// A job is selected in a workshop, or unitjobs // A job is selected in a workshop, or unitjobs
DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool any_job_hotkey(df::viewscreen *top);
DFHACK_EXPORT df::job *getSelectedJob(Core *c, bool quiet = false); DFHACK_EXPORT df::job *getSelectedJob(color_ostream &out, bool quiet = false);
// A unit is selected via 'v', 'k', unitjobs, or // A unit is selected via 'v', 'k', unitjobs, or
// a full-screen item view of a cage or suchlike // a full-screen item view of a cage or suchlike
DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool any_unit_hotkey(df::viewscreen *top);
DFHACK_EXPORT df::unit *getSelectedUnit(Core *c, bool quiet = false); DFHACK_EXPORT df::unit *getSelectedUnit(color_ostream &out, bool quiet = false);
// An item is selected via 'v'->inventory, 'k', 't', or // An item is selected via 'v'->inventory, 'k', 't', or
// a full-screen item view of a container. Note that in the // a full-screen item view of a container. Note that in the
// last case, the highlighted contained item is returned, not // last case, the highlighted contained item is returned, not
// the container itself. // the container itself.
DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool any_item_hotkey(df::viewscreen *top);
DFHACK_EXPORT df::item *getSelectedItem(Core *c, bool quiet = false); DFHACK_EXPORT df::item *getSelectedItem(color_ostream &out, bool quiet = false);
// Show a plain announcement, or a titan-style popup message // Show a plain announcement, or a titan-style popup message
DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true); DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true);

@ -49,7 +49,7 @@ namespace DFHack
DFHACK_EXPORT bool operator== (const df::job_item &a, const df::job_item &b); DFHACK_EXPORT bool operator== (const df::job_item &a, const df::job_item &b);
DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b); DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b);
DFHACK_EXPORT void printJobDetails(Core *c, df::job *job); DFHACK_EXPORT void printJobDetails(color_ostream &out, df::job *job);
DFHACK_EXPORT df::building *getJobHolder(df::job *job); DFHACK_EXPORT df::building *getJobHolder(df::job *job);

@ -272,6 +272,9 @@ extern DFHACK_EXPORT void getPosition(int32_t& x, int32_t& y, int32_t& z);
extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz); extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz);
extern DFHACK_EXPORT df::map_block * getBlockAbs (int32_t x, int32_t y, int32_t z); extern DFHACK_EXPORT df::map_block * getBlockAbs (int32_t x, int32_t y, int32_t z);
inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); }
inline df::map_block * getBlockAbs (df::coord pos) { return getBlockAbs(pos.x, pos.y, pos.z); }
/// copy the whole map block at block coords (see DFTypes.h for the block structure) /// copy the whole map block at block coords (see DFTypes.h for the block structure)
extern DFHACK_EXPORT bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer); extern DFHACK_EXPORT bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer);

@ -0,0 +1,270 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#include "Export.h"
#include <cstddef>
namespace DFHack
{
namespace Windows
{
/*
* DF window stuffs
*/
enum df_color
{
black,
blue,
green,
cyan,
red,
magenta,
brown,
lgray,
dgray,
lblue,
lgreen,
lcyan,
lred,
lmagenta,
yellow,
white
// maybe add transparency?
};
// The tile format DF uses internally
struct df_screentile
{
uint8_t symbol;
uint8_t foreground; ///< df_color
uint8_t background; ///< df_color
uint8_t bright;
};
// our silly painter things and window things follow.
class df_window;
struct df_tilebuf
{
df_screentile * data;
unsigned int width;
unsigned int height;
};
DFHACK_EXPORT df_screentile *getScreenBuffer();
class DFHACK_EXPORT painter
{
friend class df_window;
public:
df_screentile* get(unsigned int x, unsigned int y)
{
if(x >= width || y >= height)
return 0;
return &buffer[x*height + y];
};
bool set(unsigned int x, unsigned int y, df_screentile tile )
{
if(x >= width || y >= height)
return false;
buffer[x*height + y] = tile;
return true;
}
df_color foreground (df_color change = (df_color) -1)
{
if(change != -1)
current_foreground = change;
return current_foreground;
}
df_color background (df_color change = (df_color) -1)
{
if(change != -1)
current_background = change;
return current_background;
}
void bright (bool change)
{
current_bright = change;
}
bool bright ()
{
return current_bright;
}
void printStr(std::string & str, bool wrap = false)
{
for ( auto iter = str.begin(); iter != str.end(); iter++)
{
auto elem = *iter;
if(cursor_y >= height)
break;
if(wrap)
{
if(cursor_x >= width)
cursor_x = wrap_column;
}
df_screentile & tile = buffer[cursor_x * height + cursor_y];
tile.symbol = elem;
tile.foreground = current_foreground;
tile.background = current_background;
tile.bright = current_bright;
cursor_x++;
}
}
void set_wrap (int new_column)
{
wrap_column = new_column;
}
void gotoxy(unsigned int x, unsigned int y)
{
cursor_x = x;
cursor_y = y;
}
void reset()
{
cursor_x = 0;
cursor_y = 0;
current_background = black;
current_foreground = white;
current_bright = false;
wrap_column = 0;
}
private:
painter (df_window * orig, df_screentile * buf, unsigned int width, unsigned int height)
{
origin = orig;
this->width = width;
this->height = height;
this->buffer = buf;
reset();
}
df_window* origin;
unsigned int width;
unsigned int height;
df_screentile* buffer;
// current paint cursor position
int cursor_x;
int cursor_y;
int wrap_column;
// current foreground color
df_color current_foreground;
// current background color
df_color current_background;
// make bright?
bool current_bright;
};
class DFHACK_EXPORT df_window
{
friend class painter;
public:
df_window(int x, int y, unsigned int width, unsigned int height);
virtual ~df_window();
virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_) = 0;
virtual void paint () = 0;
virtual painter * lock();
bool unlock (painter * painter);
virtual bool addChild(df_window *);
virtual df_tilebuf getBuffer() = 0;
public:
df_screentile* buffer;
unsigned int width;
unsigned int height;
protected:
df_window * parent;
std::vector <df_window *> children;
int left;
int top;
// FIXME: FAKE
bool locked;
painter * current_painter;
};
class DFHACK_EXPORT top_level_window : public df_window
{
public:
top_level_window();
virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_);
virtual void paint ();
virtual painter * lock();
virtual df_tilebuf getBuffer();
};
class DFHACK_EXPORT buffered_window : public df_window
{
public:
buffered_window(int x, int y, unsigned int width, unsigned int height):df_window(x,y,width, height)
{
buffer = new df_screentile[width*height];
};
virtual ~buffered_window()
{
delete buffer;
}
virtual void blit_to_parent ()
{
df_tilebuf par = parent->getBuffer();
for(int xi = 0; xi < width; xi++)
{
for(int yi = 0; yi < height; yi++)
{
int parx = left + xi;
int pary = top + yi;
if(pary >= par.height) continue;
if(parx >= par.width) continue;
par.data[parx * par.height + pary] = buffer[xi * height + yi];
}
}
}
virtual df_tilebuf getBuffer()
{
df_tilebuf buf;
buf.data = buffer;
buf.width = width;
buf.height = height;
return buf;
};
};
class DFHACK_EXPORT dfhack_dummy : public buffered_window
{
public:
dfhack_dummy(int x, int y):buffered_window(x,y,6,1){};
virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_)
{
top = top_;
left = left_;
return true;
}
virtual void paint ()
{
painter * p = lock();
p->bright(true);
p->background(black);
p->foreground(white);
std::string dfhack = "DFHack";
p->printStr(dfhack);
blit_to_parent();
}
};
}
}

@ -58,7 +58,7 @@ const t_exclusionType limitExclusion = 4; // used to store limit as an entry in
*/ */
// print the exclusion list, with the material index also translated into its token (for organics) - for debug really // print the exclusion list, with the material index also translated into its token (for organics) - for debug really
DFHACK_EXPORT void debug_print(Core &); DFHACK_EXPORT void debug_print(color_ostream &out);
// remove this material from the exclusion list if it is in it // remove this material from the exclusion list if it is in it
DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex); DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex);

@ -74,18 +74,14 @@ bool Buildings::Read (const uint32_t index, t_building & building)
bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes) bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
{ {
Core & c = Core::getInstance();
vector <building_def *> & bld_def = world->raws.buildings.all; vector <building_def *> & bld_def = world->raws.buildings.all;
uint32_t size = bld_def.size(); uint32_t size = bld_def.size();
btypes.clear(); btypes.clear();
c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def);
for (auto iter = bld_def.begin(); iter != bld_def.end();iter++) for (auto iter = bld_def.begin(); iter != bld_def.end();iter++)
{ {
building_def * temp = *iter; building_def * temp = *iter;
btypes[temp->id] = temp->code; btypes[temp->id] = temp->code;
c.con.print("%d : %s\n",temp->id, temp->code.c_str());
} }
return true; return true;
} }

@ -45,6 +45,7 @@ using namespace DFHack;
#include "df/world.h" #include "df/world.h"
#include "df/global_objects.h" #include "df/global_objects.h"
#include "df/viewscreen_dwarfmodest.h" #include "df/viewscreen_dwarfmodest.h"
#include "df/viewscreen_dungeonmodest.h"
#include "df/viewscreen_joblistst.h" #include "df/viewscreen_joblistst.h"
#include "df/viewscreen_unitlistst.h" #include "df/viewscreen_unitlistst.h"
#include "df/viewscreen_itemst.h" #include "df/viewscreen_itemst.h"
@ -69,37 +70,41 @@ using df::global::gps;
// Predefined common guard functions // Predefined common guard functions
bool Gui::default_hotkey(Core *, df::viewscreen *top) bool Gui::default_hotkey(df::viewscreen *top)
{ {
// Default hotkey guard function // Default hotkey guard function
for (;top ;top = top->parent) for (;top ;top = top->parent)
{
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(top)) if (strict_virtual_cast<df::viewscreen_dwarfmodest>(top))
return true; return true;
if (strict_virtual_cast<df::viewscreen_dungeonmodest>(top))
return true;
}
return false; return false;
} }
bool Gui::dwarfmode_hotkey(Core *, df::viewscreen *top) bool Gui::dwarfmode_hotkey(df::viewscreen *top)
{ {
// Require the main dwarf mode screen // Require the main dwarf mode screen
return !!strict_virtual_cast<df::viewscreen_dwarfmodest>(top); return !!strict_virtual_cast<df::viewscreen_dwarfmodest>(top);
} }
bool Gui::unitjobs_hotkey(Core *, df::viewscreen *top) bool Gui::unitjobs_hotkey(df::viewscreen *top)
{ {
// Require the unit or jobs list // Require the unit or jobs list
return !!strict_virtual_cast<df::viewscreen_joblistst>(top) || return !!strict_virtual_cast<df::viewscreen_joblistst>(top) ||
!!strict_virtual_cast<df::viewscreen_unitlistst>(top); !!strict_virtual_cast<df::viewscreen_unitlistst>(top);
} }
bool Gui::item_details_hotkey(Core *, df::viewscreen *top) bool Gui::item_details_hotkey(df::viewscreen *top)
{ {
// Require the main dwarf mode screen // Require the main dwarf mode screen
return !!strict_virtual_cast<df::viewscreen_itemst>(top); return !!strict_virtual_cast<df::viewscreen_itemst>(top);
} }
bool Gui::cursor_hotkey(Core *c, df::viewscreen *top) bool Gui::cursor_hotkey(df::viewscreen *top)
{ {
if (!dwarfmode_hotkey(c, top)) if (!dwarfmode_hotkey(top))
return false; return false;
// Also require the cursor. // Also require the cursor.
@ -109,7 +114,7 @@ bool Gui::cursor_hotkey(Core *c, df::viewscreen *top)
return true; return true;
} }
bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top) bool Gui::workshop_job_hotkey(df::viewscreen *top)
{ {
using namespace ui_sidebar_mode; using namespace ui_sidebar_mode;
using df::global::ui; using df::global::ui;
@ -117,7 +122,7 @@ bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top)
using df::global::ui_workshop_in_add; using df::global::ui_workshop_in_add;
using df::global::ui_workshop_job_cursor; using df::global::ui_workshop_job_cursor;
if (!dwarfmode_hotkey(c,top)) if (!dwarfmode_hotkey(top))
return false; return false;
switch (ui->main.mode) { switch (ui->main.mode) {
@ -147,13 +152,13 @@ bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top)
} }
} }
bool Gui::build_selector_hotkey(Core *c, df::viewscreen *top) bool Gui::build_selector_hotkey(df::viewscreen *top)
{ {
using namespace ui_sidebar_mode; using namespace ui_sidebar_mode;
using df::global::ui; using df::global::ui;
using df::global::ui_build_selector; using df::global::ui_build_selector;
if (!dwarfmode_hotkey(c,top)) if (!dwarfmode_hotkey(top))
return false; return false;
switch (ui->main.mode) { switch (ui->main.mode) {
@ -175,13 +180,13 @@ bool Gui::build_selector_hotkey(Core *c, df::viewscreen *top)
} }
} }
bool Gui::view_unit_hotkey(Core *c, df::viewscreen *top) bool Gui::view_unit_hotkey(df::viewscreen *top)
{ {
using df::global::ui; using df::global::ui;
using df::global::world; using df::global::world;
using df::global::ui_selected_unit; using df::global::ui_selected_unit;
if (!dwarfmode_hotkey(c,top)) if (!dwarfmode_hotkey(top))
return false; return false;
if (ui->main.mode != ui_sidebar_mode::ViewUnits) if (ui->main.mode != ui_sidebar_mode::ViewUnits)
return false; return false;
@ -191,11 +196,11 @@ bool Gui::view_unit_hotkey(Core *c, df::viewscreen *top)
return vector_get(world->units.other[0], *ui_selected_unit) != NULL; return vector_get(world->units.other[0], *ui_selected_unit) != NULL;
} }
bool Gui::unit_inventory_hotkey(Core *c, df::viewscreen *top) bool Gui::unit_inventory_hotkey(df::viewscreen *top)
{ {
using df::global::ui_unit_view_mode; using df::global::ui_unit_view_mode;
if (!view_unit_hotkey(c,top)) if (!view_unit_hotkey(top))
return false; return false;
if (!ui_unit_view_mode) if (!ui_unit_view_mode)
return false; return false;
@ -203,14 +208,14 @@ bool Gui::unit_inventory_hotkey(Core *c, df::viewscreen *top)
return ui_unit_view_mode->value == df::ui_unit_view_mode::Inventory; return ui_unit_view_mode->value == df::ui_unit_view_mode::Inventory;
} }
df::job *Gui::getSelectedWorkshopJob(Core *c, bool quiet) df::job *Gui::getSelectedWorkshopJob(color_ostream &out, bool quiet)
{ {
using df::global::world; using df::global::world;
using df::global::ui_workshop_job_cursor; using df::global::ui_workshop_job_cursor;
if (!workshop_job_hotkey(c, c->getTopViewscreen())) { if (!workshop_job_hotkey(Core::getTopViewscreen())) {
if (!quiet) if (!quiet)
c->con.printerr("Not in a workshop, or no job is highlighted.\n"); out.printerr("Not in a workshop, or no job is highlighted.\n");
return NULL; return NULL;
} }
@ -219,14 +224,14 @@ df::job *Gui::getSelectedWorkshopJob(Core *c, bool quiet)
if (idx < 0 || idx >= selected->jobs.size()) if (idx < 0 || idx >= selected->jobs.size())
{ {
c->con.printerr("Invalid job cursor index: %d\n", idx); out.printerr("Invalid job cursor index: %d\n", idx);
return NULL; return NULL;
} }
return selected->jobs[idx]; return selected->jobs[idx];
} }
bool Gui::any_job_hotkey(Core *c, df::viewscreen *top) bool Gui::any_job_hotkey(df::viewscreen *top)
{ {
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_joblistst, top)) if (VIRTUAL_CAST_VAR(screen, df::viewscreen_joblistst, top))
return vector_get(screen->jobs, screen->cursor_pos) != NULL; return vector_get(screen->jobs, screen->cursor_pos) != NULL;
@ -234,19 +239,19 @@ bool Gui::any_job_hotkey(Core *c, df::viewscreen *top)
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitlistst, top)) if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitlistst, top))
return vector_get(screen->jobs[screen->page], screen->cursor_pos[screen->page]) != NULL; return vector_get(screen->jobs[screen->page], screen->cursor_pos[screen->page]) != NULL;
return workshop_job_hotkey(c,top); return workshop_job_hotkey(top);
} }
df::job *Gui::getSelectedJob(Core *c, bool quiet) df::job *Gui::getSelectedJob(color_ostream &out, bool quiet)
{ {
df::viewscreen *top = c->getTopViewscreen(); df::viewscreen *top = Core::getTopViewscreen();
if (VIRTUAL_CAST_VAR(joblist, df::viewscreen_joblistst, top)) if (VIRTUAL_CAST_VAR(joblist, df::viewscreen_joblistst, top))
{ {
df::job *job = vector_get(joblist->jobs, joblist->cursor_pos); df::job *job = vector_get(joblist->jobs, joblist->cursor_pos);
if (!job && !quiet) if (!job && !quiet)
c->con.printerr("Selected unit has no job\n"); out.printerr("Selected unit has no job\n");
return job; return job;
} }
@ -256,15 +261,15 @@ df::job *Gui::getSelectedJob(Core *c, bool quiet)
df::job *job = vector_get(unitlist->jobs[page], unitlist->cursor_pos[page]); df::job *job = vector_get(unitlist->jobs[page], unitlist->cursor_pos[page]);
if (!job && !quiet) if (!job && !quiet)
c->con.printerr("Selected unit has no job\n"); out.printerr("Selected unit has no job\n");
return job; return job;
} }
else else
return getSelectedWorkshopJob(c, quiet); return getSelectedWorkshopJob(out, quiet);
} }
static df::unit *getAnyUnit(Core *c, df::viewscreen *top) static df::unit *getAnyUnit(df::viewscreen *top)
{ {
using namespace ui_sidebar_mode; using namespace ui_sidebar_mode;
using df::global::ui; using df::global::ui;
@ -285,7 +290,7 @@ static df::unit *getAnyUnit(Core *c, df::viewscreen *top)
return ref ? ref->getUnit() : NULL; return ref ? ref->getUnit() : NULL;
} }
if (!Gui::dwarfmode_hotkey(c,top)) if (!Gui::dwarfmode_hotkey(top))
return NULL; return NULL;
switch (ui->main.mode) { switch (ui->main.mode) {
@ -312,22 +317,22 @@ static df::unit *getAnyUnit(Core *c, df::viewscreen *top)
} }
} }
bool Gui::any_unit_hotkey(Core *c, df::viewscreen *top) bool Gui::any_unit_hotkey(df::viewscreen *top)
{ {
return getAnyUnit(c, top) != NULL; return getAnyUnit(top) != NULL;
} }
df::unit *Gui::getSelectedUnit(Core *c, bool quiet) df::unit *Gui::getSelectedUnit(color_ostream &out, bool quiet)
{ {
df::unit *unit = getAnyUnit(c, c->getTopViewscreen()); df::unit *unit = getAnyUnit(Core::getTopViewscreen());
if (!unit && !quiet) if (!unit && !quiet)
c->con.printerr("No unit is selected in the UI.\n"); out.printerr("No unit is selected in the UI.\n");
return unit; return unit;
} }
static df::item *getAnyItem(Core *c, df::viewscreen *top) static df::item *getAnyItem(df::viewscreen *top)
{ {
using namespace ui_sidebar_mode; using namespace ui_sidebar_mode;
using df::global::ui; using df::global::ui;
@ -344,7 +349,7 @@ static df::item *getAnyItem(Core *c, df::viewscreen *top)
return ref ? ref->getItem() : NULL; return ref ? ref->getItem() : NULL;
} }
if (!Gui::dwarfmode_hotkey(c,top)) if (!Gui::dwarfmode_hotkey(top))
return NULL; return NULL;
switch (ui->main.mode) { switch (ui->main.mode) {
@ -387,17 +392,17 @@ static df::item *getAnyItem(Core *c, df::viewscreen *top)
} }
} }
bool Gui::any_item_hotkey(Core *c, df::viewscreen *top) bool Gui::any_item_hotkey(df::viewscreen *top)
{ {
return getAnyItem(c, top) != NULL; return getAnyItem(top) != NULL;
} }
df::item *Gui::getSelectedItem(Core *c, bool quiet) df::item *Gui::getSelectedItem(color_ostream &out, bool quiet)
{ {
df::item *item = getAnyItem(c, c->getTopViewscreen()); df::item *item = getAnyItem(Core::getTopViewscreen());
if (!item && !quiet) if (!item && !quiet)
c->con.printerr("No item is selected in the UI.\n"); out.printerr("No item is selected in the UI.\n");
return item; return item;
} }
@ -489,7 +494,6 @@ bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z)
bool Gui::setViewCoords (const int32_t x, const int32_t y, const int32_t z) bool Gui::setViewCoords (const int32_t x, const int32_t y, const int32_t z)
{ {
auto cursor = df::global::cursor;
(*df::global::window_x) = x; (*df::global::window_x) = x;
(*df::global::window_y) = y; (*df::global::window_y) = y;
(*df::global::window_z) = z; (*df::global::window_z) = z;

@ -382,7 +382,7 @@ bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat)
if ((item_ok1.whole & ~item_mask1.whole) || if ((item_ok1.whole & ~item_mask1.whole) ||
(item_ok2.whole & ~item_mask2.whole) || (item_ok2.whole & ~item_mask2.whole) ||
(item_ok3.whole & ~item_mask3.whole)) (item_ok3.whole & ~item_mask3.whole))
Core::getInstance().con.printerr("ItemTypeInfo.matches inconsistent\n"); Core::printerr("ItemTypeInfo.matches inconsistent\n");
#undef OK #undef OK
#undef RQ #undef RQ

@ -139,48 +139,48 @@ bool DFHack::operator== (const df::job &a, const df::job &b)
return true; return true;
} }
static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) static void print_job_item_details(color_ostream &out, df::job *job, unsigned idx, df::job_item *item)
{ {
ItemTypeInfo info(item); ItemTypeInfo info(item);
c->con << " Input Item " << (idx+1) << ": " << info.toString(); out << " Input Item " << (idx+1) << ": " << info.toString();
if (item->quantity != 1) if (item->quantity != 1)
c->con << "; quantity=" << item->quantity; out << "; quantity=" << item->quantity;
if (item->min_dimension >= 0) if (item->min_dimension >= 0)
c->con << "; min_dimension=" << item->min_dimension; out << "; min_dimension=" << item->min_dimension;
c->con << endl; out << endl;
MaterialInfo mat(item); MaterialInfo mat(item);
if (mat.isValid() || item->metal_ore >= 0) { if (mat.isValid() || item->metal_ore >= 0) {
c->con << " material: " << mat.toString(); out << " material: " << mat.toString();
if (item->metal_ore >= 0) if (item->metal_ore >= 0)
c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); out << "; ore of " << MaterialInfo(0,item->metal_ore).toString();
c->con << endl; out << endl;
} }
if (item->flags1.whole) if (item->flags1.whole)
c->con << " flags1: " << bitfieldToString(item->flags1) << endl; out << " flags1: " << bitfieldToString(item->flags1) << endl;
if (item->flags2.whole) if (item->flags2.whole)
c->con << " flags2: " << bitfieldToString(item->flags2) << endl; out << " flags2: " << bitfieldToString(item->flags2) << endl;
if (item->flags3.whole) if (item->flags3.whole)
c->con << " flags3: " << bitfieldToString(item->flags3) << endl; out << " flags3: " << bitfieldToString(item->flags3) << endl;
if (!item->reaction_class.empty()) if (!item->reaction_class.empty())
c->con << " reaction class: " << item->reaction_class << endl; out << " reaction class: " << item->reaction_class << endl;
if (!item->has_material_reaction_product.empty()) if (!item->has_material_reaction_product.empty())
c->con << " reaction product: " << item->has_material_reaction_product << endl; out << " reaction product: " << item->has_material_reaction_product << endl;
if (item->has_tool_use >= 0) if (item->has_tool_use >= 0)
c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; out << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl;
} }
void DFHack::printJobDetails(Core *c, df::job *job) void DFHack::printJobDetails(color_ostream &out, df::job *job)
{ {
c->con.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY); out.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY);
c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); out << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type);
if (job->flags.whole) if (job->flags.whole)
c->con << " (" << bitfieldToString(job->flags) << ")"; out << " (" << bitfieldToString(job->flags) << ")";
c->con << endl; out << endl;
c->con.reset_color(); out.reset_color();
df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); df::item_type itype = ENUM_ATTR(job_type, item, job->job_type);
@ -190,28 +190,28 @@ void DFHack::printJobDetails(Core *c, df::job *job)
if (mat.isValid() || job->material_category.whole) if (mat.isValid() || job->material_category.whole)
{ {
c->con << " material: " << mat.toString(); out << " material: " << mat.toString();
if (job->material_category.whole) if (job->material_category.whole)
c->con << " (" << bitfieldToString(job->material_category) << ")"; out << " (" << bitfieldToString(job->material_category) << ")";
c->con << endl; out << endl;
} }
if (job->item_subtype >= 0 || job->item_category.whole) if (job->item_subtype >= 0 || job->item_category.whole)
{ {
ItemTypeInfo iinfo(itype, job->item_subtype); ItemTypeInfo iinfo(itype, job->item_subtype);
c->con << " item: " << iinfo.toString() out << " item: " << iinfo.toString()
<< " (" << bitfieldToString(job->item_category) << ")" << endl; << " (" << bitfieldToString(job->item_category) << ")" << endl;
} }
if (job->hist_figure_id >= 0) if (job->hist_figure_id >= 0)
c->con << " figure: " << job->hist_figure_id << endl; out << " figure: " << job->hist_figure_id << endl;
if (!job->reaction_name.empty()) if (!job->reaction_name.empty())
c->con << " reaction: " << job->reaction_name << endl; out << " reaction: " << job->reaction_name << endl;
for (size_t i = 0; i < job->job_items.size(); i++) for (size_t i = 0; i < job->job_items.size(); i++)
print_job_item_details(c, job, i, job->job_items[i]); print_job_item_details(out, job, i, job->job_items[i]);
} }
df::building *DFHack::getJobHolder(df::job *job) df::building *DFHack::getJobHolder(df::job *job)

@ -200,7 +200,6 @@ bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit)
} }
return false; return false;
} }
/*
/* /*
* Block flags * Block flags
*/ */

@ -0,0 +1,118 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Export.h"
#include "Module.h"
#include "Virtual.h"
#include "BitArray.h"
#include <string>
#include "DataDefs.h"
#include "df/init.h"
#include "df/ui.h"
#include <df/graphic.h>
#include <llex.h>
#include "modules/Windows.h"
using namespace DFHack;
Windows::df_screentile *Windows::getScreenBuffer()
{
return (df_screentile *) df::global::gps->screen;
}
Windows::df_window::df_window(int x, int y, unsigned int width, unsigned int height)
:buffer(0), parent(0), left(x), top(y), width(width), height(height), current_painter(NULL)
{
buffer = 0;
};
Windows::df_window::~df_window()
{
for(auto iter = children.begin();iter != children.end();iter++)
{
delete *iter;
}
children.clear();
};
Windows::painter * Windows::df_window::lock()
{
locked = true;
current_painter = new Windows::painter(this,buffer,width, height);
return current_painter;
};
bool Windows::df_window::addChild( df_window * child)
{
children.push_back(child);
child->parent = this;
return true;
}
bool Windows::df_window::unlock (painter * painter)
{
if(current_painter == painter)
{
delete current_painter;
current_painter = 0;
locked = false;
return true;
}
return false;
}
Windows::top_level_window::top_level_window(): df_window(0,0,df::global::gps->dimx,df::global::gps->dimy)
{
buffer = 0;
}
bool Windows::top_level_window::move (int left_, int top_, unsigned int width_, unsigned int height_)
{
width = width_;
height = height_;
// what if we are painting already? Is that possible?
return true;
};
Windows::painter * Windows::top_level_window::lock()
{
buffer = getScreenBuffer();
return df_window::lock();
}
void Windows::top_level_window::paint ()
{
for(auto iter = children.begin();iter != children.end();iter++)
{
(*iter)->paint();
}
};
Windows::df_tilebuf Windows::top_level_window::getBuffer()
{
df_tilebuf buf;
buf.data = getScreenBuffer();
buf.height = df::global::gps->dimy;
buf.width = df::global::gps->dimx;
return buf;
}

@ -28,12 +28,12 @@ using namespace df::enums;
using df::global::world; using df::global::world;
using df::global::ui; using df::global::ui;
void Kitchen::debug_print(Core &core) void Kitchen::debug_print(color_ostream &out)
{ {
core.con.print("Kitchen Exclusions\n"); out.print("Kitchen Exclusions\n");
for(std::size_t i = 0; i < size(); ++i) for(std::size_t i = 0; i < size(); ++i)
{ {
core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", out.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n",
i, i,
ui->kitchen.item_types[i], ui->kitchen.item_types[i],
ui->kitchen.item_subtypes[i], ui->kitchen.item_subtypes[i],
@ -43,7 +43,7 @@ void Kitchen::debug_print(Core &core)
(ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a" (ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a"
); );
} }
core.con.print("\n"); out.print("\n");
} }
void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex) void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex)

@ -0,0 +1,2 @@
*.pb.cc
*.pb.h

@ -0,0 +1,59 @@
package dfproto;
option optimize_for = LITE_RUNTIME;
message CoreTextFragment {
required string text = 1;
enum Color {
COLOR_BLACK = 0;
COLOR_BLUE = 1;
COLOR_GREEN = 2;
COLOR_CYAN = 3;
COLOR_RED = 4;
COLOR_MAGENTA = 5;
COLOR_BROWN = 6;
COLOR_GREY = 7;
COLOR_DARKGREY = 8;
COLOR_LIGHTBLUE = 9;
COLOR_LIGHTGREEN = 10;
COLOR_LIGHTCYAN = 11;
COLOR_LIGHTRED = 12;
COLOR_LIGHTMAGENTA = 13;
COLOR_YELLOW = 14;
COLOR_WHITE = 15;
};
optional Color color = 2;
}
message CoreTextNotification {
repeated CoreTextFragment fragments = 1;
}
message CoreErrorNotification {
enum ErrorCode {
CR_WOULD_BREAK = -2;
CR_NOT_IMPLEMENTED = -1;
CR_FAILURE = 0;
CR_OK = 1;
CR_WRONG_USAGE = 2;
};
required ErrorCode code = 1;
}
message CoreBindRequest {
required string method = 1;
optional string plugin = 2;
optional int32 min_version = 3;
}
message CoreBindReply {
required int32 assigned_id = 1;
required int32 version = 2;
}
message CoreRunStringRequest {
required string command = 1;
repeated string arguments = 2;
}

@ -1 +1 @@
Subproject commit cd7c4b1c8f6a73a9ed7cdf04b65ee2a75910202c Subproject commit 24e809abe07eb139c9f53c358ed3fbd3d8075410

@ -79,6 +79,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(follow follow.cpp) DFHACK_PLUGIN(follow follow.cpp)
DFHACK_PLUGIN(changevein changevein.cpp) DFHACK_PLUGIN(changevein changevein.cpp)
DFHACK_PLUGIN(advtools advtools.cpp) DFHACK_PLUGIN(advtools advtools.cpp)
DFHACK_PLUGIN(tweak tweak.cpp)
#DFHACK_PLUGIN(versionosd versionosd.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp)
endif() endif()

@ -6,6 +6,7 @@
#include "modules/World.h" #include "modules/World.h"
#include "modules/Translation.h" #include "modules/Translation.h"
#include "modules/Materials.h" #include "modules/Materials.h"
#include "modules/Maps.h"
#include "modules/Items.h" #include "modules/Items.h"
#include "DataDefs.h" #include "DataDefs.h"
@ -19,6 +20,8 @@
#include "df/historical_figure.h" #include "df/historical_figure.h"
#include "df/general_ref_is_nemesisst.h" #include "df/general_ref_is_nemesisst.h"
#include "df/general_ref_contains_itemst.h" #include "df/general_ref_contains_itemst.h"
#include "df/general_ref_contained_in_itemst.h"
#include "df/general_ref_unit_holderst.h"
#include "df/general_ref_building_civzone_assignedst.h" #include "df/general_ref_building_civzone_assignedst.h"
#include "df/material.h" #include "df/material.h"
#include "df/craft_material_class.h" #include "df/craft_material_class.h"
@ -43,14 +46,14 @@ using namespace DFHack::Translation;
* PLUGIN INTERFACE * * PLUGIN INTERFACE *
*********************/ *********************/
static bool bodyswap_hotkey(Core *c, df::viewscreen *top); static bool bodyswap_hotkey(df::viewscreen *top);
command_result adv_bodyswap (Core * c, std::vector <std::string> & parameters); command_result adv_bodyswap (color_ostream &out, std::vector <std::string> & parameters);
command_result adv_tools (Core * c, std::vector <std::string> & parameters); command_result adv_tools (color_ostream &out, std::vector <std::string> & parameters);
DFHACK_PLUGIN("advtools"); DFHACK_PLUGIN("advtools");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
@ -88,16 +91,16 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap); df::nemesis_record *getPlayerNemesis(color_ostream &out, bool restore_swap);
static bool in_transient_swap = false; static bool in_transient_swap = false;
DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_LOADED: case SC_GAME_LOADED:
@ -110,12 +113,12 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
// Revert transient swaps before trouble happens // Revert transient swaps before trouble happens
if (in_transient_swap) if (in_transient_swap)
{ {
auto screen = c->getTopViewscreen(); auto screen = Core::getTopViewscreen();
bool revert = false; bool revert = false;
if (strict_virtual_cast<df::viewscreen_dungeonmodest>(screen)) if (strict_virtual_cast<df::viewscreen_dungeonmodest>(screen))
@ -140,7 +143,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
if (revert) if (revert)
{ {
getPlayerNemesis(c, true); getPlayerNemesis(out, true);
in_transient_swap = false; in_transient_swap = false;
} }
} }
@ -152,15 +155,15 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
* UTILITY FUNCTIONS * * UTILITY FUNCTIONS *
*********************/ *********************/
static bool bodyswap_hotkey(Core *c, df::viewscreen *top) static bool bodyswap_hotkey(df::viewscreen *top)
{ {
return !!virtual_cast<df::viewscreen_dungeonmodest>(top) || return !!virtual_cast<df::viewscreen_dungeonmodest>(top) ||
!!virtual_cast<df::viewscreen_dungeon_monsterstatusst>(top); !!virtual_cast<df::viewscreen_dungeon_monsterstatusst>(top);
} }
df::unit *getCurUnit(Core *c) df::unit *getCurUnit()
{ {
auto top = c->getTopViewscreen(); auto top = Core::getTopViewscreen();
if (VIRTUAL_CAST_VAR(ms, df::viewscreen_dungeon_monsterstatusst, top)) if (VIRTUAL_CAST_VAR(ms, df::viewscreen_dungeon_monsterstatusst, top))
return ms->unit; return ms->unit;
@ -183,11 +186,11 @@ df::nemesis_record *getNemesis(df::unit *unit)
return NULL; return NULL;
} }
bool bodySwap(Core *c, df::unit *player) bool bodySwap(color_ostream &out, df::unit *player)
{ {
if (!player) if (!player)
{ {
c->con.printerr("Unit to swap is NULL\n"); out.printerr("Unit to swap is NULL\n");
return false; return false;
} }
@ -196,7 +199,7 @@ bool bodySwap(Core *c, df::unit *player)
int idx = linear_index(vec, player); int idx = linear_index(vec, player);
if (idx < 0) if (idx < 0)
{ {
c->con.printerr("Unit to swap not found: %d\n", player->id); out.printerr("Unit to swap not found: %d\n", player->id);
return false; return false;
} }
@ -206,12 +209,12 @@ bool bodySwap(Core *c, df::unit *player)
return true; return true;
} }
df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap) df::nemesis_record *getPlayerNemesis(color_ostream &out, bool restore_swap)
{ {
auto real_nemesis = vector_get(world->nemesis.all, ui_advmode->player_id); auto real_nemesis = vector_get(world->nemesis.all, ui_advmode->player_id);
if (!real_nemesis || !real_nemesis->unit) if (!real_nemesis || !real_nemesis->unit)
{ {
c->con.printerr("Invalid player nemesis id: %d\n", ui_advmode->player_id); out.printerr("Invalid player nemesis id: %d\n", ui_advmode->player_id);
return NULL; return NULL;
} }
@ -222,11 +225,11 @@ df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap)
if (ctl_nemesis != real_nemesis) if (ctl_nemesis != real_nemesis)
{ {
if (!bodySwap(c, real_nemesis->unit)) if (!bodySwap(out, real_nemesis->unit))
return NULL; return NULL;
auto name = TranslateName(&real_nemesis->unit->name, false); auto name = TranslateName(&real_nemesis->unit->name, false);
c->con.print("Returned into the body of %s.\n", name.c_str()); out.print("Returned into the body of %s.\n", name.c_str());
} }
real_nemesis->unit->relations.group_leader_id = -1; real_nemesis->unit->relations.group_leader_id = -1;
@ -315,9 +318,9 @@ void sortCompanionNemesis(std::vector<nemesis_record*> *list, int player_id = -1
list->swap(output); list->swap(output);
} }
void listCompanions(Core *c, std::vector<nemesis_record*> *list, bool units = true) void listCompanions(color_ostream &out, std::vector<nemesis_record*> *list, bool units = true)
{ {
nemesis_record *player = getPlayerNemesis(c, false); nemesis_record *player = getPlayerNemesis(out, false);
if (!player) if (!player)
return; return;
@ -421,7 +424,7 @@ bool isWeaponArmor(df::item *item)
} }
} }
int containsMetalItems(df::item *item, bool all, bool non_trader) int containsMetalItems(df::item *item, bool all, bool non_trader, bool rec = false)
{ {
int cnt = 0; int cnt = 0;
@ -429,13 +432,19 @@ int containsMetalItems(df::item *item, bool all, bool non_trader)
for (size_t i = 0; i < refs.size(); i++) for (size_t i = 0; i < refs.size(); i++)
{ {
auto ref = refs[i]; auto ref = refs[i];
if (!strict_virtual_cast<df::general_ref_contains_itemst>(ref))
continue;
if (strict_virtual_cast<df::general_ref_unit_holderst>(ref))
return 0;
if (!rec && strict_virtual_cast<df::general_ref_contained_in_itemst>(ref))
return 0;
if (strict_virtual_cast<df::general_ref_contains_itemst>(ref))
{
df::item *child = ref->getItem(); df::item *child = ref->getItem();
if (!child) continue; if (!child) continue;
cnt += containsMetalItems(child, all, non_trader); cnt += containsMetalItems(child, all, non_trader, true);
}
} }
if (!non_trader && !isShopItem(item)) if (!non_trader && !isShopItem(item))
@ -476,23 +485,23 @@ void joinCounts(std::map<df::coord, int> &counts)
* FORMATTING * * FORMATTING *
*********************/ *********************/
static void printCompanionHeader(Core *c, size_t i, df::unit *unit) static void printCompanionHeader(color_ostream &out, size_t i, df::unit *unit)
{ {
c->con.color(Console::COLOR_GREY); out.color(Console::COLOR_GREY);
if (i < 28) if (i < 28)
c->con << char('a'+i); out << char('a'+i);
else else
c->con << i; out << i;
c->con << ": " << getUnitNameProfession(unit); out << ": " << getUnitNameProfession(unit);
if (unit->flags1.bits.dead) if (unit->flags1.bits.dead)
c->con << " (DEAD)"; out << " (DEAD)";
if (unit->flags3.bits.ghostly) if (unit->flags3.bits.ghostly)
c->con << " (GHOST)"; out << " (GHOST)";
c->con << endl; out << endl;
c->con.reset_color(); out.reset_color();
} }
static size_t formatSize(std::vector<std::string> *out, const std::map<std::string, int> in, size_t *cnt) static size_t formatSize(std::vector<std::string> *out, const std::map<std::string, int> in, size_t *cnt)
@ -551,7 +560,7 @@ static std::string formatDirection(df::coord delta)
return stl_sprintf("%d away %s %+d", dist, dir.c_str(), delta.z); return stl_sprintf("%d away %s %+d", dist, dir.c_str(), delta.z);
} }
static void printEquipped(Core *c, df::unit *unit, bool all) static void printEquipped(color_ostream &out, df::unit *unit, bool all)
{ {
std::vector<inv_item> items; std::vector<inv_item> items;
listUnitInventory(&items, unit); listUnitInventory(&items, unit);
@ -627,10 +636,10 @@ static void printEquipped(Core *c, df::unit *unit, bool all)
for (int j = 0; j < 4; j++) for (int j = 0; j < 4; j++)
{ {
size_t sz = std::max(sizes[j], size_t(18)); size_t sz = std::max(sizes[j], size_t(18));
c->con << "| " << std::left << std::setw(sz) << vector_get(cols[j],i) << " "; out << "| " << std::left << std::setw(sz) << vector_get(cols[j],i) << " ";
} }
c->con << "|" << std::endl; out << "|" << std::endl;
} }
} }
@ -638,7 +647,7 @@ static void printEquipped(Core *c, df::unit *unit, bool all)
* COMMANDS * * COMMANDS *
*********************/ *********************/
command_result adv_bodyswap (Core * c, std::vector <std::string> & parameters) command_result adv_bodyswap (color_ostream &out, std::vector <std::string> & parameters)
{ {
// HOTKEY COMMAND; CORE IS SUSPENDED // HOTKEY COMMAND; CORE IS SUSPENDED
bool force = false; bool force = false;
@ -660,19 +669,19 @@ command_result adv_bodyswap (Core * c, std::vector <std::string> & parameters)
} }
// Get the real player; undo previous transient swap // Get the real player; undo previous transient swap
auto real_nemesis = getPlayerNemesis(c, true); auto real_nemesis = getPlayerNemesis(out, true);
if (!real_nemesis) if (!real_nemesis)
return CR_FAILURE; return CR_FAILURE;
// Get the unit to swap to // Get the unit to swap to
auto new_unit = getCurUnit(c); auto new_unit = getCurUnit();
auto new_nemesis = getNemesis(new_unit); auto new_nemesis = getNemesis(new_unit);
if (!new_nemesis) if (!new_nemesis)
{ {
if (new_unit) if (new_unit)
{ {
c->con.printerr("Cannot swap into a non-historical unit.\n"); out.printerr("Cannot swap into a non-historical unit.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -685,16 +694,16 @@ command_result adv_bodyswap (Core * c, std::vector <std::string> & parameters)
// Verify it's a companion // Verify it's a companion
if (!force && linear_index(real_nemesis->companions, new_nemesis->id) < 0) if (!force && linear_index(real_nemesis->companions, new_nemesis->id) < 0)
{ {
c->con.printerr("This is not your companion - use force to bodyswap.\n"); out.printerr("This is not your companion - use force to bodyswap.\n");
return CR_FAILURE; return CR_FAILURE;
} }
// Swap // Swap
if (!bodySwap(c, new_nemesis->unit)) if (!bodySwap(out, new_nemesis->unit))
return CR_FAILURE; return CR_FAILURE;
auto name = TranslateName(&new_nemesis->unit->name, false); auto name = TranslateName(&new_nemesis->unit->name, false);
c->con.print("Swapped into the body of %s.\n", name.c_str()); out.print("Swapped into the body of %s.\n", name.c_str());
// Permanently re-link everything // Permanently re-link everything
if (permanent) if (permanent)
@ -730,12 +739,12 @@ command_result adv_bodyswap (Core * c, std::vector <std::string> & parameters)
return CR_OK; return CR_OK;
} }
command_result adv_tools (Core * c, std::vector <std::string> & parameters) command_result adv_tools (color_ostream &out, std::vector <std::string> & parameters)
{ {
if (parameters.empty()) if (parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
const auto &command = parameters[0]; const auto &command = parameters[0];
if (command == "list-equipped") if (command == "list-equipped")
@ -751,7 +760,7 @@ command_result adv_tools (Core * c, std::vector <std::string> & parameters)
std::vector<nemesis_record*> list; std::vector<nemesis_record*> list;
listCompanions(c, &list); listCompanions(out, &list);
sortCompanionNemesis(&list); sortCompanionNemesis(&list);
for (size_t i = 0; i < list.size(); i++) for (size_t i = 0; i < list.size(); i++)
@ -759,8 +768,8 @@ command_result adv_tools (Core * c, std::vector <std::string> & parameters)
auto item = list[i]; auto item = list[i];
auto unit = item->unit; auto unit = item->unit;
printCompanionHeader(c, i, unit); printCompanionHeader(out, i, unit);
printEquipped(c, unit, all); printEquipped(out, unit, all);
} }
return CR_OK; return CR_OK;
@ -778,7 +787,7 @@ command_result adv_tools (Core * c, std::vector <std::string> & parameters)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
auto *player = getPlayerNemesis(c, false); auto *player = getPlayerNemesis(out, false);
if (!player) if (!player)
return CR_FAILURE; return CR_FAILURE;
@ -787,20 +796,19 @@ command_result adv_tools (Core * c, std::vector <std::string> & parameters)
int total = 0; int total = 0;
std::map<df::coord,int> counts; std::map<df::coord,int> counts;
for (size_t i = 0; i < world->map.map_blocks.size(); i++) auto &items = world->items.all;
{ for (size_t i = 0; i < items.size(); i++)
df::map_block *block = world->map.map_blocks[i];
for (size_t j = 0; j < block->items.size(); j++)
{ {
df::item *item = df::item::find(block->items[j]); df::item *item = items[i];
if (!item)
continue;
int num = containsMetalItems(item, all, non_trader); int num = containsMetalItems(item, all, non_trader);
if (!num) if (!num)
continue; continue;
df::map_block *block = Maps::getBlockAbs(item->pos);
if (!block)
continue;
total += num; total += num;
counts[(item->pos - player_pos)/10] += num; counts[(item->pos - player_pos)/10] += num;
@ -810,18 +818,17 @@ command_result adv_tools (Core * c, std::vector <std::string> & parameters)
dgn.bits.hidden = 0; // revealed dgn.bits.hidden = 0; // revealed
dgn.bits.pile = 1; // visible dgn.bits.pile = 1; // visible
} }
}
joinCounts(counts); joinCounts(counts);
c->con.print("%d items of metal merchandise found in the vicinity.\n", total); out.print("%d items of metal merchandise found in the vicinity.\n", total);
for (auto it = counts.begin(); it != counts.end(); it++) for (auto it = counts.begin(); it != counts.end(); it++)
{ {
if (!it->second) if (!it->second)
continue; continue;
df::coord delta = it->first * 10; df::coord delta = it->first * 10;
c->con.print(" %s: %d\n", formatDirection(delta).c_str(), it->second); out.print(" %s: %d\n", formatDirection(delta).c_str(), it->second);
} }
return CR_OK; return CR_OK;

@ -34,11 +34,11 @@ using df::global::world;
DFHACK_PLUGIN("autodump"); DFHACK_PLUGIN("autodump");
command_result df_autodump(Core * c, vector <string> & parameters); command_result df_autodump(color_ostream &out, vector <string> & parameters);
command_result df_autodump_destroy_here(Core * c, vector <string> & parameters); command_result df_autodump_destroy_here(color_ostream &out, vector <string> & parameters);
command_result df_autodump_destroy_item(Core * c, vector <string> & parameters); command_result df_autodump_destroy_item(color_ostream &out, vector <string> & parameters);
DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"autodump", "Teleport items marked for dumping to the cursor.", "autodump", "Teleport items marked for dumping to the cursor.",
@ -69,14 +69,14 @@ DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &com
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
typedef map <DFCoord, uint32_t> coordmap; typedef map <DFCoord, uint32_t> coordmap;
static command_result autodump_main(Core * c, vector <string> & parameters) static command_result autodump_main(color_ostream &out, vector <string> & parameters)
{ {
// Command line options // Command line options
bool destroy = false; bool destroy = false;
@ -103,14 +103,14 @@ static command_result autodump_main(Core * c, vector <string> & parameters)
if (need_visible && need_hidden) if (need_visible && need_hidden)
{ {
c->con.printerr("An item can't be both hidden and visible.\n"); out.printerr("An item can't be both hidden and visible.\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
DFHack::VersionInfo *mem = c->vinfo; //DFHack::VersionInfo *mem = Core::getInstance().vinfo;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
size_t numItems = world->items.all.size(); size_t numItems = world->items.all.size();
@ -125,7 +125,7 @@ static command_result autodump_main(Core * c, vector <string> & parameters)
{ {
if (!Gui::getCursorCoords(cx,cy,cz)) if (!Gui::getCursorCoords(cx,cy,cz))
{ {
c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); out.printerr("Cursor position not found. Please enabled the cursor.\n");
return CR_FAILURE; return CR_FAILURE;
} }
pos_cursor = DFCoord(cx,cy,cz); pos_cursor = DFCoord(cx,cy,cz);
@ -136,13 +136,13 @@ static command_result autodump_main(Core * c, vector <string> & parameters)
Block * b = MC.BlockAt(pos_cursor / 16); Block * b = MC.BlockAt(pos_cursor / 16);
if(!b) if(!b)
{ {
c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); out.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
return CR_FAILURE; return CR_FAILURE;
} }
df::tiletype ttype = MC.tiletypeAt(pos_cursor); df::tiletype ttype = MC.tiletypeAt(pos_cursor);
if(!DFHack::isFloorTerrain(ttype)) if(!DFHack::isFloorTerrain(ttype))
{ {
c->con.printerr("Cursor should be placed over a floor.\n"); out.printerr("Cursor should be placed over a floor.\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }
@ -274,18 +274,18 @@ static command_result autodump_main(Core * c, vector <string> & parameters)
// Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is?
Maps::WriteDirtyBit(cx/16, cy/16, cz, true); Maps::WriteDirtyBit(cx/16, cy/16, cz, true);
} }
c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped"); out.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped");
return CR_OK; return CR_OK;
} }
command_result df_autodump(Core * c, vector <string> & parameters) command_result df_autodump(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
return autodump_main(c, parameters); return autodump_main(out, parameters);
} }
command_result df_autodump_destroy_here(Core * c, vector <string> & parameters) command_result df_autodump_destroy_here(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND; CORE ALREADY SUSPENDED // HOTKEY COMMAND; CORE ALREADY SUSPENDED
if (!parameters.empty()) if (!parameters.empty())
@ -294,19 +294,19 @@ command_result df_autodump_destroy_here(Core * c, vector <string> & parameters)
vector<string> args; vector<string> args;
args.push_back("destroy-here"); args.push_back("destroy-here");
return autodump_main(c, args); return autodump_main(out, args);
} }
static map<int, df::item_flags> pending_destroy; static map<int, df::item_flags> pending_destroy;
static int last_frame = 0; static int last_frame = 0;
command_result df_autodump_destroy_item(Core * c, vector <string> & parameters) command_result df_autodump_destroy_item(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND; CORE ALREADY SUSPENDED // HOTKEY COMMAND; CORE ALREADY SUSPENDED
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::item *item = Gui::getSelectedItem(c); df::item *item = Gui::getSelectedItem(out);
if (!item) if (!item)
return CR_FAILURE; return CR_FAILURE;
@ -332,7 +332,7 @@ command_result df_autodump_destroy_item(Core * c, vector <string> & parameters)
// Check the item is good to destroy // Check the item is good to destroy
if (item->flags.bits.garbage_colect) if (item->flags.bits.garbage_colect)
{ {
c->con.printerr("Item is already marked for destroy.\n"); out.printerr("Item is already marked for destroy.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -340,7 +340,7 @@ command_result df_autodump_destroy_item(Core * c, vector <string> & parameters)
item->flags.bits.in_building || item->flags.bits.in_building ||
item->flags.bits.artifact1) item->flags.bits.artifact1)
{ {
c->con.printerr("Choosing not to destroy buildings, constructions and artifacts.\n"); out.printerr("Choosing not to destroy buildings, constructions and artifacts.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -349,7 +349,7 @@ command_result df_autodump_destroy_item(Core * c, vector <string> & parameters)
df::general_ref *ref = item->itemrefs[i]; df::general_ref *ref = item->itemrefs[i];
if (ref->getType() == general_ref_type::UNIT_HOLDER) if (ref->getType() == general_ref_type::UNIT_HOLDER)
{ {
c->con.printerr("Choosing not to destroy items in unit inventory.\n"); out.printerr("Choosing not to destroy items in unit inventory.\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }

@ -18,42 +18,42 @@ using namespace df::enums;
using df::global::world; using df::global::world;
using df::global::cursor; using df::global::cursor;
command_result df_changevein (Core * c, vector <string> & parameters) command_result df_changevein (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size() != 1) if (parameters.size() != 1)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (!cursor || cursor->x == -30000) if (!cursor || cursor->x == -30000)
{ {
c->con.printerr("No cursor detected - please place the cursor over a mineral vein.\n"); out.printerr("No cursor detected - please place the cursor over a mineral vein.\n");
return CR_FAILURE; return CR_FAILURE;
} }
MaterialInfo mi; MaterialInfo mi;
if (!mi.findInorganic(parameters[0])) if (!mi.findInorganic(parameters[0]))
{ {
c->con.printerr("No such material!\n"); out.printerr("No such material!\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (mi.inorganic->material.flags.is_set(material_flags::IS_METAL) || if (mi.inorganic->material.flags.is_set(material_flags::IS_METAL) ||
mi.inorganic->material.flags.is_set(material_flags::NO_STONE_STOCKPILE) || mi.inorganic->material.flags.is_set(material_flags::NO_STONE_STOCKPILE) ||
mi.inorganic->flags.is_set(inorganic_flags::SOIL_ANY)) mi.inorganic->flags.is_set(inorganic_flags::SOIL_ANY))
{ {
c->con.printerr("Invalid material - you must select a type of stone or gem\n"); out.printerr("Invalid material - you must select a type of stone or gem\n");
return CR_FAILURE; return CR_FAILURE;
} }
df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z);
if (!block) if (!block)
{ {
c->con.printerr("Invalid tile selected.\n"); out.printerr("Invalid tile selected.\n");
return CR_FAILURE; return CR_FAILURE;
} }
df::block_square_event_mineralst *mineral = NULL; df::block_square_event_mineralst *mineral = NULL;
@ -70,7 +70,7 @@ command_result df_changevein (Core * c, vector <string> & parameters)
} }
if (!mineral) if (!mineral)
{ {
c->con.printerr("Selected tile does not contain a mineral vein.\n"); out.printerr("Selected tile does not contain a mineral vein.\n");
return CR_FAILURE; return CR_FAILURE;
} }
mineral->inorganic_mat = mi.index; mineral->inorganic_mat = mi.index;
@ -80,7 +80,7 @@ command_result df_changevein (Core * c, vector <string> & parameters)
DFHACK_PLUGIN("changevein"); DFHACK_PLUGIN("changevein");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("changevein", commands.push_back(PluginCommand("changevein",
"Changes the material of a mineral inclusion.", "Changes the material of a mineral inclusion.",
@ -89,7 +89,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -23,7 +23,7 @@ using df::global::cursor;
DFHACK_PLUGIN("cleaners"); DFHACK_PLUGIN("cleaners");
command_result cleanmap (Core * c, bool snow, bool mud) command_result cleanmap (color_ostream &out, bool snow, bool mud)
{ {
// Invoked from clean(), already suspended // Invoked from clean(), already suspended
int num_blocks = 0, blocks_total = world->map.map_blocks.size(); int num_blocks = 0, blocks_total = world->map.map_blocks.size();
@ -67,11 +67,11 @@ command_result cleanmap (Core * c, bool snow, bool mud)
} }
if(num_blocks) if(num_blocks)
c->con.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total); out.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total);
return CR_OK; return CR_OK;
} }
command_result cleanitems (Core * c) command_result cleanitems (color_ostream &out)
{ {
// Invoked from clean(), already suspended // Invoked from clean(), already suspended
int cleaned_items = 0, cleaned_total = 0; int cleaned_items = 0, cleaned_total = 0;
@ -89,11 +89,11 @@ command_result cleanitems (Core * c)
} }
} }
if (cleaned_total) if (cleaned_total)
c->con.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items); out.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items);
return CR_OK; return CR_OK;
} }
command_result cleanunits (Core * c) command_result cleanunits (color_ostream &out)
{ {
// Invoked from clean(), already suspended // Invoked from clean(), already suspended
int cleaned_units = 0, cleaned_total = 0; int cleaned_units = 0, cleaned_total = 0;
@ -110,27 +110,27 @@ command_result cleanunits (Core * c)
} }
} }
if (cleaned_total) if (cleaned_total)
c->con.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units); out.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units);
return CR_OK; return CR_OK;
} }
command_result spotclean (Core * c, vector <string> & parameters) command_result spotclean (color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
if (cursor->x == -30000) if (cursor->x == -30000)
{ {
c->con.printerr("The cursor is not active.\n"); out.printerr("The cursor is not active.\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available.\n"); out.printerr("Map is not available.\n");
return CR_FAILURE; return CR_FAILURE;
} }
df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z);
if (block == NULL) if (block == NULL)
{ {
c->con.printerr("Invalid map block selected!\n"); out.printerr("Invalid map block selected!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -146,7 +146,7 @@ command_result spotclean (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
command_result clean (Core * c, vector <string> & parameters) command_result clean (color_ostream &out, vector <string> & parameters)
{ {
bool map = false; bool map = false;
bool snow = false; bool snow = false;
@ -177,17 +177,18 @@ command_result clean (Core * c, vector <string> & parameters)
if(!map && !units && !items) if(!map && !units && !items)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if(map) if(map)
cleanmap(c,snow,mud); cleanmap(out,snow,mud);
if(units) if(units)
cleanunits(c); cleanunits(out);
if(items) if(items)
cleanitems(c); cleanitems(out);
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"clean","Removes contaminants from map tiles, items and creatures.", "clean","Removes contaminants from map tiles, items and creatures.",
@ -212,7 +213,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -25,11 +25,11 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_cleanowned (Core * c, vector <string> & parameters); command_result df_cleanowned (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("cleanowned"); DFHACK_PLUGIN("cleanowned");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"cleanowned", "Confiscates and dumps garbage owned by dwarfs.", "cleanowned", "Confiscates and dumps garbage owned by dwarfs.",
@ -51,12 +51,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result df_cleanowned (Core * c, vector <string> & parameters) command_result df_cleanowned (color_ostream &out, vector <string> & parameters)
{ {
bool dump_scattered = false; bool dump_scattered = false;
bool confiscate_all = false; bool confiscate_all = false;
@ -80,15 +80,15 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Translation::IsValid()) if (!Translation::IsValid())
{ {
c->con.printerr("Translation data unavailable!\n"); out.printerr("Translation data unavailable!\n");
return CR_FAILURE; return CR_FAILURE;
} }
c->con.print("Found total %d items.\n", world->items.all.size()); out.print("Found total %d items.\n", world->items.all.size());
for (std::size_t i=0; i < world->items.all.size(); i++) for (std::size_t i=0; i < world->items.all.size(); i++)
{ {
@ -101,7 +101,7 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
int32_t owner = Items::getItemOwnerID(item); int32_t owner = Items::getItemOwnerID(item);
if (owner >= 0) if (owner >= 0)
{ {
c->con.print("Fixing a misflagged item: \t"); out.print("Fixing a misflagged item: \t");
confiscate = true; confiscate = true;
} }
else else
@ -112,7 +112,7 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
if (item->flags.bits.rotten) if (item->flags.bits.rotten)
{ {
c->con.print("Confiscating a rotten item: \t"); out.print("Confiscating a rotten item: \t");
confiscate = true; confiscate = true;
} }
else if (item->flags.bits.on_ground) else if (item->flags.bits.on_ground)
@ -130,30 +130,30 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
confiscate = true; confiscate = true;
if(dump_scattered) if(dump_scattered)
{ {
c->con.print("Dumping a dropped item: \t"); out.print("Dumping a dropped item: \t");
dump = true; dump = true;
} }
else else
{ {
c->con.print("Confiscating a dropped item: \t"); out.print("Confiscating a dropped item: \t");
} }
} }
else if(dump_scattered) else if(dump_scattered)
{ {
c->con.print("Confiscating and dumping litter: \t"); out.print("Confiscating and dumping litter: \t");
confiscate = true; confiscate = true;
dump = true; dump = true;
} }
} }
else if (item->getWear() >= wear_dump_level) else if (item->getWear() >= wear_dump_level)
{ {
c->con.print("Confiscating and dumping a worn item: \t"); out.print("Confiscating and dumping a worn item: \t");
confiscate = true; confiscate = true;
dump = true; dump = true;
} }
else if (confiscate_all) else if (confiscate_all)
{ {
c->con.print("Confiscating: \t"); out.print("Confiscating: \t");
confiscate = true; confiscate = true;
} }
@ -161,7 +161,7 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
{ {
std::string description; std::string description;
item->getItemDescription(&description, 0); item->getItemDescription(&description, 0);
c->con.print( out.print(
"0x%x %s (wear %d)", "0x%x %s (wear %d)",
item, item,
description.c_str(), description.c_str(),
@ -171,16 +171,16 @@ command_result df_cleanowned (Core * c, vector <string> & parameters)
df::unit *owner = Items::getItemOwner(item); df::unit *owner = Items::getItemOwner(item);
if (owner) if (owner)
c->con.print(", owner %s", Translation::TranslateName(&owner->name,false).c_str()); out.print(", owner %s", Translation::TranslateName(&owner->name,false).c_str());
if (!dry_run) if (!dry_run)
{ {
if (!Items::removeItemOwner(item)) if (!Items::removeItemOwner(item))
c->con.print("(unsuccessfully) "); out.print("(unsuccessfully) ");
if (dump) if (dump)
item->flags.bits.dump = 1; item->flags.bits.dump = 1;
} }
c->con.print("\n"); out.print("\n");
} }
} }
return CR_OK; return CR_OK;

@ -11,11 +11,11 @@ using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
command_result colonies (Core * c, vector <string> & parameters); command_result colonies (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("colonies"); DFHACK_PLUGIN("colonies");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"colonies", "List or change wild colonies (ants hills and such)", "colonies", "List or change wild colonies (ants hills and such)",
@ -28,16 +28,16 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
void destroyColonies(); void destroyColonies();
void convertColonies(Materials *Materials); void convertColonies(Materials *Materials);
void showColonies(Core *c, Materials *Materials); void showColonies(color_ostream &out, Materials *Materials);
command_result colonies (Core * c, vector <string> & parameters) command_result colonies (color_ostream &out, vector <string> & parameters)
{ {
bool destroy = false; bool destroy = false;
bool convert = false; bool convert = false;
@ -53,12 +53,13 @@ command_result colonies (Core * c, vector <string> & parameters)
} }
if (destroy && convert) if (destroy && convert)
{ {
c->con.printerr("Kill or make bees? DECIDE!\n"); out.printerr("Kill or make bees? DECIDE!\n");
return CR_FAILURE; return CR_FAILURE;
} }
CoreSuspender suspend(c);
Materials * materials = c->getMaterials(); CoreSuspender suspend;
Materials * materials = Core::getInstance().getMaterials();
materials->ReadCreatureTypesEx(); materials->ReadCreatureTypesEx();
@ -67,7 +68,7 @@ command_result colonies (Core * c, vector <string> & parameters)
else if (convert) else if (convert)
convertColonies(materials); convertColonies(materials);
else else
showColonies(c, materials); showColonies(out, materials);
materials->Finish(); materials->Finish();
@ -124,7 +125,7 @@ void convertColonies(Materials *Materials)
} }
} }
void showColonies(Core *c, Materials *Materials) void showColonies(color_ostream &out, Materials *Materials)
{ {
uint32_t numSpawnPoints = Vermin::getNumVermin(); uint32_t numSpawnPoints = Vermin::getNumVermin();
int numColonies = 0; int numColonies = 0;
@ -141,11 +142,11 @@ void showColonies(Core *c, Materials *Materials)
if(sp.race != -1) if(sp.race != -1)
race = Materials->raceEx[sp.race].id; race = Materials->raceEx[sp.race].id;
c->con.print("Colony %u: %s at %d:%d:%d\n", i, out.print("Colony %u: %s at %d:%d:%d\n", i,
race.c_str(), sp.x, sp.y, sp.z); race.c_str(), sp.x, sp.y, sp.z);
} }
} }
if (numColonies == 0) if (numColonies == 0)
c->con << "No colonies present." << std::endl; out << "No colonies present." << std::endl;
} }

@ -18,16 +18,16 @@ using df::global::world;
DFHACK_PLUGIN("deramp"); DFHACK_PLUGIN("deramp");
command_result df_deramp (Core * c, vector <string> & parameters) command_result df_deramp (color_ostream &out, vector <string> & parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -75,13 +75,13 @@ command_result df_deramp (Core * c, vector <string> & parameters)
} }
} }
if (count) if (count)
c->con.print("Found and changed %d tiles.\n", count); out.print("Found and changed %d tiles.\n", count);
if (countbad) if (countbad)
c->con.print("Fixed %d bad down ramps.\n", countbad); out.print("Fixed %d bad down ramps.\n", countbad);
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"deramp", "De-ramp. All ramps marked for removal are replaced with floors.", "deramp", "De-ramp. All ramps marked for removal are replaced with floors.",
@ -93,7 +93,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -18,40 +18,38 @@ using std::string;
using std::stack; using std::stack;
using namespace DFHack; using namespace DFHack;
command_result readFlag (Core * c, vector <string> & parameters); command_result readFlag (color_ostream &out, vector <string> & parameters);
command_result writeFlag (Core * c, vector <string> & parameters); command_result writeFlag (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("buildprobe"); DFHACK_PLUGIN("buildprobe");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("bshow","Output building occupancy value",readFlag)); commands.push_back(PluginCommand("bshow","Output building occupancy value",readFlag));
commands.push_back(PluginCommand("bset","Set building occupancy value",writeFlag)); commands.push_back(PluginCommand("bset","Set building occupancy value",writeFlag));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result readFlag (Core * c, vector <string> & parameters) command_result readFlag (color_ostream &out, vector <string> & parameters)
{ {
c->Suspend(); CoreSuspender suspend;
// init the map // init the map
if(!Maps::IsValid()) if(!Maps::IsValid())
{ {
c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); out.printerr("Can't init map. Make sure you have a map loaded in DF.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
int32_t cx, cy, cz; int32_t cx, cy, cz;
if(!Gui::getCursorCoords(cx,cy,cz)) if(!Gui::getCursorCoords(cx,cy,cz))
{ {
c->con.printerr("Cursor is not active.\n"); out.printerr("Cursor is not active.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
@ -60,23 +58,21 @@ command_result readFlag (Core * c, vector <string> & parameters)
MapExtras::MapCache * MCache = new MapExtras::MapCache(); MapExtras::MapCache * MCache = new MapExtras::MapCache();
t_occupancy oc = MCache->occupancyAt(cursor); t_occupancy oc = MCache->occupancyAt(cursor);
c->con.print("Current Value: %d\n", oc.bits.building); out.print("Current Value: %d\n", oc.bits.building);
c->Resume();
return CR_OK; return CR_OK;
} }
command_result writeFlag (Core * c, vector <string> & parameters) command_result writeFlag (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size() == 0) if (parameters.size() == 0)
{ {
c->con.print("No value specified\n"); out.print("No value specified\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (parameters[0] == "help" || parameters[0] == "?") if (parameters[0] == "help" || parameters[0] == "?")
{ {
c->con.print("Set the building occupancy flag.\n" out.print("Set the building occupancy flag.\n"
"Value must be between 0 and 7, inclusive.\n"); "Value must be between 0 and 7, inclusive.\n");
return CR_OK; return CR_OK;
} }
@ -97,26 +93,24 @@ command_result writeFlag (Core * c, vector <string> & parameters)
break; break;
default: default:
c->con.print("Invalid value specified\n"); out.print("Invalid value specified\n");
return CR_FAILURE; return CR_FAILURE;
break; //Redundant. break; //Redundant.
} }
c->Suspend(); CoreSuspender suspend;
// init the map // init the map
if(!Maps::IsValid()) if(!Maps::IsValid())
{ {
c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); out.printerr("Can't init map. Make sure you have a map loaded in DF.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
int32_t cx, cy, cz; int32_t cx, cy, cz;
if(!Gui::getCursorCoords(cx,cy,cz)) if(!Gui::getCursorCoords(cx,cy,cz))
{ {
c->con.printerr("Cursor is not active.\n"); out.printerr("Cursor is not active.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
@ -129,6 +123,5 @@ command_result writeFlag (Core * c, vector <string> & parameters)
MCache->setOccupancyAt(cursor, oc); MCache->setOccupancyAt(cursor, oc);
MCache->WriteAll(); MCache->WriteAll();
c->Resume();
return CR_OK; return CR_OK;
} }

@ -25,12 +25,12 @@ using namespace std;
using namespace DFHack; using namespace DFHack;
command_result catsplosion (Core * c, std::vector <std::string> & parameters); command_result catsplosion (color_ostream &out, std::vector <std::string> & parameters);
DFHACK_PLUGIN("catsplosion"); DFHACK_PLUGIN("catsplosion");
// Mandatory init function. If you have some global state, create it here. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -41,13 +41,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
typedef df::unit::T_relations::T_pregnancy_ptr pregstruct; typedef df::unit::T_relations::T_pregnancy_ptr pregstruct;
command_result catsplosion (Core * c, std::vector <std::string> & parameters) command_result catsplosion (color_ostream &out, std::vector <std::string> & parameters)
{ {
list<string> s_creatures; list<string> s_creatures;
// only cats for now. // only cats for now.
@ -55,7 +55,7 @@ command_result catsplosion (Core * c, std::vector <std::string> & parameters)
// make the creature list unique ... with cats. they are always unique // make the creature list unique ... with cats. they are always unique
s_creatures.unique(); s_creatures.unique();
// SUSPEND THE CORE! ::Evil laugh:: // SUSPEND THE CORE! ::Evil laugh::
CoreSuspender susp(c); CoreSuspender susp;
uint32_t numCreatures; uint32_t numCreatures;
if(!(numCreatures = Units::getNumCreatures())) if(!(numCreatures = Units::getNumCreatures()))
@ -95,10 +95,10 @@ command_result catsplosion (Core * c, std::vector <std::string> & parameters)
// print (optional) // print (optional)
//if (showcreatures == 1) //if (showcreatures == 1)
{ {
c->con.print("Type Male # Female #\n"); out.print("Type Male # Female #\n");
for(auto it1 = male_counts.begin();it1!=male_counts.end();it1++) for(auto it1 = male_counts.begin();it1!=male_counts.end();it1++)
{ {
c->con.print("%20s %6d %8d\n", it1->first.c_str(), it1->second.size(), female_counts[it1->first].size()); out.print("%20s %6d %8d\n", it1->first.c_str(), it1->second.size(), female_counts[it1->first].size());
} }
} }
@ -133,9 +133,9 @@ command_result catsplosion (Core * c, std::vector <std::string> & parameters)
} }
} }
if(totalchanged) if(totalchanged)
c->con.print("%d pregnancies accelerated.\n", totalchanged); out.print("%d pregnancies accelerated.\n", totalchanged);
if(totalcreated) if(totalcreated)
c->con.print("%d pregnancies created.\n", totalcreated); out.print("%d pregnancies created.\n", totalcreated);
c->con.print("Total creatures checked: %d\n", totalcount); out.print("Total creatures checked: %d\n", totalcount);
return CR_OK; return CR_OK;
} }

@ -19,22 +19,22 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_dumpmats (Core *c, vector<string> &parameters) command_result df_dumpmats (color_ostream &out, vector<string> &parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
c->con.print("hardcoded_materials\n\n"); out.print("hardcoded_materials\n\n");
c->con.print("[OBJECT:MATERIAL]\n"); out.print("[OBJECT:MATERIAL]\n");
FOR_ENUM_ITEMS(builtin_mats, mat_num) FOR_ENUM_ITEMS(builtin_mats, mat_num)
{ {
df::material *mat = world->raws.mat_table.builtin[mat_num]; df::material *mat = world->raws.mat_table.builtin[mat_num];
if (!mat) if (!mat)
continue; continue;
c->con.print("\n[MATERIAL:%s] - reconstructed from data extracted from memory\n", mat->id.c_str()); out.print("\n[MATERIAL:%s] - reconstructed from data extracted from memory\n", mat->id.c_str());
int32_t def_color[6] = {-1,-1,-1,-1,-1,-1}; int32_t def_color[6] = {-1,-1,-1,-1,-1,-1};
bool name_all = false; bool name_all = false;
@ -58,10 +58,10 @@ command_result df_dumpmats (Core *c, vector<string> &parameters)
{ {
def_color[matter_state::Liquid] = solid_color; def_color[matter_state::Liquid] = solid_color;
def_color[matter_state::Gas] = solid_color; def_color[matter_state::Gas] = solid_color;
c->con.print("\t[STATE_COLOR:ALL:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); out.print("\t[STATE_COLOR:ALL:%s]\n", world->raws.language.colors[solid_color]->id.c_str());
} }
else else
c->con.print("\t[STATE_COLOR:ALL_SOLID:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); out.print("\t[STATE_COLOR:ALL_SOLID:%s]\n", world->raws.language.colors[solid_color]->id.c_str());
} }
string solid_name = mat->state_name[matter_state::Solid]; string solid_name = mat->state_name[matter_state::Solid];
@ -88,10 +88,10 @@ command_result df_dumpmats (Core *c, vector<string> &parameters)
def_name[matter_state::Gas] = solid_name; def_name[matter_state::Gas] = solid_name;
def_adj[matter_state::Liquid] = solid_name; def_adj[matter_state::Liquid] = solid_name;
def_adj[matter_state::Gas] = solid_name; def_adj[matter_state::Gas] = solid_name;
c->con.print("\t[STATE_NAME_ADJ:ALL:%s]\n", solid_name.c_str()); out.print("\t[STATE_NAME_ADJ:ALL:%s]\n", solid_name.c_str());
} }
else else
c->con.print("\t[STATE_NAME_ADJ:ALL_SOLID:%s]\n", solid_name.c_str()); out.print("\t[STATE_NAME_ADJ:ALL_SOLID:%s]\n", solid_name.c_str());
} }
} }
else else
@ -110,10 +110,10 @@ command_result df_dumpmats (Core *c, vector<string> &parameters)
{ {
def_name[matter_state::Liquid] = solid_name; def_name[matter_state::Liquid] = solid_name;
def_name[matter_state::Gas] = solid_name; def_name[matter_state::Gas] = solid_name;
c->con.print("\t[STATE_NAME:ALL:%s]\n", solid_name.c_str()); out.print("\t[STATE_NAME:ALL:%s]\n", solid_name.c_str());
} }
else else
c->con.print("\t[STATE_NAME:ALL_SOLID:%s]\n", solid_name.c_str()); out.print("\t[STATE_NAME:ALL_SOLID:%s]\n", solid_name.c_str());
} }
if (solid_adj == mat->state_adj[matter_state::Powder] || if (solid_adj == mat->state_adj[matter_state::Powder] ||
solid_adj == mat->state_adj[matter_state::Paste] || solid_adj == mat->state_adj[matter_state::Paste] ||
@ -129,148 +129,148 @@ command_result df_dumpmats (Core *c, vector<string> &parameters)
{ {
def_adj[matter_state::Liquid] = solid_adj; def_adj[matter_state::Liquid] = solid_adj;
def_adj[matter_state::Gas] = solid_adj; def_adj[matter_state::Gas] = solid_adj;
c->con.print("\t[STATE_ADJ:ALL:%s]\n", solid_adj.c_str()); out.print("\t[STATE_ADJ:ALL:%s]\n", solid_adj.c_str());
} }
else else
c->con.print("\t[STATE_ADJ:ALL_SOLID:%s]\n", solid_adj.c_str()); out.print("\t[STATE_ADJ:ALL_SOLID:%s]\n", solid_adj.c_str());
} }
} }
char *state_names[6] = {"SOLID", "LIQUID", "GAS", "SOLID_POWDER", "SOLID_PASTE", "SOLID_PRESSED"}; const char *state_names[6] = {"SOLID", "LIQUID", "GAS", "SOLID_POWDER", "SOLID_PASTE", "SOLID_PRESSED"};
FOR_ENUM_ITEMS(matter_state, state) FOR_ENUM_ITEMS(matter_state, state)
{ {
if (mat->state_color[state] != -1 && mat->state_color[state] != def_color[state]) if (mat->state_color[state] != -1 && mat->state_color[state] != def_color[state])
c->con.print("\t[STATE_COLOR:%s:%s]\n", state_names[state], world->raws.language.colors[mat->state_color[state]]->id.c_str()); out.print("\t[STATE_COLOR:%s:%s]\n", state_names[state], world->raws.language.colors[mat->state_color[state]]->id.c_str());
if (mat->state_name[state] == mat->state_adj[state]) if (mat->state_name[state] == mat->state_adj[state])
{ {
if (mat->state_name[state].size() && mat->state_name[state] != def_name[state] || mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state]) if (mat->state_name[state].size() && mat->state_name[state] != def_name[state] || mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state])
c->con.print("\t[STATE_NAME_ADJ:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); out.print("\t[STATE_NAME_ADJ:%s:%s]\n", state_names[state], mat->state_name[state].c_str());
} }
else else
{ {
if (mat->state_name[state].size() && mat->state_name[state] != def_name[state]) if (mat->state_name[state].size() && mat->state_name[state] != def_name[state])
c->con.print("\t[STATE_NAME:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); out.print("\t[STATE_NAME:%s:%s]\n", state_names[state], mat->state_name[state].c_str());
if (mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state]) if (mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state])
c->con.print("\t[STATE_ADJ:%s:%s]\n", state_names[state], mat->state_adj[state].c_str()); out.print("\t[STATE_ADJ:%s:%s]\n", state_names[state], mat->state_adj[state].c_str());
} }
} }
if (mat->basic_color[0] != 7 || mat->basic_color[1] != 0) if (mat->basic_color[0] != 7 || mat->basic_color[1] != 0)
c->con.print("\t[BASIC_COLOR:%i:%i]\n", mat->basic_color[0], mat->basic_color[1]); out.print("\t[BASIC_COLOR:%i:%i]\n", mat->basic_color[0], mat->basic_color[1]);
if (mat->build_color[0] != 7 || mat->build_color[1] != 7 || mat->build_color[2] != 0) if (mat->build_color[0] != 7 || mat->build_color[1] != 7 || mat->build_color[2] != 0)
c->con.print("\t[BUILD_COLOR:%i:%i:%i]\n", mat->build_color[0], mat->build_color[1], mat->build_color[2]); out.print("\t[BUILD_COLOR:%i:%i:%i]\n", mat->build_color[0], mat->build_color[1], mat->build_color[2]);
if (mat->tile_color[0] != 7 || mat->tile_color[1] != 7 || mat->tile_color[2] != 0) if (mat->tile_color[0] != 7 || mat->tile_color[1] != 7 || mat->tile_color[2] != 0)
c->con.print("\t[TILE_COLOR:%i:%i:%i]\n", mat->tile_color[0], mat->tile_color[1], mat->tile_color[2]); out.print("\t[TILE_COLOR:%i:%i:%i]\n", mat->tile_color[0], mat->tile_color[1], mat->tile_color[2]);
if (mat->tile != 0xdb) if (mat->tile != 0xdb)
c->con.print("\t[TILE:%i]\n", mat->tile); out.print("\t[TILE:%i]\n", mat->tile);
if (mat->item_symbol != 0x07) if (mat->item_symbol != 0x07)
c->con.print("\t[ITEM_SYMBOL:%i]\n", mat->item_symbol); out.print("\t[ITEM_SYMBOL:%i]\n", mat->item_symbol);
if (mat->material_value != 1) if (mat->material_value != 1)
c->con.print("\t[MATERIAL_VALUE:%i]\n", mat->material_value); out.print("\t[MATERIAL_VALUE:%i]\n", mat->material_value);
if (mat->gem_name1.size()) if (mat->gem_name1.size())
c->con.print("\t[IS_GEM:%s:%s]\n", mat->gem_name1.c_str(), mat->gem_name2.c_str()); out.print("\t[IS_GEM:%s:%s]\n", mat->gem_name1.c_str(), mat->gem_name2.c_str());
if (mat->stone_name.size()) if (mat->stone_name.size())
c->con.print("\t[STONE_NAME:%s]\n", mat->stone_name.c_str()); out.print("\t[STONE_NAME:%s]\n", mat->stone_name.c_str());
if (mat->heat.spec_heat != 60001) if (mat->heat.spec_heat != 60001)
c->con.print("\t[SPEC_HEAT:%i]\n", mat->heat.spec_heat); out.print("\t[SPEC_HEAT:%i]\n", mat->heat.spec_heat);
if (mat->heat.heatdam_point != 60001) if (mat->heat.heatdam_point != 60001)
c->con.print("\t[HEATDAM_POINT:%i]\n", mat->heat.heatdam_point); out.print("\t[HEATDAM_POINT:%i]\n", mat->heat.heatdam_point);
if (mat->heat.colddam_point != 60001) if (mat->heat.colddam_point != 60001)
c->con.print("\t[COLDDAM_POINT:%i]\n", mat->heat.colddam_point); out.print("\t[COLDDAM_POINT:%i]\n", mat->heat.colddam_point);
if (mat->heat.ignite_point != 60001) if (mat->heat.ignite_point != 60001)
c->con.print("\t[IGNITE_POINT:%i]\n", mat->heat.ignite_point); out.print("\t[IGNITE_POINT:%i]\n", mat->heat.ignite_point);
if (mat->heat.melting_point != 60001) if (mat->heat.melting_point != 60001)
c->con.print("\t[MELTING_POINT:%i]\n", mat->heat.melting_point); out.print("\t[MELTING_POINT:%i]\n", mat->heat.melting_point);
if (mat->heat.boiling_point != 60001) if (mat->heat.boiling_point != 60001)
c->con.print("\t[BOILING_POINT:%i]\n", mat->heat.boiling_point); out.print("\t[BOILING_POINT:%i]\n", mat->heat.boiling_point);
if (mat->heat.mat_fixed_temp != 60001) if (mat->heat.mat_fixed_temp != 60001)
c->con.print("\t[MAT_FIXED_TEMP:%i]\n", mat->heat.mat_fixed_temp); out.print("\t[MAT_FIXED_TEMP:%i]\n", mat->heat.mat_fixed_temp);
if (mat->solid_density != 0xFBBC7818) if (mat->solid_density != 0xFBBC7818)
c->con.print("\t[SOLID_DENSITY:%i]\n", mat->solid_density); out.print("\t[SOLID_DENSITY:%i]\n", mat->solid_density);
if (mat->liquid_density != 0xFBBC7818) if (mat->liquid_density != 0xFBBC7818)
c->con.print("\t[LIQUID_DENSITY:%i]\n", mat->liquid_density); out.print("\t[LIQUID_DENSITY:%i]\n", mat->liquid_density);
if (mat->molar_mass != 0xFBBC7818) if (mat->molar_mass != 0xFBBC7818)
c->con.print("\t[MOLAR_MASS:%i]\n", mat->molar_mass); out.print("\t[MOLAR_MASS:%i]\n", mat->molar_mass);
if (mat->strength.impact_yield != 10000) if (mat->strength.impact_yield != 10000)
c->con.print("\t[IMPACT_YIELD:%i]\n", mat->strength.impact_yield); out.print("\t[IMPACT_YIELD:%i]\n", mat->strength.impact_yield);
if (mat->strength.impact_fracture != 10000) if (mat->strength.impact_fracture != 10000)
c->con.print("\t[IMPACT_FRACTURE:%i]\n", mat->strength.impact_fracture); out.print("\t[IMPACT_FRACTURE:%i]\n", mat->strength.impact_fracture);
if (mat->strength.impact_strain_at_yield != 0) if (mat->strength.impact_strain_at_yield != 0)
c->con.print("\t[IMPACT_STRAIN_AT_YIELD:%i]\n", mat->strength.impact_strain_at_yield); out.print("\t[IMPACT_STRAIN_AT_YIELD:%i]\n", mat->strength.impact_strain_at_yield);
if (mat->strength.compressive_yield != 10000) if (mat->strength.compressive_yield != 10000)
c->con.print("\t[COMPRESSIVE_YIELD:%i]\n", mat->strength.compressive_yield); out.print("\t[COMPRESSIVE_YIELD:%i]\n", mat->strength.compressive_yield);
if (mat->strength.compressive_fracture != 10000) if (mat->strength.compressive_fracture != 10000)
c->con.print("\t[COMPRESSIVE_FRACTURE:%i]\n", mat->strength.compressive_fracture); out.print("\t[COMPRESSIVE_FRACTURE:%i]\n", mat->strength.compressive_fracture);
if (mat->strength.compressive_strain_at_yield != 0) if (mat->strength.compressive_strain_at_yield != 0)
c->con.print("\t[COMPRESSIVE_STRAIN_AT_YIELD:%i]\n", mat->strength.compressive_strain_at_yield); out.print("\t[COMPRESSIVE_STRAIN_AT_YIELD:%i]\n", mat->strength.compressive_strain_at_yield);
if (mat->strength.tensile_yield != 10000) if (mat->strength.tensile_yield != 10000)
c->con.print("\t[TENSILE_YIELD:%i]\n", mat->strength.tensile_yield); out.print("\t[TENSILE_YIELD:%i]\n", mat->strength.tensile_yield);
if (mat->strength.tensile_fracture != 10000) if (mat->strength.tensile_fracture != 10000)
c->con.print("\t[TENSILE_FRACTURE:%i]\n", mat->strength.tensile_fracture); out.print("\t[TENSILE_FRACTURE:%i]\n", mat->strength.tensile_fracture);
if (mat->strength.tensile_strain_at_yield != 0) if (mat->strength.tensile_strain_at_yield != 0)
c->con.print("\t[TENSILE_STRAIN_AT_YIELD:%i]\n", mat->strength.tensile_strain_at_yield); out.print("\t[TENSILE_STRAIN_AT_YIELD:%i]\n", mat->strength.tensile_strain_at_yield);
if (mat->strength.torsion_yield != 10000) if (mat->strength.torsion_yield != 10000)
c->con.print("\t[TORSION_YIELD:%i]\n", mat->strength.torsion_yield); out.print("\t[TORSION_YIELD:%i]\n", mat->strength.torsion_yield);
if (mat->strength.torsion_fracture != 10000) if (mat->strength.torsion_fracture != 10000)
c->con.print("\t[TORSION_FRACTURE:%i]\n", mat->strength.torsion_fracture); out.print("\t[TORSION_FRACTURE:%i]\n", mat->strength.torsion_fracture);
if (mat->strength.torsion_strain_at_yield != 0) if (mat->strength.torsion_strain_at_yield != 0)
c->con.print("\t[TORSION_STRAIN_AT_YIELD:%i]\n", mat->strength.torsion_strain_at_yield); out.print("\t[TORSION_STRAIN_AT_YIELD:%i]\n", mat->strength.torsion_strain_at_yield);
if (mat->strength.shear_yield != 10000) if (mat->strength.shear_yield != 10000)
c->con.print("\t[SHEAR_YIELD:%i]\n", mat->strength.shear_yield); out.print("\t[SHEAR_YIELD:%i]\n", mat->strength.shear_yield);
if (mat->strength.shear_fracture != 10000) if (mat->strength.shear_fracture != 10000)
c->con.print("\t[SHEAR_FRACTURE:%i]\n", mat->strength.shear_fracture); out.print("\t[SHEAR_FRACTURE:%i]\n", mat->strength.shear_fracture);
if (mat->strength.shear_strain_at_yield != 0) if (mat->strength.shear_strain_at_yield != 0)
c->con.print("\t[SHEAR_STRAIN_AT_YIELD:%i]\n", mat->strength.shear_strain_at_yield); out.print("\t[SHEAR_STRAIN_AT_YIELD:%i]\n", mat->strength.shear_strain_at_yield);
if (mat->strength.bending_yield != 10000) if (mat->strength.bending_yield != 10000)
c->con.print("\t[BENDING_YIELD:%i]\n", mat->strength.bending_yield); out.print("\t[BENDING_YIELD:%i]\n", mat->strength.bending_yield);
if (mat->strength.bending_fracture != 10000) if (mat->strength.bending_fracture != 10000)
c->con.print("\t[BENDING_FRACTURE:%i]\n", mat->strength.bending_fracture); out.print("\t[BENDING_FRACTURE:%i]\n", mat->strength.bending_fracture);
if (mat->strength.bending_strain_at_yield != 0) if (mat->strength.bending_strain_at_yield != 0)
c->con.print("\t[BENDING_STRAIN_AT_YIELD:%i]\n", mat->strength.bending_strain_at_yield); out.print("\t[BENDING_STRAIN_AT_YIELD:%i]\n", mat->strength.bending_strain_at_yield);
if (mat->strength.max_edge != 0) if (mat->strength.max_edge != 0)
c->con.print("\t[MAX_EDGE:%i]\n", mat->strength.max_edge); out.print("\t[MAX_EDGE:%i]\n", mat->strength.max_edge);
if (mat->strength.absorption != 0) if (mat->strength.absorption != 0)
c->con.print("\t[ABSORPTION:%i]\n", mat->strength.absorption); out.print("\t[ABSORPTION:%i]\n", mat->strength.absorption);
FOR_ENUM_ITEMS(material_flags, i) FOR_ENUM_ITEMS(material_flags, i)
{ {
if (mat->flags.is_set(i)) if (mat->flags.is_set(i))
c->con.print("\t[%s]\n", ENUM_KEY_STR(material_flags, i)); out.print("\t[%s]\n", ENUM_KEY_STR(material_flags, i));
} }
if (mat->extract_storage != item_type::BARREL) if (mat->extract_storage != item_type::BARREL)
c->con.print("\t[EXTRACT_STORAGE:%s]\n", ENUM_KEY_STR(item_type, mat->extract_storage)); out.print("\t[EXTRACT_STORAGE:%s]\n", ENUM_KEY_STR(item_type, mat->extract_storage));
if (mat->butcher_special_type != item_type::NONE || mat->butcher_special_subtype != -1) if (mat->butcher_special_type != item_type::NONE || mat->butcher_special_subtype != -1)
c->con.print("\t[BUTCHER_SPECIAL:%s:%s]\n", ENUM_KEY_STR(item_type, mat->butcher_special_type), (mat->butcher_special_subtype == -1) ? "NONE" : "?"); out.print("\t[BUTCHER_SPECIAL:%s:%s]\n", ENUM_KEY_STR(item_type, mat->butcher_special_type), (mat->butcher_special_subtype == -1) ? "NONE" : "?");
if (mat->meat_name[0].size() || mat->meat_name[1].size() || mat->meat_name[2].size()) if (mat->meat_name[0].size() || mat->meat_name[1].size() || mat->meat_name[2].size())
c->con.print("\t[MEAT_NAME:%s:%s:%s]\n", mat->meat_name[0].c_str(), mat->meat_name[1].c_str(), mat->meat_name[2].c_str()); out.print("\t[MEAT_NAME:%s:%s:%s]\n", mat->meat_name[0].c_str(), mat->meat_name[1].c_str(), mat->meat_name[2].c_str());
if (mat->block_name[0].size() || mat->block_name[1].size()) if (mat->block_name[0].size() || mat->block_name[1].size())
c->con.print("\t[BLOCK_NAME:%s:%s]\n", mat->block_name[0].c_str(), mat->block_name[1].c_str()); out.print("\t[BLOCK_NAME:%s:%s]\n", mat->block_name[0].c_str(), mat->block_name[1].c_str());
for (int i = 0; i < mat->reaction_class.size(); i++) for (int i = 0; i < mat->reaction_class.size(); i++)
c->con.print("\t[REACTION_CLASS:%s]\n", mat->reaction_class[i]->c_str()); out.print("\t[REACTION_CLASS:%s]\n", mat->reaction_class[i]->c_str());
for (int i = 0; i < mat->reaction_product.id.size(); i++) for (int i = 0; i < mat->reaction_product.id.size(); i++)
c->con.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[0][i]->c_str(), mat->reaction_product.str[1][i]->c_str(), mat->reaction_product.str[2][i]->size() ? ":" : "", mat->reaction_product.str[2][i]->c_str()); out.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[0][i]->c_str(), mat->reaction_product.str[1][i]->c_str(), mat->reaction_product.str[2][i]->size() ? ":" : "", mat->reaction_product.str[2][i]->c_str());
if (mat->hardens_with_water.mat_type != -1) if (mat->hardens_with_water.mat_type != -1)
c->con.print("\t[HARDENS_WITH_WATER:%s:%s%s%s]\n", mat->hardens_with_water.str[0].c_str(), mat->hardens_with_water.str[1].c_str(), mat->hardens_with_water.str[2].size() ? ":" : "", mat->hardens_with_water.str[2].c_str()); out.print("\t[HARDENS_WITH_WATER:%s:%s%s%s]\n", mat->hardens_with_water.str[0].c_str(), mat->hardens_with_water.str[1].c_str(), mat->hardens_with_water.str[2].size() ? ":" : "", mat->hardens_with_water.str[2].c_str());
if (mat->powder_dye != -1) if (mat->powder_dye != -1)
c->con.print("\t[POWDER_DYE:%s]\n", world->raws.language.colors[mat->powder_dye]->id.c_str()); out.print("\t[POWDER_DYE:%s]\n", world->raws.language.colors[mat->powder_dye]->id.c_str());
if (mat->soap_level != -0) if (mat->soap_level != -0)
c->con.print("\t[SOAP_LEVEL:%o]\n", mat->soap_level); out.print("\t[SOAP_LEVEL:%o]\n", mat->soap_level);
for (int i = 0; i < mat->syndrome.size(); i++) for (int i = 0; i < mat->syndrome.size(); i++)
c->con.print("\t[SYNDROME] ...\n"); out.print("\t[SYNDROME] ...\n");
} }
return CR_OK; return CR_OK;
} }

@ -41,54 +41,54 @@ int changeLiquid (df::tile_liquid type)
return tiles; return tiles;
} }
command_result df_frozenlava (Core * c, vector <string> & parameters) command_result df_frozenlava (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size()) if (parameters.size())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
int tiles = changeLiquid(tile_liquid::Magma); int tiles = changeLiquid(tile_liquid::Magma);
if (tiles) if (tiles)
c->con.print("Changed %i tiles of ice into frozen lava.\n", tiles); out.print("Changed %i tiles of ice into frozen lava.\n", tiles);
return CR_OK; return CR_OK;
} }
command_result df_frozenwater (Core * c, vector <string> & parameters) command_result df_frozenwater (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size()) if (parameters.size())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
int tiles = changeLiquid(tile_liquid::Water); int tiles = changeLiquid(tile_liquid::Water);
if (tiles) if (tiles)
c->con.print("Changed %i tiles of ice into frozen water.\n", tiles); out.print("Changed %i tiles of ice into frozen water.\n", tiles);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("frozen"); DFHACK_PLUGIN("frozen");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("frozenlava", "Changes all ice into frozen magma.", df_frozenlava)); commands.push_back(PluginCommand("frozenlava", "Changes all ice into frozen magma.", df_frozenlava));
commands.push_back(PluginCommand("frozenwater", "Changes all ice into frozen water.", df_frozenwater)); commands.push_back(PluginCommand("frozenwater", "Changes all ice into frozen water.", df_frozenwater));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -27,16 +27,16 @@ int32_t last_mouse[2] = {-1, -1};
uint32_t last_menu = 0; uint32_t last_menu = 0;
uint64_t timeLast = 0; uint64_t timeLast = 0;
command_result kittens (Core * c, vector <string> & parameters); command_result kittens (color_ostream &out, vector <string> & parameters);
command_result ktimer (Core * c, vector <string> & parameters); command_result ktimer (color_ostream &out, vector <string> & parameters);
command_result trackmenu (Core * c, vector <string> & parameters); command_result trackmenu (color_ostream &out, vector <string> & parameters);
command_result trackpos (Core * c, vector <string> & parameters); command_result trackpos (color_ostream &out, vector <string> & parameters);
command_result colormods (Core * c, vector <string> & parameters); command_result colormods (color_ostream &out, vector <string> & parameters);
command_result zoom (Core * c, vector <string> & parameters); command_result zoom (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("kittens"); DFHACK_PLUGIN("kittens");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens, true)); commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens, true));
commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag (toggle).",ktimer)); commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag (toggle).",ktimer));
@ -47,17 +47,17 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
shutdown_flag = true; shutdown_flag = true;
while(!final_flag) while(!final_flag)
{ {
c->con.msleep(60); Core::getInstance().getConsole().msleep(60);
} }
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
if(timering == true) if(timering == true)
{ {
@ -66,14 +66,14 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
uint64_t delta = time2-timeLast; uint64_t delta = time2-timeLast;
// harmless potential data race here... // harmless potential data race here...
timeLast = time2; timeLast = time2;
c->con.print("Time delta = %d ms\n", delta); out.print("Time delta = %d ms\n", delta);
} }
if(trackmenu_flg) if(trackmenu_flg)
{ {
if (last_menu != df::global::ui->main.mode) if (last_menu != df::global::ui->main.mode)
{ {
last_menu = df::global::ui->main.mode; last_menu = df::global::ui->main.mode;
c->con.print("Menu: %d\n",last_menu); out.print("Menu: %d\n",last_menu);
} }
} }
if(trackpos_flg) if(trackpos_flg)
@ -85,7 +85,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
last_designation[0] = desig_x; last_designation[0] = desig_x;
last_designation[1] = desig_y; last_designation[1] = desig_y;
last_designation[2] = desig_z; last_designation[2] = desig_z;
c->con.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z); out.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z);
} }
int mouse_x, mouse_y; int mouse_x, mouse_y;
Gui::getMousePos(mouse_x,mouse_y); Gui::getMousePos(mouse_x,mouse_y);
@ -93,13 +93,13 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
{ {
last_mouse[0] = mouse_x; last_mouse[0] = mouse_x;
last_mouse[1] = mouse_y; last_mouse[1] = mouse_y;
c->con.print("Mouse: %d %d\n",mouse_x, mouse_y); out.print("Mouse: %d %d\n",mouse_x, mouse_y);
} }
} }
return CR_OK; return CR_OK;
} }
command_result trackmenu (Core * c, vector <string> & parameters) command_result trackmenu (color_ostream &out, vector <string> & parameters)
{ {
if(trackmenu_flg) if(trackmenu_flg)
{ {
@ -112,42 +112,41 @@ command_result trackmenu (Core * c, vector <string> & parameters)
{ {
trackmenu_flg = true; trackmenu_flg = true;
last_menu = df::global::ui->main.mode; last_menu = df::global::ui->main.mode;
c->con.print("Menu: %d\n",last_menu); out.print("Menu: %d\n",last_menu);
return CR_OK; return CR_OK;
} }
else else
{ {
c->con.printerr("Can't read menu state\n"); out.printerr("Can't read menu state\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }
} }
command_result trackpos (Core * c, vector <string> & parameters) command_result trackpos (color_ostream &out, vector <string> & parameters)
{ {
trackpos_flg = !trackpos_flg; trackpos_flg = !trackpos_flg;
return CR_OK; return CR_OK;
} }
command_result colormods (Core * c, vector <string> & parameters) command_result colormods (color_ostream &out, vector <string> & parameters)
{ {
c->Suspend(); CoreSuspender suspend;
auto & vec = df::global::world->raws.creatures.alphabetic; auto & vec = df::global::world->raws.creatures.alphabetic;
for(int i = 0; i < vec.size();i++) for(int i = 0; i < vec.size();i++)
{ {
df::creature_raw* rawlion = vec[i]; df::creature_raw* rawlion = vec[i];
df::caste_raw * caste = rawlion->caste[0]; df::caste_raw * caste = rawlion->caste[0];
c->con.print("%s\nCaste addr 0x%x\n",rawlion->creature_id.c_str(), &caste->color_modifiers); out.print("%s\nCaste addr 0x%x\n",rawlion->creature_id.c_str(), &caste->color_modifiers);
for(int j = 0; j < caste->color_modifiers.size();j++) for(int j = 0; j < caste->color_modifiers.size();j++)
{ {
c->con.print("mod %d: 0x%x\n", j, caste->color_modifiers[j]); out.print("mod %d: 0x%x\n", j, caste->color_modifiers[j]);
} }
} }
c->Resume();
return CR_OK; return CR_OK;
} }
// FIXME: move cursor properly relative to view position // FIXME: move cursor properly relative to view position
command_result zoom (Core * c, vector <string> & parameters) command_result zoom (color_ostream &out, vector <string> & parameters)
{ {
if(parameters.size() < 3) if(parameters.size() < 3)
return CR_FAILURE; return CR_FAILURE;
@ -155,7 +154,7 @@ command_result zoom (Core * c, vector <string> & parameters)
int y = atoi( parameters[1].c_str()); int y = atoi( parameters[1].c_str());
int z = atoi( parameters[2].c_str()); int z = atoi( parameters[2].c_str());
int xi, yi, zi; int xi, yi, zi;
CoreSuspender cs (c); CoreSuspender cs;
if(Gui::getCursorCoords(xi, yi, zi)) if(Gui::getCursorCoords(xi, yi, zi))
{ {
Gui::setCursorCoords(x,y,z); Gui::setCursorCoords(x,y,z);
@ -163,7 +162,7 @@ command_result zoom (Core * c, vector <string> & parameters)
Gui::setViewCoords(x,y,z); Gui::setViewCoords(x,y,z);
} }
command_result ktimer (Core * c, vector <string> & parameters) command_result ktimer (color_ostream &out, vector <string> & parameters)
{ {
if(timering) if(timering)
{ {
@ -171,20 +170,22 @@ command_result ktimer (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
uint64_t timestart = GetTimeMs64(); uint64_t timestart = GetTimeMs64();
c->Suspend(); {
c->Resume(); CoreSuspender suspend;
}
uint64_t timeend = GetTimeMs64(); uint64_t timeend = GetTimeMs64();
c->con.print("Time to suspend = %d ms\n",timeend - timestart); out.print("Time to suspend = %d ms\n",timeend - timestart);
// harmless potential data race here... // harmless potential data race here...
timeLast = timeend; timeLast = timeend;
timering = true; timering = true;
return CR_OK; return CR_OK;
} }
command_result kittens (Core * c, vector <string> & parameters) command_result kittens (color_ostream &out, vector <string> & parameters)
{ {
final_flag = false; final_flag = false;
Console & con = c->con; assert(out.is_console());
Console &con = static_cast<Console&>(out);
// http://evilzone.org/creative-arts/nyan-cat-ascii/ // http://evilzone.org/creative-arts/nyan-cat-ascii/
const char * nyan []= const char * nyan []=
{ {

@ -28,11 +28,11 @@ enum HEXVIEW_STATES
{ {
STATE_OFF,STATE_ON STATE_OFF,STATE_ON
}; };
command_result memview (Core * c, vector <string> & parameters); command_result memview (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("memview"); DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview)); commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview));
memdata.state=STATE_OFF; memdata.state=STATE_OFF;
@ -58,15 +58,13 @@ bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
return false; return false;
} }
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,Core *c,vector<t_memrange> & ranges) void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector<t_memrange> & ranges)
{ {
Console &con=c->con;
const size_t page_size=16; const size_t page_size=16;
con.clear();
for(size_t i=0;i<len;i+=page_size) for(size_t i=0;i<len;i+=page_size)
{ {
con.gotoxy(1,i/page_size+1); //con.gotoxy(1,i/page_size+1);
con.print("0x%08X ",i+start); con.print("0x%08X ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++) for(size_t j=0;(j<page_size) && (i+j<len);j++)
{ {
@ -93,8 +91,6 @@ void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,Core *c,vector
//con.print("\n"); //con.print("\n");
} }
con.print("\n"); con.print("\n");
con.flush();
} }
void Deinit() void Deinit()
{ {
@ -105,7 +101,7 @@ void Deinit()
delete [] memdata.lbuf; delete [] memdata.lbuf;
} }
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate (color_ostream &out)
{ {
mymutex->lock(); mymutex->lock();
@ -114,7 +110,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
mymutex->unlock(); mymutex->unlock();
return CR_OK; return CR_OK;
} }
//Console &con=c->con; //Console &con=out;
uint64_t time2 = GetTimeMs64(); uint64_t time2 = GetTimeMs64();
uint64_t delta = time2-timeLast; uint64_t delta = time2-timeLast;
@ -126,8 +122,8 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
} }
timeLast = time2; timeLast = time2;
c->p->read(memdata.addr,memdata.len,memdata.buf); Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,c,memdata.ranges); outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges);
memcpy(memdata.lbuf, memdata.buf, memdata.len); memcpy(memdata.lbuf, memdata.buf, memdata.len);
if(memdata.refresh==0) if(memdata.refresh==0)
Deinit(); Deinit();
@ -135,10 +131,10 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
return CR_OK; return CR_OK;
} }
command_result memview (Core * c, vector <string> & parameters) command_result memview (color_ostream &out, vector <string> & parameters)
{ {
mymutex->lock(); mymutex->lock();
c->p->getMemRanges(memdata.ranges); Core::getInstance().p->getMemRanges(memdata.ranges);
memdata.addr=(void *)convert(parameters[0],true); memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0) if(memdata.addr==0)
{ {
@ -156,7 +152,7 @@ command_result memview (Core * c, vector <string> & parameters)
isValid=true; isValid=true;
if(!isValid) if(!isValid)
{ {
c->con.printerr("Invalid address:%x\n",memdata.addr); out.printerr("Invalid address:%x\n",memdata.addr);
mymutex->unlock(); mymutex->unlock();
return CR_OK; return CR_OK;
} }
@ -176,11 +172,11 @@ command_result memview (Core * c, vector <string> & parameters)
uint8_t *buf,*lbuf; uint8_t *buf,*lbuf;
memdata.buf=new uint8_t[memdata.len]; memdata.buf=new uint8_t[memdata.len];
memdata.lbuf=new uint8_t[memdata.len]; memdata.lbuf=new uint8_t[memdata.len];
c->p->getMemRanges(memdata.ranges); Core::getInstance().p->getMemRanges(memdata.ranges);
mymutex->unlock(); mymutex->unlock();
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown (color_ostream &out)
{ {
mymutex->lock(); mymutex->lock();
Deinit(); Deinit();

@ -10,11 +10,11 @@ using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
command_result df_notes (Core * c, vector <string> & parameters); command_result df_notes (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("notes"); DFHACK_PLUGIN("notes");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("dumpnotes", commands.push_back(PluginCommand("dumpnotes",
"Dumps in-game notes", "Dumps in-game notes",
@ -22,30 +22,27 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result df_notes (Core * c, vector <string> & parameters) command_result df_notes (color_ostream &con, vector <string> & parameters)
{ {
Console & con = c->con; CoreSuspender suspend;
c->Suspend();
DFHack::Notes * note_mod = c->getNotes(); DFHack::Notes * note_mod = Core::getInstance().getNotes();
std::vector<t_note*>* note_list = note_mod->notes; std::vector<t_note*>* note_list = note_mod->notes;
if (note_list == NULL) if (note_list == NULL)
{ {
con.printerr("Notes are not supported under this version of DF.\n"); con.printerr("Notes are not supported under this version of DF.\n");
c->Resume();
return CR_OK; return CR_OK;
} }
if (note_list->empty()) if (note_list->empty())
{ {
con << "There are no notes." << std::endl; con << "There are no notes." << std::endl;
c->Resume();
return CR_OK; return CR_OK;
} }
@ -71,6 +68,5 @@ command_result df_notes (Core * c, vector <string> & parameters)
con << std::endl; con << std::endl;
} }
c->Resume();
return CR_OK; return CR_OK;
} }

@ -17,12 +17,12 @@ using namespace DFHack;
using df::global::world; using df::global::world;
command_result df_regrass (Core * c, vector <string> & parameters) command_result df_regrass (color_ostream &out, vector <string> & parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
int count = 0; int count = 0;
for (size_t i = 0; i < world->map.map_blocks.size(); i++) for (size_t i = 0; i < world->map.map_blocks.size(); i++)
@ -48,20 +48,20 @@ command_result df_regrass (Core * c, vector <string> & parameters)
} }
if (count) if (count)
c->con.print("Regrew %d tiles of grass.\n", count); out.print("Regrew %d tiles of grass.\n", count);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("regrass"); DFHACK_PLUGIN("regrass");
DFhackCExport command_result plugin_init (Core *c, std::vector<PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass)); commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -18,13 +18,13 @@ using df::global::world;
// Here go all the command declarations... // Here go all the command declarations...
// mostly to allow having the mandatory stuff on top of the file and commands on the bottom // mostly to allow having the mandatory stuff on top of the file and commands on the bottom
command_result tilesieve (Core * c, std::vector <std::string> & parameters); command_result tilesieve (color_ostream &out, std::vector <std::string> & parameters);
// A plugin must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll // A plugin must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll
DFHACK_PLUGIN("tilesieve"); DFHACK_PLUGIN("tilesieve");
// Mandatory init function. If you have some global state, create it here. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -37,7 +37,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
} }
// This is called right before the plugin library is removed from memory. // This is called right before the plugin library is removed from memory.
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -48,16 +48,16 @@ struct xyz
int z; int z;
}; };
command_result tilesieve(DFHack::Core * c, std::vector<std::string> & params) command_result tilesieve(color_ostream &out, std::vector<std::string> & params)
{ {
Console & con = c->con; CoreSuspender suspend;
CoreSuspender suspend(c);
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
c->con.print("Scanning.\n"); out.print("Scanning.\n");
std::set <df::tiletype> seen; std::set <df::tiletype> seen;
for (auto iter = world->map.map_blocks.begin(); iter != world->map.map_blocks.end(); iter++) for (auto iter = world->map.map_blocks.begin(); iter != world->map.map_blocks.end(); iter++)
{ {
@ -75,7 +75,7 @@ command_result tilesieve(DFHack::Core * c, std::vector<std::string> & params)
if(seen.count(tt)) if(seen.count(tt))
continue; continue;
seen.insert(tt); seen.insert(tt);
c->con.print("Found tile %x @ %d %d %d\n", tt, block->map_pos.x + x, block->map_pos.y + y, block->map_pos.z); out.print("Found tile %x @ %d %d %d\n", tt, block->map_pos.x + x, block->map_pos.y + y, block->map_pos.z);
} }
} }
return CR_OK; return CR_OK;

@ -24,14 +24,12 @@ struct t_vecTriplet
void * alloc_end; void * alloc_end;
}; };
command_result df_vectors (Core * c, command_result df_vectors (color_ostream &out, vector <string> & parameters);
vector <string> & parameters); command_result df_clearvec (color_ostream &out, vector <string> & parameters);
command_result df_clearvec (Core * c,
vector <string> & parameters);
DFHACK_PLUGIN("vectors"); DFHACK_PLUGIN("vectors");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("vectors", commands.push_back(PluginCommand("vectors",
"Scan memory for vectors.\ "Scan memory for vectors.\
@ -45,7 +43,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -94,11 +92,11 @@ static bool inAnyRange(vector<t_memrange> &ranges, void * ptr)
return false; return false;
} }
static bool getHeapRanges(Core * c, std::vector<t_memrange> &heap_ranges) static bool getHeapRanges(color_ostream &out, std::vector<t_memrange> &heap_ranges)
{ {
std::vector<t_memrange> ranges; std::vector<t_memrange> ranges;
c->p->getMemRanges(ranges); Core::getInstance().p->getMemRanges(ranges);
for (size_t i = 0; i < ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
@ -116,7 +114,7 @@ static bool getHeapRanges(Core * c, std::vector<t_memrange> &heap_ranges)
if (heap_ranges.empty()) if (heap_ranges.empty())
{ {
c->con << "No possible heap segments." << std::endl; out << "No possible heap segments." << std::endl;
return false; return false;
} }
@ -127,13 +125,13 @@ static bool getHeapRanges(Core * c, std::vector<t_memrange> &heap_ranges)
// COMMAND: vectors // COMMAND: vectors
//////////////////////////////////////// ////////////////////////////////////////
static void vectorsUsage(Console &con) static void vectorsUsage(color_ostream &con)
{ {
con << "Usage: vectors <start of scan address> <# bytes to scan>" con << "Usage: vectors <start of scan address> <# bytes to scan>"
<< std::endl; << std::endl;
} }
static void printVec(Console &con, const char* msg, t_vecTriplet *vec, static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec,
uint32_t start, uint32_t pos) uint32_t start, uint32_t pos)
{ {
uint32_t length = (int)vec->end - (int)vec->start; uint32_t length = (int)vec->end - (int)vec->start;
@ -143,10 +141,8 @@ static void printVec(Console &con, const char* msg, t_vecTriplet *vec,
msg, offset, pos, vec->start, length); msg, offset, pos, vec->start, length);
} }
command_result df_vectors (Core * c, vector <string> & parameters) command_result df_vectors (color_ostream &con, vector <string> & parameters)
{ {
Console & con = c->con;
if (parameters.size() != 2) if (parameters.size() != 2)
{ {
vectorsUsage(con); vectorsUsage(con);
@ -173,14 +169,13 @@ command_result df_vectors (Core * c, vector <string> & parameters)
while (start % 4 != 0) while (start % 4 != 0)
start++; start++;
c->Suspend(); CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> heap_ranges;
if (!getHeapRanges(c, heap_ranges)) if (!getHeapRanges(con, heap_ranges))
{ {
return CR_FAILURE; return CR_FAILURE;
c->Resume();
} }
bool startInRange = false; bool startInRange = false;
@ -208,7 +203,6 @@ command_result df_vectors (Core * c, vector <string> & parameters)
if (!startInRange) if (!startInRange)
{ {
con << "Address not in any memory range." << std::endl; con << "Address not in any memory range." << std::endl;
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
@ -250,7 +244,6 @@ command_result df_vectors (Core * c, vector <string> & parameters)
} }
} // for (uint32_t pos = start; pos < end; pos += ptr_size) } // for (uint32_t pos = start; pos < end; pos += ptr_size)
c->Resume();
return CR_OK; return CR_OK;
} }
@ -258,17 +251,15 @@ command_result df_vectors (Core * c, vector <string> & parameters)
// COMMAND: clearvec // COMMAND: clearvec
//////////////////////////////////////// ////////////////////////////////////////
static void clearUsage(Console &con) static void clearUsage(color_ostream &con)
{ {
con << "Usage: clearvec <vector1 addr> [vector2 addr] ..." << std::endl; con << "Usage: clearvec <vector1 addr> [vector2 addr] ..." << std::endl;
con << "Address can be either for vector or pointer to vector." con << "Address can be either for vector or pointer to vector."
<< std::endl; << std::endl;
} }
command_result df_clearvec (Core * c, vector <string> & parameters) command_result df_clearvec (color_ostream &con, vector <string> & parameters)
{ {
Console & con = c->con;
if (parameters.size() == 0) if (parameters.size() == 0)
{ {
clearUsage(con); clearUsage(con);
@ -289,13 +280,12 @@ command_result df_clearvec (Core * c, vector <string> & parameters)
return CR_FAILURE; return CR_FAILURE;
} }
c->Suspend(); CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> heap_ranges;
if (!getHeapRanges(c, heap_ranges)) if (!getHeapRanges(con, heap_ranges))
{ {
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
@ -356,6 +346,5 @@ command_result df_clearvec (Core * c, vector <string> & parameters)
con << addr_str << " set to zero length." << std::endl; con << addr_str << " set to zero length." << std::endl;
} // for (size_t i = 0; i < parameters.size(); i++) } // for (size_t i = 0; i < parameters.size(); i++)
c->Resume();
return CR_OK; return CR_OK;
} }

@ -1 +1 @@
Subproject commit f149da6efead3c46845d7478d1ff3d11119c589d Subproject commit 964026395ce2138e4f861594307efda50b17e96c

@ -19,12 +19,12 @@ using df::global::world;
DFHACK_PLUGIN("drybuckets"); DFHACK_PLUGIN("drybuckets");
command_result df_drybuckets (Core * c, vector <string> & parameters) command_result df_drybuckets (color_ostream &out, vector <string> & parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
int dried_total = 0; int dried_total = 0;
for (size_t i = 0; i < world->items.all.size(); i++) for (size_t i = 0; i < world->items.all.size(); i++)
@ -37,17 +37,17 @@ command_result df_drybuckets (Core * c, vector <string> & parameters)
} }
} }
if (dried_total) if (dried_total)
c->con.print("Done. %d buckets of water marked for emptying.\n", dried_total); out.print("Done. %d buckets of water marked for emptying.\n", dried_total);
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("drybuckets", "Removes water from buckets.", df_drybuckets)); commands.push_back(PluginCommand("drybuckets", "Removes water from buckets.", df_drybuckets));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -18,6 +18,8 @@ using namespace std;
#include <df/world.h> #include <df/world.h>
#include <df/unit.h> #include <df/unit.h>
#include <df/unit_soul.h> #include <df/unit_soul.h>
#include <df/unit_labor.h>
#include <df/unit_skill.h>
using namespace DFHack; using namespace DFHack;
using df::global::ui; using df::global::ui;
@ -30,12 +32,12 @@ using df::global::world;
// Here go all the command declarations... // Here go all the command declarations...
// mostly to allow having the mandatory stuff on top of the file and commands on the bottom // mostly to allow having the mandatory stuff on top of the file and commands on the bottom
command_result export_dwarves (Core * c, std::vector <std::string> & parameters); command_result export_dwarves (color_ostream &con, std::vector <std::string> & parameters);
DFHACK_PLUGIN("dwarfexport"); DFHACK_PLUGIN("dwarfexport");
// Mandatory init function. If you have some global state, create it here. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &con, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.push_back(PluginCommand("dwarfexport", commands.push_back(PluginCommand("dwarfexport",
@ -46,7 +48,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
} }
// This is called right before the plugin library is removed from memory. // This is called right before the plugin library is removed from memory.
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown (color_ostream &con)
{ {
return CR_OK; return CR_OK;
} }
@ -84,7 +86,7 @@ static void element(const char* name, const uint32_t content, ostream& out, cons
out << extra_indent << " <" << name << ">" << content << "</" << name << ">" << endl; out << extra_indent << " <" << name << ">" << content << "</" << name << ">" << endl;
} }
static void printAttributes(Core* c, df::unit* cre, ostream& out) { static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) {
out << " <Attributes>" << endl; out << " <Attributes>" << endl;
for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) { for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) {
element(physicals[i], cre->body.physical_attrs[i].unk1, out, " "); element(physicals[i], cre->body.physical_attrs[i].unk1, out, " ");
@ -99,7 +101,7 @@ static void printAttributes(Core* c, df::unit* cre, ostream& out) {
out << " </Attributes>" << endl; out << " </Attributes>" << endl;
} }
static void printTraits(Core* c, df::unit* cre, ostream& out) static void printTraits(color_ostream &con, df::unit* cre, ostream& out)
{ {
out << " <Traits>" << endl; out << " <Traits>" << endl;
@ -112,7 +114,7 @@ static void printTraits(Core* c, df::unit* cre, ostream& out)
"' value='" << s->traits[index] << "'>"; "' value='" << s->traits[index] << "'>";
//FIXME: needs reimplementing trait string generation //FIXME: needs reimplementing trait string generation
/* /*
string trait = c->vinfo->getTrait(i, s->traits[i]); string trait = con->vinfo->getTrait(i, s->traits[i]);
if (!trait.empty()) { if (!trait.empty()) {
out << trait.c_str(); out << trait.c_str();
} }
@ -124,46 +126,101 @@ static void printTraits(Core* c, df::unit* cre, ostream& out)
out << " </Traits>" << endl; out << " </Traits>" << endl;
} }
static int32_t getCreatureAge(df::unit* cre)
{
int32_t yearDifference = *df::global::cur_year - cre->relations.birth_year;
// If the birthday this year has not yet passed, subtract one year.
// ASSUMPTION: birth_time is on the same scale as cur_year_tick
if (cre->relations.birth_time >= *df::global::cur_year_tick) {
yearDifference--;
}
return yearDifference;
}
static void printLabors(color_ostream &con, df::unit* cre, ostream& out)
{
// Using British spelling here, consistent with Runesmith
out << " <Labours>" << endl;
for (int iCount = 0; iCount < sizeof(cre->status.labors); iCount++)
{
if (cre->status.labors[iCount]) {
// Get the caption for the labor index.
df::enums::unit_labor::unit_labor thisLabor = (df::enums::unit_labor::unit_labor)iCount;
element("Labour", get_caption(thisLabor), out);
}
}
out << " </Labours>" << endl;
}
static void printSkill(color_ostream &con, df::unit_skill* skill, ostream& out)
{
out << " <Skill>" << endl;
element("Name", get_caption(skill->id), out);
element("Level", skill->rating, out);
out << " </Skill>" << endl;
}
static void printSkills(color_ostream &con, df::unit* cre, ostream& out)
{
std::vector<df::unit_skill* > vSkills = cre->status.current_soul->skills;
out << " <Skills>" << endl;
for (int iCount = 0; iCount < vSkills.size(); iCount++)
{
printSkill(con, vSkills.at(iCount), out);
}
out << " </Skills>" << endl;
}
// GDC needs: // GDC needs:
// Name // Name
// Nickname // Nickname
// Sex // Sex
// Attributes // Attributes
// Traits // Traits
static void export_dwarf(Core* c, df::unit* cre, ostream& out) { static void export_dwarf(color_ostream &con, df::unit* cre, ostream& out) {
string info = cre->name.first_name; string info = cre->name.first_name;
info += " "; info += " ";
info += Translation::TranslateName(&cre->name, false); info += Translation::TranslateName(&cre->name, false);
info[0] = toupper(info[0]); info[0] = toupper(info[0]);
c->con.print("Exporting %s\n", info.c_str()); con.print("Exporting %s\n", info.c_str());
out << " <Creature>" << endl; out << " <Creature>" << endl;
element("Name", info.c_str(), out); element("Name", info.c_str(), out);
element("Nickname", cre->name.nickname.c_str(), out); element("Nickname", cre->name.nickname.c_str(), out);
element("Sex", cre->sex == 0 ? "Female" : "Male", out); element("Sex", cre->sex == 0 ? "Female" : "Male", out);
printAttributes(c, cre, out); element("Age", getCreatureAge(cre), out); // Added age, active labors, and skills March 9, 2012
printTraits(c, cre, out); printAttributes(con, cre, out);
printTraits(con, cre, out);
printLabors(con, cre, out);
printSkills(con, cre, out);
out << " </Creature>" << endl; out << " </Creature>" << endl;
} }
command_result export_dwarves (Core * c, std::vector <std::string> & parameters) command_result export_dwarves (color_ostream &con, std::vector <std::string> & parameters)
{ {
string filename; string filename;
if (parameters.size() == 1) { if (parameters.size() == 1) {
filename = parameters[0]; filename = parameters[0];
} else { } else {
c->con.print("export <filename>\n"); con.print("export <filename>\n");
return CR_OK; return CR_OK;
} }
ofstream outf(filename); ofstream outf(filename);
if (!outf) { if (!outf) {
c->con.printerr("Failed to open file %s\n", filename.c_str()); con.printerr("Failed to open file %s\n", filename.c_str());
return CR_FAILURE; return CR_FAILURE;
} }
c->Suspend(); CoreSuspender suspend;
uint32_t race = ui->race_id; uint32_t race = ui->race_id;
uint32_t civ = ui->civ_id; uint32_t civ = ui->civ_id;
@ -174,11 +231,10 @@ command_result export_dwarves (Core * c, std::vector <std::string> & parameters)
{ {
df::unit* cre = world->units.all[i]; df::unit* cre = world->units.all[i];
if (cre->race == race && cre->civ_id == civ) { if (cre->race == race && cre->civ_id == civ) {
export_dwarf(c, cre, outf); export_dwarf(con, cre, outf);
} }
} }
outf << "</Creatures>" << endl; outf << "</Creatures>" << endl;
c->Resume();
return CR_OK; return CR_OK;
} }

@ -18,14 +18,14 @@ using df::global::ui;
// dfhack interface // dfhack interface
DFHACK_PLUGIN("fastdwarf"); DFHACK_PLUGIN("fastdwarf");
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
static int enable_fastdwarf; static int enable_fastdwarf;
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
if (!enable_fastdwarf) if (!enable_fastdwarf)
return CR_OK; return CR_OK;
@ -43,7 +43,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
return CR_OK; return CR_OK;
} }
static command_result fastdwarf (Core * c, vector <string> & parameters) static command_result fastdwarf (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1")) if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1"))
{ {
@ -51,11 +51,11 @@ static command_result fastdwarf (Core * c, vector <string> & parameters)
enable_fastdwarf = 0; enable_fastdwarf = 0;
else else
enable_fastdwarf = 1; enable_fastdwarf = 1;
c->con.print("fastdwarf %sactivated.\n", (enable_fastdwarf ? "" : "de")); out.print("fastdwarf %sactivated.\n", (enable_fastdwarf ? "" : "de"));
} }
else else
{ {
c->con.print("Makes your minions move at ludicrous speeds.\n" out.print("Makes your minions move at ludicrous speeds.\n"
"Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n" "Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n"
"Current state: %d.\n", enable_fastdwarf); "Current state: %d.\n", enable_fastdwarf);
} }
@ -63,7 +63,7 @@ static command_result fastdwarf (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("fastdwarf", commands.push_back(PluginCommand("fastdwarf",
"enable/disable fastdwarf (parameter=0/1)", "enable/disable fastdwarf (parameter=0/1)",

@ -21,13 +21,13 @@ using namespace df::enums;
typedef void (*checkTile)(DFCoord, MapExtras::MapCache &); typedef void (*checkTile)(DFCoord, MapExtras::MapCache &);
//Forward Declarations for Commands //Forward Declarations for Commands
command_result filltraffic(Core * c, std::vector<std::string> & params); command_result filltraffic(color_ostream &out, std::vector<std::string> & params);
command_result alltraffic(Core * c, std::vector<std::string> & params); command_result alltraffic(color_ostream &out, std::vector<std::string> & params);
//Forward Declarations for Utility Functions //Forward Declarations for Utility Functions
command_result setAllMatching(Core * c, checkTile checkProc, command_result setAllMatching(color_ostream &out, checkTile checkProc,
DFCoord minCoord = DFCoord(0, 0, 0), DFCoord minCoord = DFCoord(0, 0, 0),
DFCoord maxCoord = DFCoord(0xFFFF, 0xFFFF, 0xFFFF)); DFCoord maxCoord = DFCoord(0xFFFF, 0xFFFF, 0xFFFF));
void allHigh(DFCoord coord, MapExtras::MapCache & map); void allHigh(DFCoord coord, MapExtras::MapCache & map);
void allNormal(DFCoord coord, MapExtras::MapCache & map); void allNormal(DFCoord coord, MapExtras::MapCache & map);
@ -36,7 +36,7 @@ void allRestricted(DFCoord coord, MapExtras::MapCache & map);
DFHACK_PLUGIN("filltraffic"); DFHACK_PLUGIN("filltraffic");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"filltraffic","Flood-fill with selected traffic designation from cursor", "filltraffic","Flood-fill with selected traffic designation from cursor",
@ -69,12 +69,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result filltraffic(Core * c, std::vector<std::string> & params) command_result filltraffic(color_ostream &out, std::vector<std::string> & params)
{ {
// HOTKEY COMMAND; CORE ALREADY SUSPENDED // HOTKEY COMMAND; CORE ALREADY SUSPENDED
@ -117,7 +117,7 @@ command_result filltraffic(Core * c, std::vector<std::string> & params)
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -128,7 +128,7 @@ command_result filltraffic(Core * c, std::vector<std::string> & params)
Gui::getCursorCoords(cx,cy,cz); Gui::getCursorCoords(cx,cy,cz);
while(cx == -30000) while(cx == -30000)
{ {
c->con.printerr("Cursor is not active.\n"); out.printerr("Cursor is not active.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -145,29 +145,29 @@ command_result filltraffic(Core * c, std::vector<std::string> & params)
source = (df::tile_traffic)des.bits.traffic; source = (df::tile_traffic)des.bits.traffic;
if(source == target) if(source == target)
{ {
c->con.printerr("This tile is already set to the target traffic type.\n"); out.printerr("This tile is already set to the target traffic type.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if(isWallTerrain(tt)) if(isWallTerrain(tt))
{ {
c->con.printerr("This tile is a wall. Please select a passable tile.\n"); out.printerr("This tile is a wall. Please select a passable tile.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if(checkpit && isOpenTerrain(tt)) if(checkpit && isOpenTerrain(tt))
{ {
c->con.printerr("This tile is a hole. Please select a passable tile.\n"); out.printerr("This tile is a hole. Please select a passable tile.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if(checkbuilding && oc.bits.building) if(checkbuilding && oc.bits.building)
{ {
c->con.printerr("This tile contains a building. Please select an empty tile.\n"); out.printerr("This tile contains a building. Please select an empty tile.\n");
return CR_FAILURE; return CR_FAILURE;
} }
c->con.print("%d/%d/%d ... FILLING!\n", cx,cy,cz); out.print("%d/%d/%d ... FILLING!\n", cx,cy,cz);
//Naive four-way or six-way flood fill with possible tiles on a stack. //Naive four-way or six-way flood fill with possible tiles on a stack.
stack <DFCoord> flood; stack <DFCoord> flood;
@ -236,7 +236,7 @@ command_result filltraffic(Core * c, std::vector<std::string> & params)
enum e_checktype {no_check, check_equal, check_nequal}; enum e_checktype {no_check, check_equal, check_nequal};
command_result alltraffic(Core * c, std::vector<std::string> & params) command_result alltraffic(color_ostream &out, std::vector<std::string> & params)
{ {
void (*proc)(DFCoord, MapExtras::MapCache &) = allNormal; void (*proc)(DFCoord, MapExtras::MapCache &) = allNormal;
@ -262,22 +262,22 @@ command_result alltraffic(Core * c, std::vector<std::string> & params)
} }
} }
return setAllMatching(c, proc); return setAllMatching(out, proc);
} }
//Helper function for writing new functions that check every tile on the map. //Helper function for writing new functions that check every tile on the map.
//newTraffic is the traffic designation to set. //newTraffic is the traffic designation to set.
//check takes a coordinate and the map cache as arguments, and returns true if the criteria is met. //check takes a coordinate and the map cache as arguments, and returns true if the criteria is met.
//minCoord and maxCoord can be used to specify a bounding cube. //minCoord and maxCoord can be used to specify a bounding cube.
command_result setAllMatching(Core * c, checkTile checkProc, command_result setAllMatching(color_ostream &out, checkTile checkProc,
DFCoord minCoord, DFCoord maxCoord) DFCoord minCoord, DFCoord maxCoord)
{ {
//Initialization. //Initialization.
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -295,23 +295,23 @@ command_result setAllMatching(Core * c, checkTile checkProc,
//Check minimum co-ordinates against maximum map size //Check minimum co-ordinates against maximum map size
if (minCoord.x > maxCoord.x) if (minCoord.x > maxCoord.x)
{ {
c->con.printerr("Minimum x coordinate is greater than maximum x coordinate.\n"); out.printerr("Minimum x coordinate is greater than maximum x coordinate.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (minCoord.y > maxCoord.y) if (minCoord.y > maxCoord.y)
{ {
c->con.printerr("Minimum y coordinate is greater than maximum y coordinate.\n"); out.printerr("Minimum y coordinate is greater than maximum y coordinate.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (minCoord.z > maxCoord.y) if (minCoord.z > maxCoord.y)
{ {
c->con.printerr("Minimum z coordinate is greater than maximum z coordinate.\n"); out.printerr("Minimum z coordinate is greater than maximum z coordinate.\n");
return CR_FAILURE; return CR_FAILURE;
} }
MapExtras::MapCache MCache; MapExtras::MapCache MCache;
c->con.print("Setting traffic...\n"); out.print("Setting traffic...\n");
//Loop through every single tile //Loop through every single tile
for(uint32_t x = minCoord.x; x <= maxCoord.x; x++) for(uint32_t x = minCoord.x; x <= maxCoord.x; x++)
@ -327,7 +327,7 @@ command_result setAllMatching(Core * c, checkTile checkProc,
} }
MCache.WriteAll(); MCache.WriteAll();
c->con.print("Complete!\n"); out.print("Complete!\n");
return CR_OK; return CR_OK;
} }

@ -20,12 +20,13 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_fixdiplomats (Core *c, vector<string> &parameters) command_result df_fixdiplomats (color_ostream &out, vector<string> &parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
int checked = 0, fixed = 0; int checked = 0, fixed = 0;
for (int i = 0; i < world->entities.all.size(); i++) for (int i = 0; i < world->entities.all.size(); i++)
{ {
@ -120,16 +121,17 @@ command_result df_fixdiplomats (Core *c, vector<string> &parameters)
if (update || assign) if (update || assign)
fixed++; fixed++;
} }
c->con.print("Fixed %d of %d civilizations to enable tree cap diplomacy.\n", fixed, checked); out.print("Fixed %d of %d civilizations to enable tree cap diplomacy.\n", fixed, checked);
return CR_OK; return CR_OK;
} }
command_result df_fixmerchants (Core *c, vector<string> &parameters) command_result df_fixmerchants (color_ostream &out, vector<string> &parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
int checked = 0, fixed = 0; int checked = 0, fixed = 0;
for (int i = 0; i < world->entities.all.size(); i++) for (int i = 0; i < world->entities.all.size(); i++)
{ {
@ -220,13 +222,13 @@ command_result df_fixmerchants (Core *c, vector<string> &parameters)
if (update || assign) if (update || assign)
fixed++; fixed++;
} }
c->con.print("Fixed %d of %d civilizations to enable merchant nobility.\n", fixed, checked); out.print("Fixed %d of %d civilizations to enable merchant nobility.\n", fixed, checked);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("fixpositions"); DFHACK_PLUGIN("fixpositions");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"fixdiplomats", "Add Diplomat position to Elven civilizations for tree cap diplomacy.", "fixdiplomats", "Add Diplomat position to Elven civilizations for tree cap diplomacy.",
@ -237,7 +239,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -34,16 +34,16 @@ bool setTileMaterial(df::tiletype &tile, const df::tiletype_material mat)
return false; return false;
} }
command_result df_fixveins (Core * c, vector <string> & parameters) command_result df_fixveins (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size()) if (parameters.size())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -90,15 +90,15 @@ command_result df_fixveins (Core * c, vector <string> & parameters)
} }
} }
if (mineral_removed || feature_removed) if (mineral_removed || feature_removed)
c->con.print("Removed invalid references from %i mineral inclusion and %i map feature tiles.\n", mineral_removed, feature_removed); out.print("Removed invalid references from %i mineral inclusion and %i map feature tiles.\n", mineral_removed, feature_removed);
if (mineral_added || feature_added) if (mineral_added || feature_added)
c->con.print("Restored missing references to %i mineral inclusion and %i map feature tiles.\n", mineral_added, feature_added); out.print("Restored missing references to %i mineral inclusion and %i map feature tiles.\n", mineral_added, feature_added);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("fixveins"); DFHACK_PLUGIN("fixveins");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("fixveins", commands.push_back(PluginCommand("fixveins",
"Remove invalid references to mineral inclusions and restore missing ones.", "Remove invalid references to mineral inclusions and restore missing ones.",
@ -106,7 +106,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -17,12 +17,12 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_flows (Core * c, vector <string> & parameters) command_result df_flows (color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
int flow1 = 0, flow2 = 0, flowboth = 0, water = 0, magma = 0; int flow1 = 0, flow2 = 0, flowboth = 0, water = 0, magma = 0;
c->con.print("Counting flows and liquids ...\n"); out.print("Counting flows and liquids ...\n");
for (size_t i = 0; i < world->map.map_blocks.size(); i++) for (size_t i = 0; i < world->map.map_blocks.size(); i++)
{ {
@ -48,17 +48,17 @@ command_result df_flows (Core * c, vector <string> & parameters)
} }
} }
c->con.print("Blocks with liquid_1=true: %d\n", flow1); out.print("Blocks with liquid_1=true: %d\n", flow1);
c->con.print("Blocks with liquid_2=true: %d\n", flow2); out.print("Blocks with liquid_2=true: %d\n", flow2);
c->con.print("Blocks with both: %d\n", flowboth); out.print("Blocks with both: %d\n", flowboth);
c->con.print("Water tiles: %d\n", water); out.print("Water tiles: %d\n", water);
c->con.print("Magma tiles: %d\n", magma); out.print("Magma tiles: %d\n", magma);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("flows"); DFHACK_PLUGIN("flows");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("flows", commands.push_back(PluginCommand("flows",
"Counts map blocks with flowing liquids.", "Counts map blocks with flowing liquids.",
@ -66,7 +66,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -17,7 +17,7 @@ using namespace DFHack;
using namespace df::enums; using namespace df::enums;
command_result follow (Core * c, std::vector <std::string> & parameters); command_result follow (color_ostream &out, std::vector <std::string> & parameters);
df::unit *followedUnit; df::unit *followedUnit;
int32_t prevX, prevY, prevZ; int32_t prevX, prevY, prevZ;
@ -25,12 +25,13 @@ uint8_t prevMenuWidth;
DFHACK_PLUGIN("follow"); DFHACK_PLUGIN("follow");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"follow", "Follow the selected unit until camera control is released", "follow", "Follow the selected unit until camera control is released",
follow, Gui::view_unit_hotkey, follow, Gui::view_unit_hotkey,
" Select a unit and run this plugin to make the camera follow it. Moving the camera yourself deactivates the plugin.\n" " Select a unit and run this plugin to make the camera follow it.\n"
" Moving the camera yourself deactivates the plugin.\n"
)); ));
followedUnit = 0; followedUnit = 0;
prevX=prevY=prevZ = -1; prevX=prevY=prevZ = -1;
@ -39,12 +40,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_LOADED: case SC_GAME_LOADED:
@ -60,11 +61,11 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
if (!followedUnit) return CR_OK; //Don't do anything if we're not following a unit if (!followedUnit) return CR_OK; //Don't do anything if we're not following a unit
DFHack::World *world =c->getWorld(); DFHack::World *world = Core::getInstance().getWorld();
if (world->ReadPauseState() && prevX==-1) return CR_OK; //Wait until the game is unpaused after first running "follow" to begin following if (world->ReadPauseState() && prevX==-1) return CR_OK; //Wait until the game is unpaused after first running "follow" to begin following
df::coord &unitPos = followedUnit->pos; df::coord &unitPos = followedUnit->pos;
@ -100,7 +101,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
followedUnit = 0; followedUnit = 0;
prevX=prevY=prevZ = -1; prevX=prevY=prevZ = -1;
prevMenuWidth = 0; prevMenuWidth = 0;
c->con.print("No longer following anything.\n"); out.print("No longer following anything.\n");
return CR_OK; return CR_OK;
} }
@ -131,7 +132,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
return CR_OK; return CR_OK;
} }
command_result follow (Core * c, std::vector <std::string> & parameters) command_result follow (color_ostream &out, std::vector <std::string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
@ -140,17 +141,17 @@ command_result follow (Core * c, std::vector <std::string> & parameters)
if (followedUnit) if (followedUnit)
{ {
c->con.print("No longer following previously selected unit.\n"); out.print("No longer following previously selected unit.\n");
followedUnit = 0; followedUnit = 0;
} }
followedUnit = Gui::getSelectedUnit(c); followedUnit = Gui::getSelectedUnit(out);
if (followedUnit) if (followedUnit)
{ {
std::ostringstream ss; std::ostringstream ss;
ss << "Unpause to begin following " << df::global::world->raws.creatures.all[followedUnit->race]->name[0]; ss << "Unpause to begin following " << df::global::world->raws.creatures.all[followedUnit->race]->name[0];
if (followedUnit->name.has_name) ss << " " << followedUnit->name.first_name; if (followedUnit->name.has_name) ss << " " << followedUnit->name.first_name;
ss << ". Simply manually move the view to break the following.\n"; ss << ". Simply manually move the view to break the following.\n";
c->con.print(ss.str().c_str()); out.print(ss.str().c_str());
} }
else followedUnit = 0; else followedUnit = 0;
return CR_OK; return CR_OK;

@ -23,7 +23,7 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_getplants (Core * c, vector <string> & parameters) command_result df_getplants (color_ostream &out, vector <string> & parameters)
{ {
string plantMatStr = ""; string plantMatStr = "";
set<int> plantIDs; set<int> plantIDs;
@ -50,21 +50,21 @@ command_result df_getplants (Core * c, vector <string> & parameters)
} }
if (treesonly && shrubsonly) if (treesonly && shrubsonly)
{ {
c->con.printerr("Cannot specify both -t and -s at the same time!\n"); out.printerr("Cannot specify both -t and -s at the same time!\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
if (all && exclude) if (all && exclude)
{ {
c->con.printerr("Cannot specify both -a and -x at the same time!\n"); out.printerr("Cannot specify both -a and -x at the same time!\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
if (all && plantNames.size()) if (all && plantNames.size())
{ {
c->con.printerr("Cannot specify -a along with plant IDs!\n"); out.printerr("Cannot specify -a along with plant IDs!\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
for (size_t i = 0; i < world->raws.plants.all.size(); i++) for (size_t i = 0; i < world->raws.plants.all.size(); i++)
{ {
@ -79,22 +79,22 @@ command_result df_getplants (Core * c, vector <string> & parameters)
} }
if (plantNames.size() > 0) if (plantNames.size() > 0)
{ {
c->con.printerr("Invalid plant ID(s):"); out.printerr("Invalid plant ID(s):");
for (set<string>::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) for (set<string>::const_iterator it = plantNames.begin(); it != plantNames.end(); it++)
c->con.printerr(" %s", it->c_str()); out.printerr(" %s", it->c_str());
c->con.printerr("\n"); out.printerr("\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (plantIDs.size() == 0) if (plantIDs.size() == 0)
{ {
c->con.print("Valid plant IDs:\n"); out.print("Valid plant IDs:\n");
for (size_t i = 0; i < world->raws.plants.all.size(); i++) for (size_t i = 0; i < world->raws.plants.all.size(); i++)
{ {
df::plant_raw *plant = world->raws.plants.all[i]; df::plant_raw *plant = world->raws.plants.all[i];
if (plant->flags.is_set(plant_raw_flags::GRASS)) if (plant->flags.is_set(plant_raw_flags::GRASS))
continue; continue;
c->con.print("* (%s) %s - %s\n", plant->flags.is_set(plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); out.print("* (%s) %s - %s\n", plant->flags.is_set(plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str());
} }
return CR_OK; return CR_OK;
} }
@ -144,13 +144,13 @@ command_result df_getplants (Core * c, vector <string> & parameters)
cur->flags.bits.designated = true; cur->flags.bits.designated = true;
} }
if (count) if (count)
c->con.print("Updated %d plant designations.\n", count); out.print("Updated %d plant designations.\n", count);
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("getplants"); DFHACK_PLUGIN("getplants");
DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"getplants", "Cut down all of the specified trees or gather specified shrubs", "getplants", "Cut down all of the specified trees or gather specified shrubs",
@ -169,7 +169,7 @@ DFhackCExport command_result plugin_init ( Core * c, vector <PluginCommand> &com
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -14,12 +14,12 @@ using namespace df::enums;
using df::global::d_init; using df::global::d_init;
command_result twaterlvl(Core * c, vector <string> & parameters); command_result twaterlvl(color_ostream &out, vector <string> & parameters);
command_result tidlers(Core * c, vector <string> & parameters); command_result tidlers(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("initflags"); DFHACK_PLUGIN("initflags");
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
if (d_init) { if (d_init) {
commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.",
@ -31,23 +31,23 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result twaterlvl(Core * c, vector <string> & parameters) command_result twaterlvl(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS); d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS);
c->con << "Toggled the display of water/magma depth." << endl; out << "Toggled the display of water/magma depth." << endl;
return CR_OK; return CR_OK;
} }
command_result tidlers(Core * c, vector <string> & parameters) command_result tidlers(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers); d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers);
c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl; out << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl;
return CR_OK; return CR_OK;
} }

@ -39,15 +39,15 @@ using df::global::job_next_id;
/* Plugin registration */ /* Plugin registration */
static bool job_material_hotkey(Core *c, df::viewscreen *top); static bool job_material_hotkey(df::viewscreen *top);
static command_result job_material(Core *c, vector <string> & parameters); static command_result job_material(color_ostream &out, vector <string> & parameters);
static command_result job_duplicate(Core *c, vector <string> & parameters); static command_result job_duplicate(color_ostream &out, vector <string> & parameters);
static command_result job_cmd(Core *c, vector <string> & parameters); static command_result job_cmd(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("jobutils"); DFHACK_PLUGIN("jobutils");
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
if (!world || !ui) if (!world || !ui)
return CR_FAILURE; return CR_FAILURE;
@ -99,30 +99,30 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
/* UI state guards */ /* UI state guards */
static bool job_material_hotkey(Core *c, df::viewscreen *top) static bool job_material_hotkey(df::viewscreen *top)
{ {
return Gui::workshop_job_hotkey(c, top) || return Gui::workshop_job_hotkey(top) ||
Gui::build_selector_hotkey(c, top); Gui::build_selector_hotkey(top);
} }
/* job-material implementation */ /* job-material implementation */
static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) static command_result job_material_in_job(color_ostream &out, MaterialInfo &new_mat)
{ {
df::job *job = Gui::getSelectedWorkshopJob(c); df::job *job = Gui::getSelectedWorkshopJob(out);
if (!job) if (!job)
return CR_FAILURE; return CR_FAILURE;
if (!new_mat.isValid() || new_mat.type != 0) if (!new_mat.isValid() || new_mat.type != 0)
{ {
c->con.printerr("New job material isn't inorganic: %s\n", out.printerr("New job material isn't inorganic: %s\n",
new_mat.toString().c_str()); new_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
@ -131,7 +131,7 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
if (!cur_mat.isValid() || cur_mat.type != 0) if (!cur_mat.isValid() || cur_mat.type != 0)
{ {
c->con.printerr("Current job material isn't inorganic: %s\n", out.printerr("Current job material isn't inorganic: %s\n",
cur_mat.toString().c_str()); cur_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
@ -139,13 +139,13 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
df::craft_material_class old_class = cur_mat.getCraftClass(); df::craft_material_class old_class = cur_mat.getCraftClass();
if (old_class == craft_material_class::None) if (old_class == craft_material_class::None)
{ {
c->con.printerr("Unexpected current material type: %s\n", out.printerr("Unexpected current material type: %s\n",
cur_mat.toString().c_str()); cur_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
if (new_mat.getCraftClass() != old_class) if (new_mat.getCraftClass() != old_class)
{ {
c->con.printerr("New material %s does not satisfy requirement: %s\n", out.printerr("New material %s does not satisfy requirement: %s\n",
new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class));
return CR_FAILURE; return CR_FAILURE;
} }
@ -157,14 +157,14 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
if (item_mat != cur_mat) if (item_mat != cur_mat)
{ {
c->con.printerr("Job item %d has different material: %s\n", out.printerr("Job item %d has different material: %s\n",
i, item_mat.toString().c_str()); i, item_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
if (!new_mat.matches(*item)) if (!new_mat.matches(*item))
{ {
c->con.printerr("Job item %d requirements not satisfied by %s.\n", out.printerr("Job item %d requirements not satisfied by %s.\n",
i, new_mat.toString().c_str()); i, new_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
@ -181,7 +181,7 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
item->mat_index = new_mat.index; item->mat_index = new_mat.index;
} }
c->con << "Applied material '" << new_mat.toString() out << "Applied material '" << new_mat.toString()
<< "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl;
return CR_OK; return CR_OK;
} }
@ -212,7 +212,7 @@ static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choic
return false; return false;
} }
static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) static command_result job_material_in_build(color_ostream &out, MaterialInfo &new_mat)
{ {
df::ui_build_selector *sel = ui_build_selector; df::ui_build_selector *sel = ui_build_selector;
df::ui_build_item_req *req = sel->requirements[ui_build_selector->req_index]; df::ui_build_item_req *req = sel->requirements[ui_build_selector->req_index];
@ -234,11 +234,11 @@ static command_result job_material_in_build(Core *c, MaterialInfo &new_mat)
} }
} }
c->con.printerr("Could not find material in list: %s\n", new_mat.toString().c_str()); out.printerr("Could not find material in list: %s\n", new_mat.toString().c_str());
return CR_FAILURE; return CR_FAILURE;
} }
static command_result job_material(Core * c, vector <string> & parameters) static command_result job_material(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
@ -246,7 +246,7 @@ static command_result job_material(Core * c, vector <string> & parameters)
if (parameters.size() == 1) if (parameters.size() == 1)
{ {
if (!new_mat.find(parameters[0])) { if (!new_mat.find(parameters[0])) {
c->con.printerr("Could not find material: %s\n", parameters[0].c_str()); out.printerr("Could not find material: %s\n", parameters[0].c_str());
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
} }
@ -254,21 +254,21 @@ static command_result job_material(Core * c, vector <string> & parameters)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
if (ui->main.mode == ui_sidebar_mode::QueryBuilding) if (ui->main.mode == ui_sidebar_mode::QueryBuilding)
return job_material_in_job(c, new_mat); return job_material_in_job(out, new_mat);
if (ui->main.mode == ui_sidebar_mode::Build) if (ui->main.mode == ui_sidebar_mode::Build)
return job_material_in_build(c, new_mat); return job_material_in_build(out, new_mat);
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
/* job-duplicate implementation */ /* job-duplicate implementation */
static command_result job_duplicate(Core * c, vector <string> & parameters) static command_result job_duplicate(color_ostream &out, vector <string> & parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::job *job = Gui::getSelectedWorkshopJob(c); df::job *job = Gui::getSelectedWorkshopJob(out);
if (!job) if (!job)
return CR_FAILURE; return CR_FAILURE;
@ -277,14 +277,14 @@ static command_result job_duplicate(Core * c, vector <string> & parameters)
job->job_type != job_type::CollectSand && job->job_type != job_type::CollectSand &&
job->job_type != job_type::CollectClay)) job->job_type != job_type::CollectClay))
{ {
c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); out.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type));
return CR_FAILURE; return CR_FAILURE;
} }
df::building *building = world->selected_building; df::building *building = world->selected_building;
if (building->jobs.size() >= 10) if (building->jobs.size() >= 10)
{ {
c->con.printerr("Job list is already full.\n"); out.printerr("Job list is already full.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -299,40 +299,40 @@ static command_result job_duplicate(Core * c, vector <string> & parameters)
/* Main job command implementation */ /* Main job command implementation */
static df::job_item *getJobItem(Core *c, df::job *job, std::string idx) static df::job_item *getJobItem(color_ostream &out, df::job *job, std::string idx)
{ {
if (!job) if (!job)
return NULL; return NULL;
int v = atoi(idx.c_str()); int v = atoi(idx.c_str());
if (v < 1 || v > job->job_items.size()) { if (v < 1 || v > job->job_items.size()) {
c->con.printerr("Invalid item index.\n"); out.printerr("Invalid item index.\n");
return NULL; return NULL;
} }
return job->job_items[v-1]; return job->job_items[v-1];
} }
static command_result job_cmd(Core * c, vector <string> & parameters) static command_result job_cmd(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
std::string cmd = (parameters.empty() ? "query" : parameters[0]); std::string cmd = (parameters.empty() ? "query" : parameters[0]);
if (cmd == "query" || cmd == "list") if (cmd == "query" || cmd == "list")
{ {
df::job *job = Gui::getSelectedJob(c); df::job *job = Gui::getSelectedJob(out);
if (!job) if (!job)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
if (cmd == "query") { if (cmd == "query") {
printJobDetails(c, job); printJobDetails(out, job);
} else { } else {
if (!Gui::workshop_job_hotkey(c, c->getTopViewscreen())) if (!Gui::workshop_job_hotkey(Core::getTopViewscreen()))
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::building *selected = world->selected_building; df::building *selected = world->selected_building;
for (size_t i = 0; i < selected->jobs.size(); i++) for (size_t i = 0; i < selected->jobs.size(); i++)
printJobDetails(c, selected->jobs[i]); printJobDetails(out, selected->jobs[i]);
} }
} }
else if (cmd == "item-material") else if (cmd == "item-material")
@ -340,8 +340,8 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
if (parameters.size() != 3) if (parameters.size() != 3)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::job *job = Gui::getSelectedJob(c); df::job *job = Gui::getSelectedJob(out);
df::job_item *item = getJobItem(c, job, parameters[1]); df::job_item *item = getJobItem(out, job, parameters[1]);
if (!item) if (!item)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
@ -349,13 +349,13 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
MaterialInfo minfo; MaterialInfo minfo;
if (!minfo.find(parameters[2])) { if (!minfo.find(parameters[2])) {
c->con.printerr("Could not find the specified material.\n"); out.printerr("Could not find the specified material.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (minfo.isValid() && !iinfo.matches(*item, &minfo)) { if (minfo.isValid() && !iinfo.matches(*item, &minfo)) {
c->con.printerr("Material does not match the requirements.\n"); out.printerr("Material does not match the requirements.\n");
printJobDetails(c, job); printJobDetails(out, job);
return CR_FAILURE; return CR_FAILURE;
} }
@ -370,13 +370,13 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
item->mat_type = minfo.type; item->mat_type = minfo.type;
item->mat_index = minfo.index; item->mat_index = minfo.index;
c->con << "Job item updated." << endl; out << "Job item updated." << endl;
if (item->item_type < 0 && minfo.isValid()) if (item->item_type < 0 && minfo.isValid())
c->con.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n" out.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n"
" is ignored unless the item type is also specified.\n"); " is ignored unless the item type is also specified.\n");
printJobDetails(c, job); printJobDetails(out, job);
return CR_OK; return CR_OK;
} }
else if (cmd == "item-type") else if (cmd == "item-type")
@ -384,8 +384,8 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
if (parameters.size() != 3) if (parameters.size() != 3)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::job *job = Gui::getSelectedJob(c); df::job *job = Gui::getSelectedJob(out);
df::job_item *item = getJobItem(c, job, parameters[1]); df::job_item *item = getJobItem(out, job, parameters[1]);
if (!item) if (!item)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
@ -393,21 +393,21 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
MaterialInfo minfo(item); MaterialInfo minfo(item);
if (!iinfo.find(parameters[2])) { if (!iinfo.find(parameters[2])) {
c->con.printerr("Could not find the specified item type.\n"); out.printerr("Could not find the specified item type.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) { if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) {
c->con.printerr("Item type does not match the requirements.\n"); out.printerr("Item type does not match the requirements.\n");
printJobDetails(c, job); printJobDetails(out, job);
return CR_FAILURE; return CR_FAILURE;
} }
item->item_type = iinfo.type; item->item_type = iinfo.type;
item->item_subtype = iinfo.subtype; item->item_subtype = iinfo.subtype;
c->con << "Job item updated." << endl; out << "Job item updated." << endl;
printJobDetails(c, job); printJobDetails(out, job);
return CR_OK; return CR_OK;
} }
else else

@ -26,11 +26,11 @@ typedef vector <df::coord> coord_vec;
CommandHistory liquids_hist; CommandHistory liquids_hist;
command_result df_liquids (Core * c, vector <string> & parameters); command_result df_liquids (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("liquids"); DFHACK_PLUGIN("liquids");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
liquids_hist.load("liquids.history"); liquids_hist.load("liquids.history");
commands.clear(); commands.clear();
@ -38,7 +38,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
liquids_hist.save("liquids.history"); liquids_hist.save("liquids.history");
return CR_OK; return CR_OK;
@ -220,15 +220,18 @@ private:
Core *c_; Core *c_;
}; };
command_result df_liquids (Core * c, vector <string> & parameters) command_result df_liquids (color_ostream &out_, vector <string> & parameters)
{ {
int32_t x,y,z; int32_t x,y,z;
assert(out_.is_console());
Console &out = static_cast<Console&>(out_);
for(size_t i = 0; i < parameters.size();i++) for(size_t i = 0; i < parameters.size();i++)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("This tool allows placing magma, water and other similar things.\n" out.print("This tool allows placing magma, water and other similar things.\n"
"It is interactive and further help is available when you run it.\n" "It is interactive and further help is available when you run it.\n"
); );
return CR_OK; return CR_OK;
@ -237,14 +240,14 @@ command_result df_liquids (Core * c, vector <string> & parameters)
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
Brush * brush = new RectangleBrush(1,1); Brush * brush = new RectangleBrush(1,1);
string brushname = "point"; string brushname = "point";
bool end = false; bool end = false;
c->con << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; out << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;
string mode="magma"; string mode="magma";
string flowmode="f+"; string flowmode="f+";
@ -256,11 +259,11 @@ command_result df_liquids (Core * c, vector <string> & parameters)
string command = ""; string command = "";
std::stringstream str; std::stringstream str;
str <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]#"; str <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]#";
if(c->con.lineedit(str.str(),command,liquids_hist) == -1) if(out.lineedit(str.str(),command,liquids_hist) == -1)
return CR_FAILURE; return CR_FAILURE;
if(command=="help" || command == "?") if(command=="help" || command == "?")
{ {
c->con << "Modes:" << endl out << "Modes:" << endl
<< "m - switch to magma" << endl << "m - switch to magma" << endl
<< "w - switch to water" << endl << "w - switch to water" << endl
<< "o - make obsidian wall instead" << endl << "o - make obsidian wall instead" << endl
@ -333,21 +336,21 @@ command_result df_liquids (Core * c, vector <string> & parameters)
std::stringstream str; std::stringstream str;
CommandHistory range_hist; CommandHistory range_hist;
str << " :set range width<" << width << "># "; str << " :set range width<" << width << "># ";
c->con.lineedit(str.str(),command,range_hist); out.lineedit(str.str(),command,range_hist);
range_hist.add(command); range_hist.add(command);
width = command == "" ? width : atoi (command.c_str()); width = command == "" ? width : atoi (command.c_str());
if(width < 1) width = 1; if(width < 1) width = 1;
str.str(""); str.str("");
str << " :set range height<" << height << "># "; str << " :set range height<" << height << "># ";
c->con.lineedit(str.str(),command,range_hist); out.lineedit(str.str(),command,range_hist);
range_hist.add(command); range_hist.add(command);
height = command == "" ? height : atoi (command.c_str()); height = command == "" ? height : atoi (command.c_str());
if(height < 1) height = 1; if(height < 1) height = 1;
str.str(""); str.str("");
str << " :set range z-levels<" << z_levels << "># "; str << " :set range z-levels<" << z_levels << "># ";
c->con.lineedit(str.str(),command,range_hist); out.lineedit(str.str(),command,range_hist);
range_hist.add(command); range_hist.add(command);
z_levels = command == "" ? z_levels : atoi (command.c_str()); z_levels = command == "" ? z_levels : atoi (command.c_str());
if(z_levels < 1) z_levels = 1; if(z_levels < 1) z_levels = 1;
@ -378,7 +381,7 @@ command_result df_liquids (Core * c, vector <string> & parameters)
{ {
delete brush; delete brush;
brushname = "flood"; brushname = "flood";
brush = new FloodBrush(c); brush = new FloodBrush(&Core::getInstance());
} }
else if(command == "q") else if(command == "q")
{ {
@ -427,24 +430,25 @@ command_result df_liquids (Core * c, vector <string> & parameters)
amount = 7; amount = 7;
else if(command.empty()) else if(command.empty())
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
do do
{ {
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con << "Can't see any DF map loaded." << endl; out << "Can't see any DF map loaded." << endl;
break;; break;;
} }
if(!Gui::getCursorCoords(x,y,z)) if(!Gui::getCursorCoords(x,y,z))
{ {
c->con << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; out << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
break; break;
} }
c->con << "cursor coords: " << x << "/" << y << "/" << z << endl; out << "cursor coords: " << x << "/" << y << "/" << z << endl;
MapCache mcache; MapCache mcache;
DFHack::DFCoord cursor(x,y,z); DFHack::DFCoord cursor(x,y,z);
coord_vec all_tiles = brush->points(mcache,cursor); coord_vec all_tiles = brush->points(mcache,cursor);
c->con << "working..." << endl; out << "working..." << endl;
if(mode == "obsidian") if(mode == "obsidian")
{ {
coord_vec::iterator iter = all_tiles.begin(); coord_vec::iterator iter = all_tiles.begin();
@ -584,21 +588,21 @@ command_result df_liquids (Core * c, vector <string> & parameters)
} }
else else
{ {
c->con << "flow bit 1 = " << bflags.bits.liquid_1 << endl; out << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
c->con << "flow bit 2 = " << bflags.bits.liquid_2 << endl; out << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
} }
biter ++; biter ++;
} }
} }
if(mcache.WriteAll()) if(mcache.WriteAll())
c->con << "OK" << endl; out << "OK" << endl;
else else
c->con << "Something failed horribly! RUN!" << endl; out << "Something failed horribly! RUN!" << endl;
} while (0); } while (0);
} }
else else
{ {
c->con << command << " : unknown command." << endl; out << command << " : unknown command." << endl;
} }
} }
return CR_OK; return CR_OK;

@ -1,15 +1,5 @@
PROJECT(mapexport) PROJECT(mapexport)
INCLUDE_DIRECTORIES (
${CMAKE_CURRENT_SOURCE_DIR}
${dfhack_SOURCE_DIR}/library/depends/protobuf/
${dfhack_SOURCE_DIR}/library/depends/zlib/
)
LINK_DIRECTORIES(
${dfhack_SOURCE_DIR}/library/depends/zlib/
)
#The protobuf sources we generate will require these headers #The protobuf sources we generate will require these headers
SET(PROJECT_HDRS SET(PROJECT_HDRS
${dfhack_SOURCE_DIR}/library/depends/protobuf/google/protobuf/stubs/once.h ${dfhack_SOURCE_DIR}/library/depends/protobuf/google/protobuf/stubs/once.h
@ -51,7 +41,7 @@ DEPENDS protoc-bin ${PROJECT_PROTOS}
) )
IF(WIN32) IF(WIN32)
DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf zlib) DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite)
ELSE() ELSE()
DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf z) DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite)
ENDIF() ENDIF()

@ -23,11 +23,11 @@ using df::global::world;
typedef std::vector<df::plant *> PlantList; typedef std::vector<df::plant *> PlantList;
command_result mapexport (Core * c, std::vector <std::string> & parameters); command_result mapexport (color_ostream &out, std::vector <std::string> & parameters);
DFHACK_PLUGIN("mapexport"); DFHACK_PLUGIN("mapexport");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
commands.clear(); commands.clear();
@ -35,13 +35,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
google::protobuf::ShutdownProtobufLibrary();
return CR_OK; return CR_OK;
} }
command_result mapexport (Core * c, std::vector <std::string> & parameters) command_result mapexport (color_ostream &out, std::vector <std::string> & parameters)
{ {
bool showHidden = false; bool showHidden = false;
@ -51,7 +50,7 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("Exports the currently visible map to a file.\n" out.print("Exports the currently visible map to a file.\n"
"Usage: mapexport [options] <filename>\n" "Usage: mapexport [options] <filename>\n"
"Example: mapexport all embark.dfmap\n" "Example: mapexport all embark.dfmap\n"
"Options:\n" "Options:\n"
@ -66,32 +65,30 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
} }
} }
CoreSuspender suspend;
uint32_t x_max=0, y_max=0, z_max=0; uint32_t x_max=0, y_max=0, z_max=0;
c->Suspend();
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
if (parameters.size() < filenameParameter) if (parameters.size() < filenameParameter)
{ {
c->con.printerr("Please supply a filename.\n"); out.printerr("Please supply a filename.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
std::string filename = parameters[filenameParameter-1]; std::string filename = parameters[filenameParameter-1];
if (filename.rfind(".dfmap") == std::string::npos) filename += ".dfmap"; if (filename.rfind(".dfmap") == std::string::npos) filename += ".dfmap";
c->con << "Writing to " << filename << "..." << std::endl; out << "Writing to " << filename << "..." << std::endl;
std::ofstream output_file(filename, std::ios::out | std::ios::trunc | std::ios::binary); std::ofstream output_file(filename, std::ios::out | std::ios::trunc | std::ios::binary);
if (!output_file.is_open()) if (!output_file.is_open())
{ {
c->con.printerr("Couldn't open the output file.\n"); out.printerr("Couldn't open the output file.\n");
c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&output_file); ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&output_file);
@ -102,16 +99,16 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
Maps::getSize(x_max, y_max, z_max); Maps::getSize(x_max, y_max, z_max);
MapExtras::MapCache map; MapExtras::MapCache map;
DFHack::Materials *mats = c->getMaterials(); DFHack::Materials *mats = Core::getInstance().getMaterials();
c->con << "Writing map info..." << std::endl; out << "Writing map info..." << std::endl;
dfproto::Map protomap; dfproto::Map protomap;
protomap.set_x_size(x_max); protomap.set_x_size(x_max);
protomap.set_y_size(y_max); protomap.set_y_size(y_max);
protomap.set_z_size(z_max); protomap.set_z_size(z_max);
c->con << "Writing material dictionary..." << std::endl; out << "Writing material dictionary..." << std::endl;
for (size_t i = 0; i < world->raws.inorganics.size(); i++) for (size_t i = 0; i < world->raws.inorganics.size(); i++)
{ {
@ -143,7 +140,7 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureGlobal;
DFHack::t_feature blockFeatureLocal; DFHack::t_feature blockFeatureLocal;
c->con.print("Writing map block information"); out.print("Writing map block information");
for(uint32_t z = 0; z < z_max; z++) for(uint32_t z = 0; z < z_max; z++)
{ {
@ -151,7 +148,7 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
{ {
for(uint32_t b_x = 0; b_x < x_max; b_x++) for(uint32_t b_x = 0; b_x < x_max; b_x++)
{ {
if (b_x == 0 && b_y == 0 && z % 10 == 0) c->con.print("."); if (b_x == 0 && b_y == 0 && z % 10 == 0) out.print(".");
// Get the map block // Get the map block
df::coord2d blockCoord(b_x, b_y); df::coord2d blockCoord(b_x, b_y);
MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z));
@ -283,7 +280,6 @@ command_result mapexport (Core * c, std::vector <std::string> & parameters)
delete raw_output; delete raw_output;
mats->Finish(); mats->Finish();
c->con.print("\nMap succesfully exported!\n"); out.print("\nMap succesfully exported!\n");
c->Resume();
return CR_OK; return CR_OK;
} }

@ -12,11 +12,11 @@ using namespace std;
using namespace DFHack; using namespace DFHack;
command_result mode (Core * c, vector <string> & parameters); command_result mode (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("mode"); DFHACK_PLUGIN("mode");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -29,12 +29,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
// add tracking here // add tracking here
return CR_OK; return CR_OK;
@ -94,8 +94,11 @@ void printCurrentModes(t_gamemodes gm, Console & con)
} }
} }
command_result mode (Core * c, vector <string> & parameters) command_result mode (color_ostream &out_, vector <string> & parameters)
{ {
assert(out_.is_console());
Console &out = static_cast<Console&>(out_);
string command = ""; string command = "";
bool set = false; bool set = false;
bool abuse = false; bool abuse = false;
@ -113,22 +116,28 @@ command_result mode (Core * c, vector <string> & parameters)
else else
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
c->Suspend();
World *world = c->getWorld(); World *world;
{
CoreSuspender suspend;
world = Core::getInstance().getWorld();
world->Start(); world->Start();
world->ReadGameMode(gm); world->ReadGameMode(gm);
c->Resume(); }
printCurrentModes(gm, c->con);
printCurrentModes(gm, out);
if(set) if(set)
{ {
if(!abuse) if(!abuse)
{ {
if( gm.g_mode == GAMEMODE_NONE || gm.g_type == GAMETYPE_VIEW_LEGENDS) if( gm.g_mode == GAMEMODE_NONE || gm.g_type == GAMETYPE_VIEW_LEGENDS)
{ {
c->con.printerr("It is not safe to set modes in menus.\n"); out.printerr("It is not safe to set modes in menus.\n");
return CR_FAILURE; return CR_FAILURE;
} }
c->con << "\nPossible choices:" << endl out << "\nPossible choices:" << endl
<< "0 = Fortress Mode" << endl << "0 = Fortress Mode" << endl
<< "1 = Adventurer Mode" << endl << "1 = Adventurer Mode" << endl
<< "2 = Arena Mode" << endl << "2 = Arena Mode" << endl
@ -140,7 +149,7 @@ command_result mode (Core * c, vector <string> & parameters)
string selected; string selected;
input_again: input_again:
CommandHistory hist; CommandHistory hist;
c->con.lineedit("Enter new mode: ",selected, hist); out.lineedit("Enter new mode: ",selected, hist);
if(selected == "c") if(selected == "c")
return CR_OK; return CR_OK;
const char * start = selected.c_str(); const char * start = selected.c_str();
@ -148,7 +157,7 @@ command_result mode (Core * c, vector <string> & parameters)
select = strtol(start, &end, 10); select = strtol(start, &end, 10);
if(!end || end==start || select > 4) if(!end || end==start || select > 4)
{ {
c->con.printerr("This is not a valid selection.\n"); out.printerr("This is not a valid selection.\n");
goto input_again; goto input_again;
} }
switch(select) switch(select)
@ -179,21 +188,24 @@ command_result mode (Core * c, vector <string> & parameters)
{ {
CommandHistory hist; CommandHistory hist;
string selected; string selected;
c->con.lineedit("Enter new game mode number (c for exit): ",selected, hist); out.lineedit("Enter new game mode number (c for exit): ",selected, hist);
if(selected == "c") if(selected == "c")
return CR_OK; return CR_OK;
const char * start = selected.c_str(); const char * start = selected.c_str();
gm.g_mode = (GameMode) strtol(start, 0, 10); gm.g_mode = (GameMode) strtol(start, 0, 10);
c->con.lineedit("Enter new game type number (c for exit): ",selected, hist); out.lineedit("Enter new game type number (c for exit): ",selected, hist);
if(selected == "c") if(selected == "c")
return CR_OK; return CR_OK;
start = selected.c_str(); start = selected.c_str();
gm.g_type = (GameType) strtol(start, 0, 10); gm.g_type = (GameType) strtol(start, 0, 10);
} }
c->Suspend();
{
CoreSuspender suspend;
world->WriteGameMode(gm); world->WriteGameMode(gm);
c->Resume(); }
c->con << endl;
out << endl;
} }
return CR_OK; return CR_OK;
} }

@ -20,13 +20,13 @@ using std::string;
using namespace DFHack; using namespace DFHack;
using df::global::world; using df::global::world;
command_result df_grow (Core * c, vector <string> & parameters); command_result df_grow (color_ostream &out, vector <string> & parameters);
command_result df_immolate (Core * c, vector <string> & parameters); command_result df_immolate (color_ostream &out, vector <string> & parameters);
command_result df_extirpate (Core * c, vector <string> & parameters); command_result df_extirpate (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("plants"); DFHACK_PLUGIN("plants");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow)); commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow));
@ -35,7 +35,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -81,13 +81,13 @@ static bool getoptions( vector <string> & parameters, bool & shrubs, bool & tree
* And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin. * And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin.
* Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants. * Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants.
*/ */
static command_result immolations (Core * c, do_what what, bool shrubs, bool trees, bool help) static command_result immolations (color_ostream &out, do_what what, bool shrubs, bool trees, bool help)
{ {
static const char * what1 = "destroys"; static const char * what1 = "destroys";
static const char * what2 = "burns"; static const char * what2 = "burns";
if(help) if(help)
{ {
c->con.print("Without any options, this command %s a plant under the cursor.\n" out.print("Without any options, this command %s a plant under the cursor.\n"
"Options:\n" "Options:\n"
"shrubs - affect all shrubs\n" "shrubs - affect all shrubs\n"
"trees - affect all trees\n" "trees - affect all trees\n"
@ -96,10 +96,10 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre
); );
return CR_OK; return CR_OK;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
uint32_t x_max, y_max, z_max; uint32_t x_max, y_max, z_max;
@ -119,7 +119,7 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre
destroyed ++; destroyed ++;
} }
} }
c->con.print("Praise Armok!\n"); out.print("Praise Armok!\n");
} }
else else
{ {
@ -152,55 +152,55 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre
} }
else else
{ {
c->con.printerr("No mass destruction and no cursor...\n" ); out.printerr("No mass destruction and no cursor...\n" );
} }
} }
return CR_OK; return CR_OK;
} }
command_result df_immolate (Core * c, vector <string> & parameters) command_result df_immolate (color_ostream &out, vector <string> & parameters)
{ {
bool shrubs = false, trees = false, help = false; bool shrubs = false, trees = false, help = false;
if(getoptions(parameters,shrubs,trees,help)) if(getoptions(parameters,shrubs,trees,help))
{ {
return immolations(c,do_immolate,shrubs,trees, help); return immolations(out,do_immolate,shrubs,trees, help);
} }
else else
{ {
c->con.printerr("Invalid parameter!\n"); out.printerr("Invalid parameter!\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }
command_result df_extirpate (Core * c, vector <string> & parameters) command_result df_extirpate (color_ostream &out, vector <string> & parameters)
{ {
bool shrubs = false, trees = false, help = false; bool shrubs = false, trees = false, help = false;
if(getoptions(parameters,shrubs,trees, help)) if(getoptions(parameters,shrubs,trees, help))
{ {
return immolations(c,do_extirpate,shrubs,trees, help); return immolations(out,do_extirpate,shrubs,trees, help);
} }
else else
{ {
c->con.printerr("Invalid parameter!\n"); out.printerr("Invalid parameter!\n");
return CR_FAILURE; return CR_FAILURE;
} }
} }
command_result df_grow (Core * c, vector <string> & parameters) command_result df_grow (color_ostream &out, vector <string> & parameters)
{ {
for(size_t i = 0; i < parameters.size();i++) for(size_t i = 0; i < parameters.size();i++)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("This command turns all living saplings into full-grown trees.\n"); out.print("This command turns all living saplings into full-grown trees.\n");
return CR_OK; return CR_OK;
} }
} }
CoreSuspender suspend(c); CoreSuspender suspend;
Console & con = c->con;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
MapExtras::MapCache map; MapExtras::MapCache map;

@ -33,13 +33,13 @@ using namespace df::enums;
using df::global::world; using df::global::world;
using df::global::cursor; using df::global::cursor;
command_result df_probe (Core * c, vector <string> & parameters); command_result df_probe (color_ostream &out, vector <string> & parameters);
command_result df_cprobe (Core * c, vector <string> & parameters); command_result df_cprobe (color_ostream &out, vector <string> & parameters);
command_result df_bprobe (Core * c, vector <string> & parameters); command_result df_bprobe (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("probe"); DFHACK_PLUGIN("probe");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("probe", commands.push_back(PluginCommand("probe",
@ -54,20 +54,19 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result df_cprobe (Core * c, vector <string> & parameters) command_result df_cprobe (color_ostream &out, vector <string> & parameters)
{ {
Console & con = c->con; CoreSuspender suspend;
CoreSuspender suspend(c);
int32_t cursorX, cursorY, cursorZ; int32_t cursorX, cursorY, cursorZ;
Gui::getCursorCoords(cursorX,cursorY,cursorZ); Gui::getCursorCoords(cursorX,cursorY,cursorZ);
if(cursorX == -30000) if(cursorX == -30000)
{ {
con.printerr("No cursor; place cursor over creature to probe.\n"); out.printerr("No cursor; place cursor over creature to probe.\n");
} }
else else
{ {
@ -76,7 +75,7 @@ command_result df_cprobe (Core * c, vector <string> & parameters)
df::unit * unit = world->units.all[i]; df::unit * unit = world->units.all[i];
if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ) if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ)
{ {
con.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id); out.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id);
break; break;
} }
} }
@ -84,29 +83,29 @@ command_result df_cprobe (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
command_result df_probe (Core * c, vector <string> & parameters) command_result df_probe (color_ostream &out, vector <string> & parameters)
{ {
//bool showBlock, showDesig, showOccup, showTile, showMisc; //bool showBlock, showDesig, showOccup, showTile, showMisc;
Console & con = c->con;
/* /*
if (!parseOptions(parameters, showBlock, showDesig, showOccup, if (!parseOptions(parameters, showBlock, showDesig, showOccup,
showTile, showMisc)) showTile, showMisc))
{ {
con.printerr("Unknown parameters!\n"); out.printerr("Unknown parameters!\n");
return CR_FAILURE; return CR_FAILURE;
} }
*/ */
CoreSuspender suspend(c); CoreSuspender suspend;
DFHack::Materials *Materials = Core::getInstance().getMaterials();
DFHack::Materials *Materials = c->getMaterials();
DFHack::VersionInfo* mem = c->vinfo;
std::vector<t_matglossInorganic> inorganic; std::vector<t_matglossInorganic> inorganic;
bool hasmats = Materials->CopyInorganicMaterials(inorganic); bool hasmats = Materials->CopyInorganicMaterials(inorganic);
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
MapExtras::MapCache mc; MapExtras::MapCache mc;
@ -118,7 +117,7 @@ command_result df_probe (Core * c, vector <string> & parameters)
Gui::getCursorCoords(cursorX,cursorY,cursorZ); Gui::getCursorCoords(cursorX,cursorY,cursorZ);
if(cursorX == -30000) if(cursorX == -30000)
{ {
con.printerr("No cursor; place cursor over tile to probe.\n"); out.printerr("No cursor; place cursor over tile to probe.\n");
return CR_FAILURE; return CR_FAILURE;
} }
DFCoord cursor (cursorX,cursorY,cursorZ); DFCoord cursor (cursorX,cursorY,cursorZ);
@ -131,17 +130,17 @@ command_result df_probe (Core * c, vector <string> & parameters)
MapExtras::Block * b = mc.BlockAt(cursor/16); MapExtras::Block * b = mc.BlockAt(cursor/16);
if(!b && !b->valid) if(!b && !b->valid)
{ {
con.printerr("No data.\n"); out.printerr("No data.\n");
return CR_OK; return CR_OK;
} }
mapblock40d & block = b->raw; mapblock40d & block = b->raw;
con.print("block addr: 0x%x\n\n", block.origin); out.print("block addr: 0x%x\n\n", block.origin);
/* /*
if (showBlock) if (showBlock)
{ {
con.print("block flags:\n"); out.print("block flags:\n");
print_bits<uint32_t>(block.blockflags.whole,con); print_bits<uint32_t>(block.blockflags.whole,out);
con.print("\n\n"); out.print("\n\n");
} }
*/ */
df::tiletype tiletype = mc.tiletypeAt(cursor); df::tiletype tiletype = mc.tiletypeAt(cursor);
@ -149,96 +148,96 @@ command_result df_probe (Core * c, vector <string> & parameters)
/* /*
if(showDesig) if(showDesig)
{ {
con.print("designation\n"); out.print("designation\n");
print_bits<uint32_t>(block.designation[tileX][tileY].whole, print_bits<uint32_t>(block.designation[tileX][tileY].whole,
con); out);
con.print("\n\n"); out.print("\n\n");
} }
if(showOccup) if(showOccup)
{ {
con.print("occupancy\n"); out.print("occupancy\n");
print_bits<uint32_t>(block.occupancy[tileX][tileY].whole, print_bits<uint32_t>(block.occupancy[tileX][tileY].whole,
con); out);
con.print("\n\n"); out.print("\n\n");
} }
*/ */
// tiletype // tiletype
con.print("tiletype: %d", tiletype); out.print("tiletype: %d", tiletype);
if(tileName(tiletype)) if(tileName(tiletype))
con.print(" = %s",tileName(tiletype)); out.print(" = %s",tileName(tiletype));
con.print("\n"); out.print("\n");
df::tiletype_shape shape = tileShape(tiletype); df::tiletype_shape shape = tileShape(tiletype);
df::tiletype_material material = tileMaterial(tiletype); df::tiletype_material material = tileMaterial(tiletype);
df::tiletype_special special = tileSpecial(tiletype); df::tiletype_special special = tileSpecial(tiletype);
df::tiletype_variant variant = tileVariant(tiletype); df::tiletype_variant variant = tileVariant(tiletype);
con.print("%-10s: %4d %s\n","Class" ,shape, out.print("%-10s: %4d %s\n","Class" ,shape,
ENUM_KEY_STR(tiletype_shape, shape)); ENUM_KEY_STR(tiletype_shape, shape));
con.print("%-10s: %4d %s\n","Material" , out.print("%-10s: %4d %s\n","Material" ,
material, ENUM_KEY_STR(tiletype_material, material)); material, ENUM_KEY_STR(tiletype_material, material));
con.print("%-10s: %4d %s\n","Special" , out.print("%-10s: %4d %s\n","Special" ,
special, ENUM_KEY_STR(tiletype_special, special)); special, ENUM_KEY_STR(tiletype_special, special));
con.print("%-10s: %4d %s\n" ,"Variant" , out.print("%-10s: %4d %s\n" ,"Variant" ,
variant, ENUM_KEY_STR(tiletype_variant, variant)); variant, ENUM_KEY_STR(tiletype_variant, variant));
con.print("%-10s: %s\n" ,"Direction", out.print("%-10s: %s\n" ,"Direction",
tileDirection(tiletype).getStr()); tileDirection(tiletype).getStr());
con.print("\n"); out.print("\n");
con.print("temperature1: %d U\n",mc.temperature1At(cursor)); out.print("temperature1: %d U\n",mc.temperature1At(cursor));
con.print("temperature2: %d U\n",mc.temperature2At(cursor)); out.print("temperature2: %d U\n",mc.temperature2At(cursor));
// biome, geolayer // biome, geolayer
con << "biome: " << des.bits.biome << std::endl; out << "biome: " << des.bits.biome << std::endl;
con << "geolayer: " << des.bits.geolayer_index out << "geolayer: " << des.bits.geolayer_index
<< std::endl; << std::endl;
int16_t base_rock = mc.baseMaterialAt(cursor); int16_t base_rock = mc.baseMaterialAt(cursor);
if(base_rock != -1) if(base_rock != -1)
{ {
con << "Layer material: " << dec << base_rock; out << "Layer material: " << dec << base_rock;
if(hasmats) if(hasmats)
con << " / " << inorganic[base_rock].id out << " / " << inorganic[base_rock].id
<< " / " << " / "
<< inorganic[base_rock].name << inorganic[base_rock].name
<< endl; << endl;
else else
con << endl; out << endl;
} }
int16_t vein_rock = mc.veinMaterialAt(cursor); int16_t vein_rock = mc.veinMaterialAt(cursor);
if(vein_rock != -1) if(vein_rock != -1)
{ {
con << "Vein material (final): " << dec << vein_rock; out << "Vein material (final): " << dec << vein_rock;
if(hasmats) if(hasmats)
con << " / " << inorganic[vein_rock].id out << " / " << inorganic[vein_rock].id
<< " / " << " / "
<< inorganic[vein_rock].name << inorganic[vein_rock].name
<< endl; << endl;
else else
con << endl; out << endl;
} }
// liquids // liquids
if(des.bits.flow_size) if(des.bits.flow_size)
{ {
if(des.bits.liquid_type == tile_liquid::Magma) if(des.bits.liquid_type == tile_liquid::Magma)
con <<"magma: "; out <<"magma: ";
else con <<"water: "; else out <<"water: ";
con << des.bits.flow_size << std::endl; out << des.bits.flow_size << std::endl;
} }
if(des.bits.flow_forbid) if(des.bits.flow_forbid)
con << "flow forbid" << std::endl; out << "flow forbid" << std::endl;
if(des.bits.pile) if(des.bits.pile)
con << "stockpile?" << std::endl; out << "stockpile?" << std::endl;
if(des.bits.rained) if(des.bits.rained)
con << "rained?" << std::endl; out << "rained?" << std::endl;
if(des.bits.smooth) if(des.bits.smooth)
con << "smooth?" << std::endl; out << "smooth?" << std::endl;
if(des.bits.water_salt) if(des.bits.water_salt)
con << "salty" << endl; out << "salty" << endl;
if(des.bits.water_stagnant) if(des.bits.water_stagnant)
con << "stagnant" << endl; out << "stagnant" << endl;
#define PRINT_FLAG( X ) con.print("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) ) #define PRINT_FLAG( X ) out.print("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) )
PRINT_FLAG( bits.hidden ); PRINT_FLAG( bits.hidden );
PRINT_FLAG( bits.light ); PRINT_FLAG( bits.light );
PRINT_FLAG( bits.outside ); PRINT_FLAG( bits.outside );
@ -254,37 +253,37 @@ command_result df_probe (Core * c, vector <string> & parameters)
PRINT_FLAG( bits.feature_local ); PRINT_FLAG( bits.feature_local );
if(local.type != -1) if(local.type != -1)
{ {
con.print("%-16s", ""); out.print("%-16s", "");
con.print(" %4d", block.local_feature); out.print(" %4d", block.local_feature);
con.print(" (%2d)", local.type); out.print(" (%2d)", local.type);
con.print(" addr 0x%X ", local.origin); out.print(" addr 0x%X ", local.origin);
con.print(" %s\n", sa_feature(local.type)); out.print(" %s\n", sa_feature(local.type));
} }
PRINT_FLAG( bits.feature_global ); PRINT_FLAG( bits.feature_global );
if(global.type != -1) if(global.type != -1)
{ {
con.print("%-16s", ""); out.print("%-16s", "");
con.print(" %4d", block.global_feature); out.print(" %4d", block.global_feature);
con.print(" (%2d)", global.type); out.print(" (%2d)", global.type);
con.print(" %s\n", sa_feature(global.type)); out.print(" %s\n", sa_feature(global.type));
} }
#undef PRINT_FLAG #undef PRINT_FLAG
con << "local feature idx: " << block.local_feature out << "local feature idx: " << block.local_feature
<< endl; << endl;
con << "global feature idx: " << block.global_feature out << "global feature idx: " << block.global_feature
<< endl; << endl;
con << "mystery: " << block.mystery << endl; out << "mystery: " << block.mystery << endl;
con << std::endl; out << std::endl;
return CR_OK; return CR_OK;
} }
command_result df_bprobe (Core * c, vector <string> & parameters) command_result df_bprobe (color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
if(cursor->x == -30000) if(cursor->x == -30000)
{ {
c->con.printerr("No cursor; place cursor over tile to probe.\n"); out.printerr("No cursor; place cursor over tile to probe.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -299,38 +298,38 @@ command_result df_bprobe (Core * c, vector <string> & parameters)
continue; continue;
string name; string name;
building.origin->getName(&name); building.origin->getName(&name);
c->con.print("Building %i - \"%s\" - type %s", building.origin->id, name.c_str(), ENUM_KEY_STR(building_type, building.type)); out.print("Building %i - \"%s\" - type %s", building.origin->id, name.c_str(), ENUM_KEY_STR(building_type, building.type));
switch (building.type) switch (building.type)
{ {
case building_type::Furnace: case building_type::Furnace:
c->con.print(", subtype %s", ENUM_KEY_STR(furnace_type, building.furnace_type)); out.print(", subtype %s", ENUM_KEY_STR(furnace_type, building.furnace_type));
if (building.furnace_type == furnace_type::Custom) if (building.furnace_type == furnace_type::Custom)
c->con.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); out.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str());
break; break;
case building_type::Workshop: case building_type::Workshop:
c->con.print(", subtype %s", ENUM_KEY_STR(workshop_type, building.workshop_type)); out.print(", subtype %s", ENUM_KEY_STR(workshop_type, building.workshop_type));
if (building.workshop_type == workshop_type::Custom) if (building.workshop_type == workshop_type::Custom)
c->con.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); out.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str());
break; break;
case building_type::Construction: case building_type::Construction:
c->con.print(", subtype %s", ENUM_KEY_STR(construction_type, building.construction_type)); out.print(", subtype %s", ENUM_KEY_STR(construction_type, building.construction_type));
break; break;
case building_type::Shop: case building_type::Shop:
c->con.print(", subtype %s", ENUM_KEY_STR(shop_type, building.shop_type)); out.print(", subtype %s", ENUM_KEY_STR(shop_type, building.shop_type));
break; break;
case building_type::SiegeEngine: case building_type::SiegeEngine:
c->con.print(", subtype %s", ENUM_KEY_STR(siegeengine_type, building.siegeengine_type)); out.print(", subtype %s", ENUM_KEY_STR(siegeengine_type, building.siegeengine_type));
break; break;
case building_type::Trap: case building_type::Trap:
c->con.print(", subtype %s", ENUM_KEY_STR(trap_type, building.trap_type)); out.print(", subtype %s", ENUM_KEY_STR(trap_type, building.trap_type));
break; break;
default: default:
if (building.subtype != -1) if (building.subtype != -1)
c->con.print(", subtype %i", building.subtype); out.print(", subtype %i", building.subtype);
break; break;
} }
c->con.print("\n"); out.print("\n");
} }
return CR_OK; return CR_OK;

@ -108,7 +108,7 @@ struct compare_pair_second
} }
}; };
static void printMatdata(DFHack::Console & con, const matdata &data) static void printMatdata(color_ostream &con, const matdata &data)
{ {
con << std::setw(9) << data.count; con << std::setw(9) << data.count;
@ -129,7 +129,7 @@ static int getValue(const df::plant_raw &info)
} }
template <typename T, template <typename> class P> template <typename T, template <typename> class P>
void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials, bool show_value) void printMats(color_ostream &con, MatMap &mat, std::vector<T*> &materials, bool show_value)
{ {
unsigned int total = 0; unsigned int total = 0;
MatSorter sorting_vector; MatSorter sorting_vector;
@ -160,7 +160,7 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector<T*> &materials, b
con << ">>> TOTAL = " << total << std::endl << std::endl; con << ">>> TOTAL = " << total << std::endl << std::endl;
} }
void printVeins(DFHack::Console & con, MatMap &mat_map, void printVeins(color_ostream &con, MatMap &mat_map,
DFHack::Materials* mats, bool show_value) DFHack::Materials* mats, bool show_value)
{ {
MatMap ores; MatMap ores;
@ -189,11 +189,11 @@ void printVeins(DFHack::Console & con, MatMap &mat_map,
printMats<df::inorganic_raw, std::greater>(con, rest, world->raws.inorganics, show_value); printMats<df::inorganic_raw, std::greater>(con, rest, world->raws.inorganics, show_value);
} }
command_result prospector (Core * c, vector <string> & parameters); command_result prospector (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("prospector"); DFHACK_PLUGIN("prospector");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -215,7 +215,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -226,12 +226,12 @@ static coord2d biome_delta[] = {
coord2d(-1,-1), coord2d(0,-1), coord2d(1,-1) coord2d(-1,-1), coord2d(0,-1), coord2d(1,-1)
}; };
static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_start_sitest *screen, static command_result embark_prospector(color_ostream &out, df::viewscreen_choose_start_sitest *screen,
bool showHidden, bool showValue) bool showHidden, bool showValue)
{ {
if (!world || !world->world_data) if (!world || !world->world_data)
{ {
c->con.printerr("World data is not available.\n"); out.printerr("World data is not available.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -242,7 +242,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s
if (!cur_details) if (!cur_details)
{ {
c->con.printerr("Current region details are not available.\n"); out.printerr("Current region details are not available.\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -251,7 +251,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s
if (screen->biome_highlighted) if (screen->biome_highlighted)
{ {
c->con.print("Processing one embark tile of biome F%d.\n\n", screen->biome_idx+1); out.print("Processing one embark tile of biome F%d.\n\n", screen->biome_idx+1);
biomes[screen->biome_rgn[screen->biome_idx]]++; biomes[screen->biome_rgn[screen->biome_idx]]++;
} }
else else
@ -279,7 +279,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s
if (!geo_biome) if (!geo_biome)
{ {
c->con.printerr("Region geo-biome not found: (%d,%d)\n", bx, by); out.printerr("Region geo-biome not found: (%d,%d)\n", bx, by);
return CR_FAILURE; return CR_FAILURE;
} }
@ -340,21 +340,21 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s
} }
// Print the report // Print the report
c->con << "Layer materials:" << std::endl; out << "Layer materials:" << std::endl;
printMats<df::inorganic_raw, shallower>(c->con, layerMats, world->raws.inorganics, showValue); printMats<df::inorganic_raw, shallower>(out, layerMats, world->raws.inorganics, showValue);
if (showHidden) { if (showHidden) {
DFHack::Materials *mats = c->getMaterials(); DFHack::Materials *mats = Core::getInstance().getMaterials();
printVeins(c->con, veinMats, mats, showValue); printVeins(out, veinMats, mats, showValue);
mats->Finish(); mats->Finish();
} }
c->con << "Warning: the above data is only a very rough estimate." << std::endl; out << "Warning: the above data is only a very rough estimate." << std::endl;
return CR_OK; return CR_OK;
} }
command_result prospector (DFHack::Core * c, vector <string> & parameters) command_result prospector (color_ostream &con, vector <string> & parameters)
{ {
bool showHidden = false; bool showHidden = false;
bool showPlants = true; bool showPlants = true;
@ -362,7 +362,7 @@ command_result prospector (DFHack::Core * c, vector <string> & parameters)
bool showTemple = true; bool showTemple = true;
bool showValue = false; bool showValue = false;
bool showTube = false; bool showTube = false;
Console & con = c->con;
for(size_t i = 0; i < parameters.size();i++) for(size_t i = 0; i < parameters.size();i++)
{ {
if (parameters[i] == "all") if (parameters[i] == "all")
@ -380,15 +380,16 @@ command_result prospector (DFHack::Core * c, vector <string> & parameters)
else else
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
CoreSuspender suspend(c);
CoreSuspender suspend;
// Embark screen active: estimate using world geology data // Embark screen active: estimate using world geology data
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, c->getTopViewscreen())) if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen()))
return embark_prospector(c, screen, showHidden, showValue); return embark_prospector(con, screen, showHidden, showValue);
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); con.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -396,7 +397,7 @@ command_result prospector (DFHack::Core * c, vector <string> & parameters)
Maps::getSize(x_max, y_max, z_max); Maps::getSize(x_max, y_max, z_max);
MapExtras::MapCache map; MapExtras::MapCache map;
DFHack::Materials *mats = c->getMaterials(); DFHack::Materials *mats = Core::getInstance().getMaterials();
DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureGlobal;
DFHack::t_feature blockFeatureLocal; DFHack::t_feature blockFeatureLocal;

@ -28,11 +28,11 @@ using namespace df::enums;
using df::global::ui; using df::global::ui;
using df::global::world; using df::global::world;
static command_result rename(Core * c, vector <string> & parameters); static command_result rename(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("rename"); DFHACK_PLUGIN("rename");
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
if (world && ui) { if (world && ui) {
@ -49,7 +49,7 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -79,9 +79,9 @@ static df::squad *getSquadByIndex(unsigned idx)
return df::squad::find(entity->squads[idx]); return df::squad::find(entity->squads[idx]);
} }
static command_result rename(Core * c, vector <string> &parameters) static command_result rename(color_ostream &out, vector <string> &parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
string cmd; string cmd;
if (!parameters.empty()) if (!parameters.empty())
@ -96,7 +96,7 @@ static command_result rename(Core * c, vector <string> &parameters)
df::squad *squad = getSquadByIndex(id-1); df::squad *squad = getSquadByIndex(id-1);
if (!squad) { if (!squad) {
c->con.printerr("Couldn't find squad with index %d.\n", id); out.printerr("Couldn't find squad with index %d.\n", id);
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
@ -109,7 +109,7 @@ static command_result rename(Core * c, vector <string> &parameters)
int id = atoi(parameters[1].c_str()); int id = atoi(parameters[1].c_str());
if (id < 1 || id > 16) { if (id < 1 || id > 16) {
c->con.printerr("Invalid hotkey index\n"); out.printerr("Invalid hotkey index\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
@ -120,7 +120,7 @@ static command_result rename(Core * c, vector <string> &parameters)
if (parameters.size() != 2) if (parameters.size() != 2)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::unit *unit = Gui::getSelectedUnit(c); df::unit *unit = Gui::getSelectedUnit(out);
if (!unit) if (!unit)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
@ -153,7 +153,7 @@ static command_result rename(Core * c, vector <string> &parameters)
if (parameters.size() != 2) if (parameters.size() != 2)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
df::unit *unit = Gui::getSelectedUnit(c); df::unit *unit = Gui::getSelectedUnit(out);
if (!unit) if (!unit)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
@ -162,7 +162,7 @@ static command_result rename(Core * c, vector <string> &parameters)
else else
{ {
if (!parameters.empty() && cmd != "?") if (!parameters.empty() && cmd != "?")
c->con.printerr("Invalid command: %s\n", cmd.c_str()); out.printerr("Invalid command: %s\n", cmd.c_str());
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }

@ -58,15 +58,15 @@ enum revealstate
revealstate revealed = NOT_REVEALED; revealstate revealed = NOT_REVEALED;
command_result reveal(DFHack::Core * c, std::vector<std::string> & params); command_result reveal(color_ostream &out, std::vector<std::string> & params);
command_result unreveal(DFHack::Core * c, std::vector<std::string> & params); command_result unreveal(color_ostream &out, std::vector<std::string> & params);
command_result revtoggle(DFHack::Core * c, std::vector<std::string> & params); command_result revtoggle(color_ostream &out, std::vector<std::string> & params);
command_result revflood(DFHack::Core * c, std::vector<std::string> & params); command_result revflood(color_ostream &out, std::vector<std::string> & params);
command_result nopause(DFHack::Core * c, std::vector<std::string> & params); command_result nopause(color_ostream &out, std::vector<std::string> & params);
DFHACK_PLUGIN("reveal"); DFHACK_PLUGIN("reveal");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal)); commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal));
@ -77,9 +77,9 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
DFHack::World *World =c->getWorld(); DFHack::World *World = Core::getInstance().getWorld();
t_gamemodes gm; t_gamemodes gm;
World->ReadGameMode(gm); World->ReadGameMode(gm);
if(gm.g_mode == GAMEMODE_DWARF) if(gm.g_mode == GAMEMODE_DWARF)
@ -97,12 +97,12 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result nopause (Core * c, std::vector <std::string> & parameters) command_result nopause (color_ostream &out, std::vector <std::string> & parameters)
{ {
if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1")) if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1"))
{ {
@ -110,17 +110,17 @@ command_result nopause (Core * c, std::vector <std::string> & parameters)
nopause_state = 0; nopause_state = 0;
else else
nopause_state = 1; nopause_state = 1;
c->con.print("nopause %sactivated.\n", (nopause_state ? "" : "de")); out.print("nopause %sactivated.\n", (nopause_state ? "" : "de"));
} }
else else
{ {
c->con.print("Disable pausing (doesn't affect pause forced by reveal).\nActivate with 'nopause 1', deactivate with 'nopause 0'.\nCurrent state: %d.\n", nopause_state); out.print("Disable pausing (doesn't affect pause forced by reveal).\nActivate with 'nopause 1', deactivate with 'nopause 0'.\nCurrent state: %d.\n", nopause_state);
} }
return CR_OK; return CR_OK;
} }
void revealAdventure(DFHack::Core * c) void revealAdventure(color_ostream &out)
{ {
for (size_t i = 0; i < world->map.map_blocks.size(); i++) for (size_t i = 0; i < world->map.map_blocks.size(); i++)
{ {
@ -138,10 +138,10 @@ void revealAdventure(DFHack::Core * c)
designations[x][y].bits.pile = 1; designations[x][y].bits.pile = 1;
} }
} }
c->con.print("Local map revealed.\n"); out.print("Local map revealed.\n");
} }
command_result reveal(DFHack::Core * c, std::vector<std::string> & params) command_result reveal(color_ostream &out, std::vector<std::string> & params)
{ {
bool no_hell = true; bool no_hell = true;
bool pause = true; bool pause = true;
@ -151,7 +151,7 @@ command_result reveal(DFHack::Core * c, std::vector<std::string> & params)
no_hell = false; no_hell = false;
else if(params[i] == "help" || params[i] == "?") else if(params[i] == "help" || params[i] == "?")
{ {
c->con.print("Reveals the map, by default ignoring hell.\n" out.print("Reveals the map, by default ignoring hell.\n"
"Options:\n" "Options:\n"
"hell - also reveal hell, while forcing the game to pause.\n" "hell - also reveal hell, while forcing the game to pause.\n"
"demon - reveal hell, do not pause.\n" "demon - reveal hell, do not pause.\n"
@ -168,25 +168,26 @@ command_result reveal(DFHack::Core * c, std::vector<std::string> & params)
no_hell = false; no_hell = false;
pause = false; pause = false;
} }
Console & con = c->con; auto & con = out;
if(revealed != NOT_REVEALED) if(revealed != NOT_REVEALED)
{ {
con.printerr("Map is already revealed or this is a different map.\n"); con.printerr("Map is already revealed or this is a different map.\n");
return CR_FAILURE; return CR_FAILURE;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
DFHack::World *World =c->getWorld();
DFHack::World *World = Core::getInstance().getWorld();
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
t_gamemodes gm; t_gamemodes gm;
World->ReadGameMode(gm); World->ReadGameMode(gm);
if(gm.g_mode == GAMEMODE_ADVENTURE) if(gm.g_mode == GAMEMODE_ADVENTURE)
{ {
revealAdventure(c); revealAdventure(out);
return CR_OK; return CR_OK;
} }
if(gm.g_mode != GAMEMODE_DWARF) if(gm.g_mode != GAMEMODE_DWARF)
@ -237,14 +238,14 @@ command_result reveal(DFHack::Core * c, std::vector<std::string> & params)
return CR_OK; return CR_OK;
} }
command_result unreveal(DFHack::Core * c, std::vector<std::string> & params) command_result unreveal(color_ostream &out, std::vector<std::string> & params)
{ {
Console & con = c->con; auto & con = out;
for(size_t i = 0; i < params.size();i++) for(size_t i = 0; i < params.size();i++)
{ {
if(params[i] == "help" || params[i] == "?") if(params[i] == "help" || params[i] == "?")
{ {
c->con.print("Reverts the previous reveal operation, hiding the map again.\n"); out.print("Reverts the previous reveal operation, hiding the map again.\n");
return CR_OK; return CR_OK;
} }
} }
@ -253,12 +254,12 @@ command_result unreveal(DFHack::Core * c, std::vector<std::string> & params)
con.printerr("There's nothing to revert!\n"); con.printerr("There's nothing to revert!\n");
return CR_FAILURE; return CR_FAILURE;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
DFHack::World *World =c->getWorld(); DFHack::World *World = Core::getInstance().getWorld();
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
t_gamemodes gm; t_gamemodes gm;
@ -294,56 +295,56 @@ command_result unreveal(DFHack::Core * c, std::vector<std::string> & params)
return CR_OK; return CR_OK;
} }
command_result revtoggle (DFHack::Core * c, std::vector<std::string> & params) command_result revtoggle (color_ostream &out, std::vector<std::string> & params)
{ {
for(size_t i = 0; i < params.size();i++) for(size_t i = 0; i < params.size();i++)
{ {
if(params[i] == "help" || params[i] == "?") if(params[i] == "help" || params[i] == "?")
{ {
c->con.print("Toggles between reveal and unreveal.\nCurrently it: "); out.print("Toggles between reveal and unreveal.\nCurrently it: ");
break; break;
} }
} }
if(revealed) if(revealed)
{ {
return unreveal(c,params); return unreveal(out,params);
} }
else else
{ {
return reveal(c,params); return reveal(out,params);
} }
} }
command_result revflood(DFHack::Core * c, std::vector<std::string> & params) command_result revflood(color_ostream &out, std::vector<std::string> & params)
{ {
for(size_t i = 0; i < params.size();i++) for(size_t i = 0; i < params.size();i++)
{ {
if(params[i] == "help" || params[i] == "?") if(params[i] == "help" || params[i] == "?")
{ {
c->con.print("This command hides the whole map. Then, starting from the cursor,\n" out.print("This command hides the whole map. Then, starting from the cursor,\n"
"reveals all accessible tiles. Allows repairing parma-revealed maps.\n" "reveals all accessible tiles. Allows repairing parma-revealed maps.\n"
); );
return CR_OK; return CR_OK;
} }
} }
CoreSuspender suspend(c); CoreSuspender suspend;
uint32_t x_max,y_max,z_max; uint32_t x_max,y_max,z_max;
World * World = c->getWorld(); World * World = Core::getInstance().getWorld();
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
if(revealed != NOT_REVEALED) if(revealed != NOT_REVEALED)
{ {
c->con.printerr("This is only safe to use with non-revealed map.\n"); out.printerr("This is only safe to use with non-revealed map.\n");
return CR_FAILURE; return CR_FAILURE;
} }
t_gamemodes gm; t_gamemodes gm;
World->ReadGameMode(gm); World->ReadGameMode(gm);
if(gm.g_type != GAMETYPE_DWARF_MAIN && gm.g_mode != GAMEMODE_DWARF ) if(gm.g_type != GAMETYPE_DWARF_MAIN && gm.g_mode != GAMEMODE_DWARF )
{ {
c->con.printerr("Only in proper dwarf mode.\n"); out.printerr("Only in proper dwarf mode.\n");
return CR_FAILURE; return CR_FAILURE;
} }
int32_t cx, cy, cz; int32_t cx, cy, cz;
@ -354,7 +355,7 @@ command_result revflood(DFHack::Core * c, std::vector<std::string> & params)
Gui::getCursorCoords(cx,cy,cz); Gui::getCursorCoords(cx,cy,cz);
if(cx == -30000) if(cx == -30000)
{ {
c->con.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n");
return CR_FAILURE; return CR_FAILURE;
} }
DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
@ -362,7 +363,7 @@ command_result revflood(DFHack::Core * c, std::vector<std::string> & params)
df::tiletype tt = MCache->tiletypeAt(xy); df::tiletype tt = MCache->tiletypeAt(xy);
if(isWallTerrain(tt)) if(isWallTerrain(tt))
{ {
c->con.printerr("Point the cursor at some empty space you want to be unhidden.\n"); out.printerr("Point the cursor at some empty space you want to be unhidden.\n");
delete MCache; delete MCache;
return CR_FAILURE; return CR_FAILURE;
} }

@ -42,19 +42,19 @@ bool ignoreSeeds(df::item_flags& f) // seeds with the following flags should not
f.bits.in_job; f.bits.in_job;
}; };
void printHelp(Core& core) // prints help void printHelp(color_ostream &out) // prints help
{ {
core.con.print( out.print(
"Watches the numbers of seeds available and enables/disables seed and plant cooking.\n" "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n"
"Each plant type can be assigned a limit. If their number falls below,\n" "Each plant type can be assigned a limit. If their number falls below,\n"
"the plants and seeds of that type will be excluded from cookery.\n" "the plants and seeds of that type will be excluded from cookery.\n"
"If the number rises above the limit + %i, then cooking will be allowed.\n", buffer "If the number rises above the limit + %i, then cooking will be allowed.\n", buffer
); );
core.con.printerr( out.printerr(
"The plugin needs a fortress to be loaded and will deactivate automatically otherwise.\n" "The plugin needs a fortress to be loaded and will deactivate automatically otherwise.\n"
"You have to reactivate with 'seedwatch start' after you load the game.\n" "You have to reactivate with 'seedwatch start' after you load the game.\n"
); );
core.con.print( out.print(
"Options:\n" "Options:\n"
"seedwatch all - Adds all plants from the abbreviation list to the watch list.\n" "seedwatch all - Adds all plants from the abbreviation list to the watch list.\n"
"seedwatch start - Start watching.\n" "seedwatch start - Start watching.\n"
@ -64,13 +64,13 @@ void printHelp(Core& core) // prints help
); );
if(!abbreviations.empty()) if(!abbreviations.empty())
{ {
core.con.print("You can use these abbreviations for the plant tokens:\n"); out.print("You can use these abbreviations for the plant tokens:\n");
for(map<string, string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) for(map<string, string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i)
{ {
core.con.print("%s -> %s\n", i->first.c_str(), i->second.c_str()); out.print("%s -> %s\n", i->first.c_str(), i->second.c_str());
} }
} }
core.con.print( out.print(
"Examples:\n" "Examples:\n"
"seedwatch MUSHROOM_HELMET_PLUMP 30\n" "seedwatch MUSHROOM_HELMET_PLUMP 30\n"
" add MUSHROOM_HELMET_PLUMP to the watch list, limit = 30\n" " add MUSHROOM_HELMET_PLUMP to the watch list, limit = 30\n"
@ -96,14 +96,9 @@ string searchAbbreviations(string in)
} }
}; };
command_result df_seedwatch(Core* pCore, vector<string>& parameters) command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{ {
Core& core = *pCore; CoreSuspender suspend;
if(!core.isValid())
{
return CR_FAILURE;
}
CoreSuspender suspend(pCore);
map<string, t_materialIndex> materialsReverser; map<string, t_materialIndex> materialsReverser;
for(size_t i = 0; i < world->raws.plants.all.size(); ++i) for(size_t i = 0; i < world->raws.plants.all.size(); ++i)
@ -111,7 +106,7 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
materialsReverser[world->raws.plants.all[i]->id] = i; materialsReverser[world->raws.plants.all[i]->id] = i;
} }
World *w = core.getWorld(); World *w = Core::getInstance().getWorld();
t_gamemodes gm; t_gamemodes gm;
w->ReadGameMode(gm);// FIXME: check return value w->ReadGameMode(gm);// FIXME: check return value
@ -119,7 +114,7 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN) if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN)
{ {
// just print the help // just print the help
printHelp(core); printHelp(out);
return CR_OK; return CR_OK;
} }
@ -128,50 +123,50 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
switch(parameters.size()) switch(parameters.size())
{ {
case 0: case 0:
printHelp(core); printHelp(out);
break; break;
case 1: case 1:
par = parameters[0]; par = parameters[0];
if(par == "help") printHelp(core); if(par == "help") printHelp(out);
else if(par == "?") printHelp(core); else if(par == "?") printHelp(out);
else if(par == "start") else if(par == "start")
{ {
running = true; running = true;
core.con.print("seedwatch supervision started.\n"); out.print("seedwatch supervision started.\n");
} }
else if(par == "stop") else if(par == "stop")
{ {
running = false; running = false;
core.con.print("seedwatch supervision stopped.\n"); out.print("seedwatch supervision stopped.\n");
} }
else if(par == "clear") else if(par == "clear")
{ {
Kitchen::clearLimits(); Kitchen::clearLimits();
core.con.print("seedwatch watchlist cleared\n"); out.print("seedwatch watchlist cleared\n");
} }
else if(par == "info") else if(par == "info")
{ {
core.con.print("seedwatch Info:\n"); out.print("seedwatch Info:\n");
if(running) if(running)
{ {
core.con.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n"); out.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n");
} }
else else
{ {
core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); out.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n");
} }
map<t_materialIndex, unsigned int> watchMap; map<t_materialIndex, unsigned int> watchMap;
Kitchen::fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
if(watchMap.empty()) if(watchMap.empty())
{ {
core.con.print("The watch list is empty.\n"); out.print("The watch list is empty.\n");
} }
else else
{ {
core.con.print("The watch list is:\n"); out.print("The watch list is:\n");
for(map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) for(map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i)
{ {
core.con.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second); out.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second);
} }
} }
} }
@ -179,22 +174,22 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
{ {
map<t_materialIndex, unsigned int> watchMap; map<t_materialIndex, unsigned int> watchMap;
Kitchen::fillWatchMap(watchMap); Kitchen::fillWatchMap(watchMap);
Kitchen::debug_print(core); Kitchen::debug_print(out);
} }
/* /*
else if(par == "dumpmaps") else if(par == "dumpmaps")
{ {
core.con.print("Plants:\n"); out.print("Plants:\n");
for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++) for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++)
{ {
auto t = materialsModule.df_organic->at(i->first); auto t = materialsModule.df_organic->at(i->first);
core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat); out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat);
} }
core.con.print("Seeds:\n"); out.print("Seeds:\n");
for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++) for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++)
{ {
auto t = materialsModule.df_organic->at(i->first); auto t = materialsModule.df_organic->at(i->first);
core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed); out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed);
} }
} }
*/ */
@ -204,11 +199,11 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
if(materialsReverser.count(token) > 0) if(materialsReverser.count(token) > 0)
{ {
Kitchen::removeLimit(materialsReverser[token]); Kitchen::removeLimit(materialsReverser[token]);
core.con.print("%s is not being watched\n", token.c_str()); out.print("%s is not being watched\n", token.c_str());
} }
else else
{ {
core.con.print("%s has not been found as a material.\n", token.c_str()); out.print("%s has not been found as a material.\n", token.c_str());
} }
} }
break; break;
@ -228,16 +223,16 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
if(materialsReverser.count(token) > 0) if(materialsReverser.count(token) > 0)
{ {
Kitchen::setLimit(materialsReverser[token], limit); Kitchen::setLimit(materialsReverser[token], limit);
core.con.print("%s is being watched.\n", token.c_str()); out.print("%s is being watched.\n", token.c_str());
} }
else else
{ {
core.con.print("%s has not been found as a material.\n", token.c_str()); out.print("%s has not been found as a material.\n", token.c_str());
} }
} }
break; break;
default: default:
printHelp(core); printHelp(out);
break; break;
} }
@ -246,7 +241,7 @@ command_result df_seedwatch(Core* pCore, vector<string>& parameters)
DFHACK_PLUGIN("seedwatch"); DFHACK_PLUGIN("seedwatch");
DFhackCExport command_result plugin_init(Core* pCore, vector<PluginCommand>& commands) DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginCommand>& commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch));
@ -275,13 +270,13 @@ DFhackCExport command_result plugin_init(Core* pCore, vector<PluginCommand>& com
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_LOADED: case SC_GAME_LOADED:
case SC_GAME_UNLOADED: case SC_GAME_UNLOADED:
if (running) if (running)
pCore->con.printerr("seedwatch deactivated due to game load/unload\n"); out.printerr("seedwatch deactivated due to game load/unload\n");
running = false; running = false;
break; break;
default: default:
@ -291,7 +286,7 @@ DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_even
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onupdate(Core* pCore) DFhackCExport command_result plugin_onupdate(color_ostream &out)
{ {
if (running) if (running)
{ {
@ -301,8 +296,7 @@ DFhackCExport command_result plugin_onupdate(Core* pCore)
return CR_OK; return CR_OK;
counter = 0; counter = 0;
Core& core = *pCore; World *w = Core::getInstance().getWorld();
World *w = core.getWorld();
t_gamemodes gm; t_gamemodes gm;
w->ReadGameMode(gm);// FIXME: check return value w->ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode // if game mode isn't fortress mode
@ -310,7 +304,7 @@ DFhackCExport command_result plugin_onupdate(Core* pCore)
{ {
// stop running. // stop running.
running = false; running = false;
core.con.printerr("seedwatch deactivated due to game mode switch\n"); out.printerr("seedwatch deactivated due to game mode switch\n");
return CR_OK; return CR_OK;
} }
// this is dwarf mode, continue // this is dwarf mode, continue

@ -10,13 +10,13 @@ using namespace DFHack;
// Here go all the command declarations... // Here go all the command declarations...
// mostly to allow having the mandatory stuff on top of the file and commands on the bottom // mostly to allow having the mandatory stuff on top of the file and commands on the bottom
command_result server (Core * c, std::vector <std::string> & parameters); command_result server (color_ostream &out, std::vector <std::string> & parameters);
// A plugins must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll // A plugins must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll
DFHACK_PLUGIN("server"); DFHACK_PLUGIN("server");
// Mandatory init function. If you have some global state, create it here. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.clear(); commands.clear();
@ -27,7 +27,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
} }
// This is called right before the plugin library is removed from memory. // This is called right before the plugin library is removed from memory.
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
// You *MUST* kill all threads you created before this returns. // You *MUST* kill all threads you created before this returns.
// If everythin fails, just return CR_FAILURE. Your plugin will be // If everythin fails, just return CR_FAILURE. Your plugin will be
@ -36,7 +36,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
} }
// This is WRONG and STUPID. Never use this as an example! // This is WRONG and STUPID. Never use this as an example!
command_result server (Core * c, std::vector <std::string> & parameters) command_result server (color_ostream &out, std::vector <std::string> & parameters)
{ {
// It's nice to provide a 'help' option for your command. // It's nice to provide a 'help' option for your command.
// It's also nice to print the same help if you get invalid options from the user instead of just acting strange // It's also nice to print the same help if you get invalid options from the user instead of just acting strange
@ -46,7 +46,7 @@ command_result server (Core * c, std::vector <std::string> & parameters)
{ {
// Core has a handle to the console. The console is thread-safe. // Core has a handle to the console. The console is thread-safe.
// Only one thing can read from it at a time though... // Only one thing can read from it at a time though...
c->con.print("This command is a simple Hello World example for zeromq!\n"); out.print("This command is a simple Hello World example for zeromq!\n");
return CR_OK; return CR_OK;
} }
} }
@ -61,7 +61,7 @@ command_result server (Core * c, std::vector <std::string> & parameters)
// Wait for next request from client // Wait for next request from client
socket.recv (&request); socket.recv (&request);
c->con.print("Received Hello\n"); out.print("Received Hello\n");
// Do some 'work' // Do some 'work'
#ifdef LINUX_BUILD #ifdef LINUX_BUILD

@ -26,18 +26,18 @@ using namespace df::enums;
using df::global::world; using df::global::world;
command_result df_showmood (Core * c, vector <string> & parameters) command_result df_showmood (color_ostream &out, vector <string> & parameters)
{ {
if (!parameters.empty()) if (!parameters.empty())
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
if (!Translation::IsValid()) if (!Translation::IsValid())
{ {
c->con.printerr("Translation data unavailable!\n"); out.printerr("Translation data unavailable!\n");
return CR_FAILURE; return CR_FAILURE;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
bool found = false; bool found = false;
for (df::job_list_link *cur = world->job_list.next; cur != NULL; cur = cur->next) for (df::job_list_link *cur = world->job_list.next; cur != NULL; cur = cur->next)
@ -58,27 +58,27 @@ command_result df_showmood (Core * c, vector <string> & parameters)
} }
if (!unit) if (!unit)
{ {
c->con.printerr("Found strange mood not attached to any dwarf!\n"); out.printerr("Found strange mood not attached to any dwarf!\n");
continue; continue;
} }
if (unit->mood == mood_type::None) if (unit->mood == mood_type::None)
{ {
c->con.printerr("Dwarf with strange mood does not have a mood type!\n"); out.printerr("Dwarf with strange mood does not have a mood type!\n");
continue; continue;
} }
c->con.print("%s is currently ", Translation::TranslateName(&unit->name, false).c_str()); out.print("%s is currently ", Translation::TranslateName(&unit->name, false).c_str());
switch (unit->mood) switch (unit->mood)
{ {
case mood_type::Macabre: case mood_type::Macabre:
c->con.print("in a macabre mood"); out.print("in a macabre mood");
if (job->job_type != job_type::StrangeMoodBrooding) if (job->job_type != job_type::StrangeMoodBrooding)
c->con.print(" (but isn't actually in a macabre mood?)"); out.print(" (but isn't actually in a macabre mood?)");
break; break;
case mood_type::Fell: case mood_type::Fell:
c->con.print("in a fell mood"); out.print("in a fell mood");
if (job->job_type != job_type::StrangeMoodFell) if (job->job_type != job_type::StrangeMoodFell)
c->con.print(" (but isn't actually in a fell mood?)"); out.print(" (but isn't actually in a fell mood?)");
break; break;
case mood_type::Fey: case mood_type::Fey:
@ -87,77 +87,80 @@ command_result df_showmood (Core * c, vector <string> & parameters)
switch (unit->mood) switch (unit->mood)
{ {
case mood_type::Fey: case mood_type::Fey:
c->con.print("in a fey mood"); out.print("in a fey mood");
break; break;
case mood_type::Secretive: case mood_type::Secretive:
c->con.print("in a secretive mood"); out.print("in a secretive mood");
break; break;
case mood_type::Possessed: case mood_type::Possessed:
c->con.print("possessed"); out.print("possessed");
break; break;
} }
c->con.print(" with intent to "); out.print(" with intent to ");
switch (job->job_type) switch (job->job_type)
{ {
case job_type::StrangeMoodCrafter: case job_type::StrangeMoodCrafter:
c->con.print("become a Craftsdwarf (or Engraver)"); out.print("become a Craftsdwarf (or Engraver)");
break; break;
case job_type::StrangeMoodJeweller: case job_type::StrangeMoodJeweller:
c->con.print("become a Jeweler"); out.print("become a Jeweler");
break; break;
case job_type::StrangeMoodForge: case job_type::StrangeMoodForge:
c->con.print("become a Metalworker"); out.print("become a Metalworker");
break; break;
case job_type::StrangeMoodMagmaForge: case job_type::StrangeMoodMagmaForge:
c->con.print("become a Metalworker using a Magma Forge"); out.print("become a Metalworker using a Magma Forge");
break; break;
case job_type::StrangeMoodCarpenter: case job_type::StrangeMoodCarpenter:
c->con.print("become a Carpenter"); out.print("become a Carpenter");
break; break;
case job_type::StrangeMoodMason: case job_type::StrangeMoodMason:
c->con.print("become a Mason (or Miner)"); out.print("become a Mason (or Miner)");
break; break;
case job_type::StrangeMoodBowyer: case job_type::StrangeMoodBowyer:
c->con.print("become a Bowyer"); out.print("become a Bowyer");
break; break;
case job_type::StrangeMoodTanner: case job_type::StrangeMoodTanner:
c->con.print("become a Leatherworker (or Tanner)"); out.print("become a Leatherworker (or Tanner)");
break; break;
case job_type::StrangeMoodWeaver: case job_type::StrangeMoodWeaver:
c->con.print("become a Clothier (or Weaver)"); out.print("become a Clothier (or Weaver)");
break; break;
case job_type::StrangeMoodGlassmaker: case job_type::StrangeMoodGlassmaker:
c->con.print("become a Glassmaker"); out.print("become a Glassmaker");
break; break;
case job_type::StrangeMoodMechanics: case job_type::StrangeMoodMechanics:
c->con.print("become a Mechanic"); out.print("become a Mechanic");
break; break;
case job_type::StrangeMoodBrooding: case job_type::StrangeMoodBrooding:
c->con.print("enter a macabre mood?"); out.print("enter a macabre mood?");
break; break;
case job_type::StrangeMoodFell: case job_type::StrangeMoodFell:
c->con.print("enter a fell mood?"); out.print("enter a fell mood?");
break;
default:
out.print("do something else...");
break; break;
} }
break; break;
default: default:
c->con.print("insane?"); out.print("insane?");
break; break;
} }
if (building) if (building)
{ {
string name; string name;
building->getName(&name); building->getName(&name);
c->con.print(" and has claimed a %s\n", name.c_str()); out.print(" and has claimed a %s\n", name.c_str());
} }
else else
c->con.print(" and has not yet claimed a workshop\n"); out.print(" and has not yet claimed a workshop\n");
for (size_t i = 0; i < job->job_items.size(); i++) for (size_t i = 0; i < job->job_items.size(); i++)
{ {
df::job_item *item = job->job_items[i]; df::job_item *item = job->job_items[i];
c->con.print("Item %i: ", i + 1); out.print("Item %i: ", i + 1);
MaterialInfo matinfo(item->mat_type, item->mat_index); MaterialInfo matinfo(item->mat_type, item->mat_index);
@ -166,37 +169,37 @@ command_result df_showmood (Core * c, vector <string> & parameters)
switch (item->item_type) switch (item->item_type)
{ {
case item_type::BOULDER: case item_type::BOULDER:
c->con.print("%s boulder", mat_name.c_str()); out.print("%s boulder", mat_name.c_str());
break; break;
case item_type::BLOCKS: case item_type::BLOCKS:
c->con.print("%s blocks", mat_name.c_str()); out.print("%s blocks", mat_name.c_str());
break; break;
case item_type::WOOD: case item_type::WOOD:
c->con.print("%s logs", mat_name.c_str()); out.print("%s logs", mat_name.c_str());
break; break;
case item_type::BAR: case item_type::BAR:
if (matinfo.isInorganicWildcard()) if (matinfo.isInorganicWildcard())
mat_name = "metal"; mat_name = "metal";
if (matinfo.inorganic && matinfo.inorganic->flags.is_set(inorganic_flags::WAFERS)) if (matinfo.inorganic && matinfo.inorganic->flags.is_set(inorganic_flags::WAFERS))
c->con.print("%s wafers", mat_name.c_str()); out.print("%s wafers", mat_name.c_str());
else else
c->con.print("%s bars", mat_name.c_str()); out.print("%s bars", mat_name.c_str());
break; break;
case item_type::SMALLGEM: case item_type::SMALLGEM:
c->con.print("%s cut gems", mat_name.c_str()); out.print("%s cut gems", mat_name.c_str());
break; break;
case item_type::ROUGH: case item_type::ROUGH:
if (matinfo.isAnyInorganic()) if (matinfo.isAnyInorganic())
{ {
if (matinfo.isInorganicWildcard()) if (matinfo.isInorganicWildcard())
mat_name = "any"; mat_name = "any";
c->con.print("%s rough gems", mat_name.c_str()); out.print("%s rough gems", mat_name.c_str());
} }
else else
c->con.print("raw %s", mat_name.c_str()); out.print("raw %s", mat_name.c_str());
break; break;
case item_type::SKIN_TANNED: case item_type::SKIN_TANNED:
c->con.print("%s leather", mat_name.c_str()); out.print("%s leather", mat_name.c_str());
break; break;
case item_type::CLOTH: case item_type::CLOTH:
if (matinfo.isNone()) if (matinfo.isNone())
@ -208,36 +211,36 @@ command_result df_showmood (Core * c, vector <string> & parameters)
else if (item->flags2.bits.yarn) else if (item->flags2.bits.yarn)
mat_name = "any yarn"; mat_name = "any yarn";
} }
c->con.print("%s cloth", mat_name.c_str()); out.print("%s cloth", mat_name.c_str());
break; break;
case item_type::REMAINS: case item_type::REMAINS:
c->con.print("%s remains", mat_name.c_str()); out.print("%s remains", mat_name.c_str());
break; break;
case item_type::CORPSE: case item_type::CORPSE:
c->con.print("%s %scorpse", mat_name.c_str(), (item->flags1.bits.murdered ? "murdered " : "")); out.print("%s %scorpse", mat_name.c_str(), (item->flags1.bits.murdered ? "murdered " : ""));
break; break;
case item_type::NONE: case item_type::NONE:
if (item->flags2.bits.body_part) if (item->flags2.bits.body_part)
{ {
if (item->flags2.bits.bone) if (item->flags2.bits.bone)
c->con.print("%s bones", mat_name.c_str()); out.print("%s bones", mat_name.c_str());
else if (item->flags2.bits.shell) else if (item->flags2.bits.shell)
c->con.print("%s shells", mat_name.c_str()); out.print("%s shells", mat_name.c_str());
else if (item->flags2.bits.horn) else if (item->flags2.bits.horn)
c->con.print("%s horns", mat_name.c_str()); out.print("%s horns", mat_name.c_str());
else if (item->flags2.bits.pearl) else if (item->flags2.bits.pearl)
c->con.print("%s pearls", mat_name.c_str()); out.print("%s pearls", mat_name.c_str());
else if (item->flags2.bits.ivory_tooth) else if (item->flags2.bits.ivory_tooth)
c->con.print("%s ivory/teeth", mat_name.c_str()); out.print("%s ivory/teeth", mat_name.c_str());
else else
c->con.print("%s unknown body parts (%s:%s:%s)", out.print("%s unknown body parts (%s:%s:%s)",
mat_name.c_str(), mat_name.c_str(),
bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(), bitfieldToString(item->flags2).c_str(),
bitfieldToString(item->flags3).c_str()); bitfieldToString(item->flags3).c_str());
} }
else else
c->con.print("indeterminate %s item (%s:%s:%s)", out.print("indeterminate %s item (%s:%s:%s)",
mat_name.c_str(), mat_name.c_str(),
bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(), bitfieldToString(item->flags2).c_str(),
@ -247,7 +250,7 @@ command_result df_showmood (Core * c, vector <string> & parameters)
{ {
ItemTypeInfo itinfo(item->item_type, item->item_subtype); ItemTypeInfo itinfo(item->item_type, item->item_subtype);
c->con.print("item %s material %s flags (%s:%s:%s)", out.print("item %s material %s flags (%s:%s:%s)",
itinfo.toString().c_str(), mat_name.c_str(), itinfo.toString().c_str(), mat_name.c_str(),
bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(), bitfieldToString(item->flags2).c_str(),
@ -256,25 +259,25 @@ command_result df_showmood (Core * c, vector <string> & parameters)
} }
} }
c->con.print(", quantity %i\n", item->quantity); out.print(", quantity %i\n", item->quantity);
} }
} }
if (!found) if (!found)
c->con.print("No strange moods currently active.\n"); out.print("No strange moods currently active.\n");
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN("showmood"); DFHACK_PLUGIN("showmood");
DFhackCExport command_result plugin_init (Core *c, std::vector<PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood)); commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }

@ -19,14 +19,14 @@ using namespace df::enums;
// Here go all the command declarations... // Here go all the command declarations...
// mostly to allow having the mandatory stuff on top of the file and commands on the bottom // mostly to allow having the mandatory stuff on top of the file and commands on the bottom
command_result skeleton (Core * c, std::vector <std::string> & parameters); command_result skeleton (color_ostream &out, std::vector <std::string> & parameters);
// A plugin must be able to return its name and version. // A plugin must be able to return its name and version.
// The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case // The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case
DFHACK_PLUGIN("skeleton"); DFHACK_PLUGIN("skeleton");
// Mandatory init function. If you have some global state, create it here. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.clear(); commands.clear();
@ -43,7 +43,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
} }
// This is called right before the plugin library is removed from memory. // This is called right before the plugin library is removed from memory.
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
// You *MUST* kill all threads you created before this returns. // You *MUST* kill all threads you created before this returns.
// If everything fails, just return CR_FAILURE. Your plugin will be // If everything fails, just return CR_FAILURE. Your plugin will be
@ -55,7 +55,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
// Invoked with DF suspended, and always before the matching plugin_onupdate. // Invoked with DF suspended, and always before the matching plugin_onupdate.
// More event codes may be added in the future. // More event codes may be added in the future.
/* /*
DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_LOADED: case SC_GAME_LOADED:
@ -74,7 +74,7 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
// Whatever you put here will be done in each game step. Don't abuse it. // Whatever you put here will be done in each game step. Don't abuse it.
// It's optional, so you can just comment it out like this if you don't need it. // It's optional, so you can just comment it out like this if you don't need it.
/* /*
DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
// whetever. You don't need to suspend DF execution here. // whetever. You don't need to suspend DF execution here.
return CR_OK; return CR_OK;
@ -82,7 +82,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c )
*/ */
// A command! It sits around and looks pretty. And it's nice and friendly. // A command! It sits around and looks pretty. And it's nice and friendly.
command_result skeleton (Core * c, std::vector <std::string> & parameters) command_result skeleton (color_ostream &out, std::vector <std::string> & parameters)
{ {
// It's nice to print a help message you get invalid options // It's nice to print a help message you get invalid options
// from the user instead of just acting strange. // from the user instead of just acting strange.
@ -96,9 +96,9 @@ command_result skeleton (Core * c, std::vector <std::string> & parameters)
// Suspend this thread until DF has time for us. If you // Suspend this thread until DF has time for us. If you
// use CoreSuspender, it'll automatically resume DF when // use CoreSuspender, it'll automatically resume DF when
// execution leaves the current scope. // execution leaves the current scope.
CoreSuspender suspend(c); CoreSuspender suspend;
// Actually do something here. Yay. // Actually do something here. Yay.
c->con.print("Hello! I do nothing, remember?\n"); out.print("Hello! I do nothing, remember?\n");
// Give control back to DF. // Give control back to DF.
return CR_OK; return CR_OK;
} }

@ -22,12 +22,12 @@ using df::global::selection_rect;
using df::building_stockpilest; using df::building_stockpilest;
static command_result copystock(Core *c, vector <string> & parameters); static command_result copystock(color_ostream &out, vector <string> & parameters);
static bool copystock_guard(Core *c, df::viewscreen *top); static bool copystock_guard(df::viewscreen *top);
DFHACK_PLUGIN("stockpiles"); DFHACK_PLUGIN("stockpiles");
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
if (world && ui) { if (world && ui) {
@ -47,16 +47,16 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
static bool copystock_guard(Core *c, df::viewscreen *top) static bool copystock_guard(df::viewscreen *top)
{ {
using namespace ui_sidebar_mode; using namespace ui_sidebar_mode;
if (!Gui::dwarfmode_hotkey(c,top)) if (!Gui::dwarfmode_hotkey(top))
return false; return false;
switch (ui->main.mode) { switch (ui->main.mode) {
@ -70,7 +70,7 @@ static bool copystock_guard(Core *c, df::viewscreen *top)
} }
} }
static command_result copystock(Core * c, vector <string> & parameters) static command_result copystock(color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
@ -80,14 +80,14 @@ static command_result copystock(Core * c, vector <string> & parameters)
ui->main.mode = ui_sidebar_mode::QueryBuilding; ui->main.mode = ui_sidebar_mode::QueryBuilding;
selection_rect->start_x = -30000; selection_rect->start_x = -30000;
c->con << "Switched back to query building." << endl; out << "Switched back to query building." << endl;
return CR_OK; return CR_OK;
} }
building_stockpilest *sp = virtual_cast<building_stockpilest>(world->selected_building); building_stockpilest *sp = virtual_cast<building_stockpilest>(world->selected_building);
if (!sp) if (!sp)
{ {
c->con.printerr("Selected building isn't a stockpile.\n"); out.printerr("Selected building isn't a stockpile.\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
@ -95,6 +95,6 @@ static command_result copystock(Core * c, vector <string> & parameters)
ui->main.mode = ui_sidebar_mode::Stockpiles; ui->main.mode = ui_sidebar_mode::Stockpiles;
world->selected_stockpile_type = stockpile_category::Custom; world->selected_stockpile_type = stockpile_category::Custom;
c->con << "Stockpile options copied." << endl; out << "Stockpile options copied." << endl;
return CR_OK; return CR_OK;
} }

@ -1 +1 @@
Subproject commit 34183f96b86394895975fb59ae3c4673cd78f502 Subproject commit f05386bae01d1840bdc889f30253ed50ee892860

@ -633,11 +633,11 @@ public:
CommandHistory tiletypes_hist; CommandHistory tiletypes_hist;
command_result df_tiletypes (Core * c, vector <string> & parameters); command_result df_tiletypes (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("tiletypes"); DFHACK_PLUGIN("tiletypes");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
tiletypes_hist.load("tiletypes.history"); tiletypes_hist.load("tiletypes.history");
commands.clear(); commands.clear();
@ -645,13 +645,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
tiletypes_hist.save("tiletypes.history"); tiletypes_hist.save("tiletypes.history");
return CR_OK; return CR_OK;
} }
command_result df_tiletypes (Core * c, vector <string> & parameters) command_result df_tiletypes (color_ostream &out, vector <string> & parameters)
{ {
uint32_t x_max = 0, y_max = 0, z_max = 0; uint32_t x_max = 0, y_max = 0, z_max = 0;
int32_t x = 0, y = 0, z = 0; int32_t x = 0, y = 0, z = 0;
@ -660,7 +660,7 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("This tool allows painting tiles types with a brush, using an optional filter.\n" out.print("This tool allows painting tiles types with a brush, using an optional filter.\n"
"The tool is interactive, similarly to the liquids tool.\n" "The tool is interactive, similarly to the liquids tool.\n"
"Further help is available inside.\n" "Further help is available inside.\n"
); );
@ -668,16 +668,19 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
} }
} }
assert(out.is_console());
Console &con = static_cast<Console&>(out);
TileType filter, paint; TileType filter, paint;
Brush *brush = new RectangleBrush(1,1); Brush *brush = new RectangleBrush(1,1);
bool end = false; bool end = false;
std::string brushname = "point"; std::string brushname = "point";
int width = 1, height = 1, z_levels = 1; int width = 1, height = 1, z_levels = 1;
c->con << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; con << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;
c->con.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n"); con.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n");
while (!end) while (!end)
{ {
c->con << "Filter: " << filter << std::endl con << "Filter: " << filter << std::endl
<< "Paint: " << paint << std::endl << "Paint: " << paint << std::endl
<< "Brush: " << brushname << std::endl; << "Brush: " << brushname << std::endl;
@ -686,7 +689,7 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
std::string option = ""; std::string option = "";
std::string value = ""; std::string value = "";
c->con.lineedit("tiletypes> ",input,tiletypes_hist); con.lineedit("tiletypes> ",input,tiletypes_hist);
tiletypes_hist.add(input); tiletypes_hist.add(input);
std::istringstream ss(input); std::istringstream ss(input);
ss >> command >> option >> value; ss >> command >> option >> value;
@ -695,7 +698,7 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
if (command == "help" || command == "?") if (command == "help" || command == "?")
{ {
help(c->con,option); help(con,option);
} }
else if (command == "quit" || command == "q") else if (command == "quit" || command == "q")
{ {
@ -720,19 +723,19 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
std::stringstream ss; std::stringstream ss;
CommandHistory hist; CommandHistory hist;
ss << "Set range width <" << width << "> "; ss << "Set range width <" << width << "> ";
c->con.lineedit(ss.str(),command,hist); con.lineedit(ss.str(),command,hist);
width = command == "" ? width : toint(command); width = command == "" ? width : toint(command);
if (width < 1) width = 1; if (width < 1) width = 1;
ss.str(""); ss.str("");
ss << "Set range height <" << height << "> "; ss << "Set range height <" << height << "> ";
c->con.lineedit(ss.str(),command,hist); con.lineedit(ss.str(),command,hist);
height = command == "" ? height : toint(command); height = command == "" ? height : toint(command);
if (height < 1) height = 1; if (height < 1) height = 1;
ss.str(""); ss.str("");
ss << "Set range z-levels <" << z_levels << "> "; ss << "Set range z-levels <" << z_levels << "> ";
c->con.lineedit(ss.str(),command,hist); con.lineedit(ss.str(),command,hist);
z_levels = command == "" ? z_levels : toint(command); z_levels = command == "" ? z_levels : toint(command);
if (z_levels < 1) z_levels = 1; if (z_levels < 1) z_levels = 1;
@ -763,29 +766,30 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
{ {
if (paint.empty()) if (paint.empty())
{ {
c->con.printerr("Set the paint first.\n"); con.printerr("Set the paint first.\n");
continue; continue;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); con.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
Maps::getSize(x_max, y_max, z_max); Maps::getSize(x_max, y_max, z_max);
if (!Gui::getCursorCoords(x,y,z)) if (!Gui::getCursorCoords(x,y,z))
{ {
c->con.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n"); con.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n");
return CR_FAILURE; return CR_FAILURE;
} }
c->con.print("Cursor coords: (%d, %d, %d)\n",x,y,z); con.print("Cursor coords: (%d, %d, %d)\n",x,y,z);
DFHack::DFCoord cursor(x,y,z); DFHack::DFCoord cursor(x,y,z);
MapExtras::MapCache map; MapExtras::MapCache map;
coord_vec all_tiles = brush->points(map, cursor); coord_vec all_tiles = brush->points(map, cursor);
c->con.print("working...\n"); con.print("working...\n");
for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter) for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter)
{ {
@ -895,11 +899,11 @@ command_result df_tiletypes (Core * c, vector <string> & parameters)
if (map.WriteAll()) if (map.WriteAll())
{ {
c->con.print("OK\n"); con.print("OK\n");
} }
else else
{ {
c->con.printerr("Something failed horribly! RUN!\n"); con.printerr("Something failed horribly! RUN!\n");
} }
} }
} }

@ -17,23 +17,23 @@ using namespace DFHack;
using namespace df::enums; using namespace df::enums;
using df::global::world; using df::global::world;
command_result tubefill(DFHack::Core * c, std::vector<std::string> & params); command_result tubefill(color_ostream &out, std::vector<std::string> & params);
DFHACK_PLUGIN("tubefill"); DFHACK_PLUGIN("tubefill");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill)); commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill));
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result tubefill(DFHack::Core * c, std::vector<std::string> & params) command_result tubefill(color_ostream &out, std::vector<std::string> & params)
{ {
uint64_t count = 0; uint64_t count = 0;
@ -41,16 +41,18 @@ command_result tubefill(DFHack::Core * c, std::vector<std::string> & params)
{ {
if(params[i] == "help" || params[i] == "?") if(params[i] == "help" || params[i] == "?")
{ {
c->con.print("Replenishes mined out adamantine and hollow adamantine tubes.\n" out.print("Replenishes mined out adamantine and hollow adamantine tubes.\n"
"May cause !!FUN!!\n" "May cause !!FUN!!\n"
); );
return CR_OK; return CR_OK;
} }
} }
CoreSuspender suspend(c);
CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -102,6 +104,6 @@ command_result tubefill(DFHack::Core * c, std::vector<std::string> & params)
} }
} }
} }
c->con.print("Found and changed %d tiles.\n", count); out.print("Found and changed %d tiles.\n", count);
return CR_OK; return CR_OK;
} }

@ -0,0 +1,121 @@
// A container for random minor tweaks that don't fit anywhere else,
// in order to avoid creating lots of plugins and polluting the namespace.
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "modules/Gui.h"
#include "DataDefs.h"
#include "df/ui.h"
#include "df/world.h"
#include "df/squad.h"
#include "df/unit.h"
#include "df/unit_soul.h"
#include "df/historical_entity.h"
#include "df/historical_figure.h"
#include "df/historical_figure_info.h"
#include "df/assumed_identity.h"
#include "df/language_name.h"
#include "df/death_info.h"
#include "df/criminal_case.h"
#include <stdlib.h>
using std::vector;
using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
using df::global::ui;
using df::global::world;
using namespace DFHack::Gui;
static command_result tweak(color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("tweak");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand(
"tweak", "Various tweaks for minor bugs.", tweak, false,
" tweak clear-missing\n"
" Remove the missing status from the selected unit.\n"
" tweak lair\n"
" Mark the map as monster lair, preventing item scatter on reclaim.\n"
));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown (color_ostream &out)
{
return CR_OK;
}
static command_result lair(color_ostream &out, std::vector<std::string> & params);
static command_result tweak(color_ostream &out, vector <string> &parameters)
{
CoreSuspender suspend;
if (parameters.empty())
return CR_WRONG_USAGE;
string cmd = parameters[0];
if (cmd == "clear-missing")
{
df::unit *unit = getSelectedUnit(out);
if (!unit)
return CR_FAILURE;
auto death = df::death_info::find(unit->counters.death_id);
if (death)
{
death->flags.bits.discovered = true;
auto crime = df::criminal_case::find(death->crime_id);
if (crime)
crime->flags.bits.discovered = true;
}
}
else if(cmd == "lair")
{
return lair(out,parameters);
}
else return CR_WRONG_USAGE;
return CR_OK;
}
#include "modules/Maps.h"
command_result lair(color_ostream &out, std::vector<std::string> & params)
{
if (!Maps::IsValid())
{
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
uint32_t x_max,y_max,z_max;
Maps::getSize(x_max,y_max,z_max);
for (size_t i = 0; i < world->map.map_blocks.size(); i++)
{
df::map_block *block = world->map.map_blocks[i];
DFHack::occupancies40d & occupancies = block->occupancy;
// for each tile in block
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
{
// set to revealed
occupancies[x][y].bits.monster_lair = true;
}
}
out.print("Map monsterized.\n");
return CR_OK;
}

@ -16,16 +16,16 @@ using std::stack;
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
command_result vdig (Core * c, vector <string> & parameters); command_result vdig (color_ostream &out, vector <string> & parameters);
command_result vdigx (Core * c, vector <string> & parameters); command_result vdigx (color_ostream &out, vector <string> & parameters);
command_result autodig (Core * c, vector <string> & parameters); command_result autodig (color_ostream &out, vector <string> & parameters);
command_result expdig (Core * c, vector <string> & parameters); command_result expdig (color_ostream &out, vector <string> & parameters);
command_result digcircle (Core *c, vector <string> & parameters); command_result digcircle (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("vdig"); DFHACK_PLUGIN("vdig");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -45,7 +45,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
@ -79,12 +79,12 @@ bool dig (MapExtras::MapCache & MCache,
return false; return false;
if(x == 0 || x == x_max * 16 - 1) if(x == 0 || x == x_max * 16 - 1)
{ {
//c->con.print("not digging map border\n"); //out.print("not digging map border\n");
return false; return false;
} }
if(y == 0 || y == y_max * 16 - 1) if(y == 0 || y == y_max * 16 - 1)
{ {
//c->con.print("not digging map border\n"); //out.print("not digging map border\n");
return false; return false;
} }
df::tiletype tt = MCache.tiletypeAt(at); df::tiletype tt = MCache.tiletypeAt(at);
@ -177,7 +177,7 @@ bool lineY (MapExtras::MapCache & MCache,
return true; return true;
}; };
command_result digcircle (Core * c, vector <string> & parameters) command_result digcircle (color_ostream &out, vector <string> & parameters)
{ {
static bool filled = false; static bool filled = false;
static circle_what what = circle_set; static circle_what what = circle_set;
@ -244,7 +244,7 @@ command_result digcircle (Core * c, vector <string> & parameters)
diameter = -diameter; diameter = -diameter;
if(force_help || diameter == 0) if(force_help || diameter == 0)
{ {
c->con.print( out.print(
"A command for easy designation of filled and hollow circles.\n" "A command for easy designation of filled and hollow circles.\n"
"\n" "\n"
"Options:\n" "Options:\n"
@ -272,10 +272,10 @@ command_result digcircle (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
int32_t cx, cy, cz; int32_t cx, cy, cz;
CoreSuspender suspend(c); CoreSuspender suspend;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -285,7 +285,7 @@ command_result digcircle (Core * c, vector <string> & parameters)
MapExtras::MapCache MCache; MapExtras::MapCache MCache;
if(!Gui::getCursorCoords(cx,cy,cz) || cx == -30000) if(!Gui::getCursorCoords(cx,cy,cz) || cx == -30000)
{ {
c->con.printerr("Can't get the cursor coords...\n"); out.printerr("Can't get the cursor coords...\n");
return CR_FAILURE; return CR_FAILURE;
} }
int r = diameter / 2; int r = diameter / 2;
@ -773,7 +773,7 @@ bool stamp_pattern (uint32_t bx, uint32_t by, int z_level,
return true; return true;
}; };
command_result expdig (Core * c, vector <string> & parameters) command_result expdig (color_ostream &out, vector <string> & parameters)
{ {
bool force_help = false; bool force_help = false;
static explo_how how = EXPLO_NOTHING; static explo_how how = EXPLO_NOTHING;
@ -823,7 +823,7 @@ command_result expdig (Core * c, vector <string> & parameters)
} }
if(force_help || how == EXPLO_NOTHING) if(force_help || how == EXPLO_NOTHING)
{ {
c->con.print( out.print(
"This command can be used for exploratory mining.\n" "This command can be used for exploratory mining.\n"
"http://dwarffortresswiki.org/Exploratory_mining\n" "http://dwarffortresswiki.org/Exploratory_mining\n"
"\n" "\n"
@ -846,18 +846,18 @@ command_result expdig (Core * c, vector <string> & parameters)
); );
return CR_OK; return CR_OK;
} }
CoreSuspender suspend(c); CoreSuspender suspend;
uint32_t x_max, y_max, z_max; uint32_t x_max, y_max, z_max;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
Maps::getSize(x_max,y_max,z_max); Maps::getSize(x_max,y_max,z_max);
int32_t xzzz,yzzz,z_level; int32_t xzzz,yzzz,z_level;
if(!Gui::getViewCoords(xzzz,yzzz,z_level)) if(!Gui::getViewCoords(xzzz,yzzz,z_level))
{ {
c->con.printerr("Can't get view coords...\n"); out.printerr("Can't get view coords...\n");
return CR_FAILURE; return CR_FAILURE;
} }
if(how == EXPLO_DIAG5) if(how == EXPLO_DIAG5)
@ -949,15 +949,15 @@ command_result expdig (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
command_result vdigx (Core * c, vector <string> & parameters) command_result vdigx (color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
vector <string> lol; vector <string> lol;
lol.push_back("x"); lol.push_back("x");
return vdig(c,lol); return vdig(out,lol);
} }
command_result vdig (Core * c, vector <string> & parameters) command_result vdig (color_ostream &out, vector <string> & parameters)
{ {
// HOTKEY COMMAND: CORE ALREADY SUSPENDED // HOTKEY COMMAND: CORE ALREADY SUSPENDED
uint32_t x_max,y_max,z_max; uint32_t x_max,y_max,z_max;
@ -970,11 +970,11 @@ command_result vdig (Core * c, vector <string> & parameters)
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
Console & con = c->con; auto &con = out;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
c->con.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
@ -1114,7 +1114,7 @@ command_result vdig (Core * c, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
command_result autodig (Core * c, vector <string> & parameters) command_result autodig (color_ostream &out, vector <string> & parameters)
{ {
return CR_NOT_IMPLEMENTED; return CR_NOT_IMPLEMENTED;
} }

@ -15,7 +15,7 @@ using namespace std;
#include "modules/Gui.h" #include "modules/Gui.h"
using namespace DFHack; using namespace DFHack;
command_result df_versionosd (Core * c, vector <string> & parameters); command_result df_versionosd (color_ostream &out, vector <string> & parameters);
static DFSDL_Surface* (*_IMG_LoadPNG_RW)(void* src) = 0; static DFSDL_Surface* (*_IMG_LoadPNG_RW)(void* src) = 0;
static vPtr (*_SDL_RWFromFile)(const char* file, const char *mode) = 0; static vPtr (*_SDL_RWFromFile)(const char* file, const char *mode) = 0;
static int (*_SDL_SetAlpha)(vPtr surface, uint32_t flag, uint8_t alpha) = 0; static int (*_SDL_SetAlpha)(vPtr surface, uint32_t flag, uint8_t alpha) = 0;
@ -45,7 +45,7 @@ DFTileSurface* createTile(int x, int y)
return tile; return tile;
} }
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("versionosd", commands.push_back(PluginCommand("versionosd",
@ -66,7 +66,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
if ( !surface ) if ( !surface )
{ {
c->con.print("Couldnt load image from file %s", file); out.print("Couldnt load image from file %s", file);
return CR_FAILURE; return CR_FAILURE;
} }
@ -99,7 +99,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
Graphic* g = c->getGraphic(); Graphic* g = c->getGraphic();
g->Unregister(gettile); g->Unregister(gettile);
@ -114,12 +114,11 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK; return CR_OK;
} }
command_result df_versionosd (Core * c, vector <string> & parameters) command_result df_versionosd (color_ostream &out, vector <string> & parameters)
{ {
On = !On; On = !On;
c->Suspend(); CoreSuspender suspend;
c->con.print("Version OSD is %s\n", On ? "On" : "Off"); out.print("Version OSD is %s\n", On ? "On" : "Off");
c->Resume();
return CR_OK; return CR_OK;
} }

@ -13,11 +13,11 @@ using namespace DFHack;
bool locked = false; bool locked = false;
unsigned char locked_data[25]; unsigned char locked_data[25];
command_result weather (Core * c, vector <string> & parameters); command_result weather (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("weather"); DFHACK_PLUGIN("weather");
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
@ -32,14 +32,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
return CR_OK; return CR_OK;
} }
command_result weather (Core * c, vector <string> & parameters) command_result weather (color_ostream &con, vector <string> & parameters)
{ {
Console & con = c->con;
int val_override = -1; int val_override = -1;
bool lock = false; bool lock = false;
bool unlock = false; bool unlock = false;
@ -81,8 +80,9 @@ command_result weather (Core * c, vector <string> & parameters)
} }
bool something = lock || unlock || rain || snow || clear || val_override != -1; bool something = lock || unlock || rain || snow || clear || val_override != -1;
CoreSuspender suspend(c); CoreSuspender suspend;
DFHack::World * w = c->getWorld();
DFHack::World * w = Core::getInstance().getWorld();
if(!w->wmap) if(!w->wmap)
{ {
con << "Weather support seems broken :(" << std::endl; con << "Weather support seems broken :(" << std::endl;

@ -50,14 +50,14 @@ using df::global::job_next_id;
/* Plugin registration */ /* Plugin registration */
static command_result workflow_cmd(Core *c, vector <string> & parameters); static command_result workflow_cmd(color_ostream &out, vector <string> & parameters);
static void init_state(Core *c); static void init_state(color_ostream &out);
static void cleanup_state(Core *c); static void cleanup_state(color_ostream &out);
DFHACK_PLUGIN("workflow"); DFHACK_PLUGIN("workflow");
DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
if (!world || !ui) if (!world || !ui)
@ -118,27 +118,27 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
); );
} }
init_state(c); init_state(out);
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown (color_ostream &out)
{ {
cleanup_state(c); cleanup_state(out);
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_LOADED: case SC_GAME_LOADED:
cleanup_state(c); cleanup_state(out);
init_state(c); init_state(out);
break; break;
case SC_GAME_UNLOADED: case SC_GAME_UNLOADED:
cleanup_state(c); cleanup_state(out);
break; break;
default: default:
break; break;
@ -392,12 +392,12 @@ static void setOptionEnabled(ConfigFlags flag, bool on)
* STATE INITIALIZATION * * STATE INITIALIZATION *
******************************/ ******************************/
static void stop_protect(Core *c) static void stop_protect(color_ostream &out)
{ {
pending_recover.clear(); pending_recover.clear();
if (!known_jobs.empty()) if (!known_jobs.empty())
c->con.print("Unprotecting %d jobs.\n", known_jobs.size()); out.print("Unprotecting %d jobs.\n", known_jobs.size());
for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it)
delete it->second; delete it->second;
@ -405,31 +405,33 @@ static void stop_protect(Core *c)
known_jobs.clear(); known_jobs.clear();
} }
static void cleanup_state(Core *c) static void cleanup_state(color_ostream &out)
{ {
config = PersistentDataItem(); config = PersistentDataItem();
stop_protect(c); stop_protect(out);
for (size_t i = 0; i < constraints.size(); i++) for (size_t i = 0; i < constraints.size(); i++)
delete constraints[i]; delete constraints[i];
constraints.clear(); constraints.clear();
} }
static void check_lost_jobs(Core *c, int ticks); static void check_lost_jobs(color_ostream &out, int ticks);
static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg = NULL); static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg = NULL);
static void start_protect(Core *c) static void start_protect(color_ostream &out)
{ {
check_lost_jobs(c, 0); check_lost_jobs(out, 0);
if (!known_jobs.empty()) if (!known_jobs.empty())
c->con.print("Protecting %d jobs.\n", known_jobs.size()); out.print("Protecting %d jobs.\n", known_jobs.size());
} }
static void init_state(Core *c) static void init_state(color_ostream &out)
{ {
config = c->getWorld()->GetPersistentData("workflow/config"); auto pworld = Core::getInstance().getWorld();
config = pworld->GetPersistentData("workflow/config");
if (config.isValid() && config.ival(0) == -1) if (config.isValid() && config.ival(0) == -1)
config.ival(0) = 0; config.ival(0) = 0;
@ -437,14 +439,14 @@ static void init_state(Core *c)
// Parse constraints // Parse constraints
std::vector<PersistentDataItem> items; std::vector<PersistentDataItem> items;
c->getWorld()->GetPersistentData(&items, "workflow/constraints"); pworld->GetPersistentData(&items, "workflow/constraints");
for (int i = items.size()-1; i >= 0; i--) { for (int i = items.size()-1; i >= 0; i--) {
if (get_constraint(c, items[i].val(), &items[i])) if (get_constraint(out, items[i].val(), &items[i]))
continue; continue;
c->con.printerr("Lost constraint %s\n", items[i].val().c_str()); out.printerr("Lost constraint %s\n", items[i].val().c_str());
c->getWorld()->DeletePersistentData(items[i]); pworld->DeletePersistentData(items[i]);
} }
last_tick_frame_count = world->frame_counter; last_tick_frame_count = world->frame_counter;
@ -453,35 +455,37 @@ static void init_state(Core *c)
if (!enabled) if (!enabled)
return; return;
start_protect(c); start_protect(out);
} }
static void enable_plugin(Core *c) static void enable_plugin(color_ostream &out)
{ {
auto pworld = Core::getInstance().getWorld();
if (!config.isValid()) if (!config.isValid())
{ {
config = c->getWorld()->AddPersistentData("workflow/config"); config = pworld->AddPersistentData("workflow/config");
config.ival(0) = 0; config.ival(0) = 0;
} }
setOptionEnabled(CF_ENABLED, true); setOptionEnabled(CF_ENABLED, true);
enabled = true; enabled = true;
c->con << "Enabling the plugin." << endl; out << "Enabling the plugin." << endl;
start_protect(c); start_protect(out);
} }
/****************************** /******************************
* JOB AUTO-RECOVERY * * JOB AUTO-RECOVERY *
******************************/ ******************************/
static void forget_job(Core *c, ProtectedJob *pj) static void forget_job(color_ostream &out, ProtectedJob *pj)
{ {
known_jobs.erase(pj->id); known_jobs.erase(pj->id);
delete pj; delete pj;
} }
static bool recover_job(Core *c, ProtectedJob *pj) static bool recover_job(color_ostream &out, ProtectedJob *pj)
{ {
if (pj->isLive()) if (pj->isLive())
return true; return true;
@ -490,18 +494,18 @@ static bool recover_job(Core *c, ProtectedJob *pj)
pj->holder = df::building::find(pj->building_id); pj->holder = df::building::find(pj->building_id);
if (!pj->holder) if (!pj->holder)
{ {
c->con.printerr("Forgetting job %d (%s): holder building lost.", out.printerr("Forgetting job %d (%s): holder building lost.",
pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type));
forget_job(c, pj); forget_job(out, pj);
return true; return true;
} }
// Check its state and postpone or cancel if invalid // Check its state and postpone or cancel if invalid
if (pj->holder->jobs.size() >= 10) if (pj->holder->jobs.size() >= 10)
{ {
c->con.printerr("Forgetting job %d (%s): holder building has too many jobs.", out.printerr("Forgetting job %d (%s): holder building has too many jobs.",
pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type));
forget_job(c, pj); forget_job(out, pj);
return true; return true;
} }
@ -522,7 +526,7 @@ static bool recover_job(Core *c, ProtectedJob *pj)
{ {
deleteJobStruct(recovered); deleteJobStruct(recovered);
c->con.printerr("Inconsistency: job %d (%s) already in list.", out.printerr("Inconsistency: job %d (%s) already in list.",
pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type));
return true; return true;
} }
@ -534,7 +538,7 @@ static bool recover_job(Core *c, ProtectedJob *pj)
return true; return true;
} }
static void check_lost_jobs(Core *c, int ticks) static void check_lost_jobs(color_ostream &out, int ticks)
{ {
ProtectedJob::cur_tick_idx++; ProtectedJob::cur_tick_idx++;
if (ticks < 0) ticks = 0; if (ticks < 0) ticks = 0;
@ -548,7 +552,7 @@ static void check_lost_jobs(Core *c, int ticks)
if (pj) if (pj)
{ {
if (!job->flags.bits.repeat) if (!job->flags.bits.repeat)
forget_job(c, pj); forget_job(out, pj);
else else
pj->tick_job(job, ticks); pj->tick_job(job, ticks);
} }
@ -571,7 +575,7 @@ static void check_lost_jobs(Core *c, int ticks)
} }
} }
static void update_job_data(Core *c) static void update_job_data(color_ostream &out)
{ {
df::job_list_link *p = world->job_list.next; df::job_list_link *p = world->job_list.next;
for (; p; p = p->next) for (; p; p = p->next)
@ -583,16 +587,16 @@ static void update_job_data(Core *c)
} }
} }
static void recover_jobs(Core *c) static void recover_jobs(color_ostream &out)
{ {
for (int i = pending_recover.size()-1; i >= 0; i--) for (int i = pending_recover.size()-1; i >= 0; i--)
if (recover_job(c, pending_recover[i])) if (recover_job(out, pending_recover[i]))
vector_erase_at(pending_recover, i); vector_erase_at(pending_recover, i);
} }
static void process_constraints(Core *c); static void process_constraints(color_ostream &out);
DFhackCExport command_result plugin_onupdate(Core* c) DFhackCExport command_result plugin_onupdate(color_ostream &out)
{ {
if (!enabled) if (!enabled)
return CR_OK; return CR_OK;
@ -602,7 +606,7 @@ DFhackCExport command_result plugin_onupdate(Core* c)
if ((++cnt % 5) != 0) if ((++cnt % 5) != 0)
return CR_OK; return CR_OK;
check_lost_jobs(c, world->frame_counter - last_tick_frame_count); check_lost_jobs(out, world->frame_counter - last_tick_frame_count);
last_tick_frame_count = world->frame_counter; last_tick_frame_count = world->frame_counter;
// Proceed every in-game half-day, or when jobs to recover changed // Proceed every in-game half-day, or when jobs to recover changed
@ -611,7 +615,7 @@ DFhackCExport command_result plugin_onupdate(Core* c)
if (pending_recover.size() != last_rlen || check_time) if (pending_recover.size() != last_rlen || check_time)
{ {
recover_jobs(c); recover_jobs(out);
last_rlen = pending_recover.size(); last_rlen = pending_recover.size();
// If the half-day passed, proceed to update // If the half-day passed, proceed to update
@ -619,8 +623,8 @@ DFhackCExport command_result plugin_onupdate(Core* c)
{ {
last_frame_count = world->frame_counter; last_frame_count = world->frame_counter;
update_job_data(c); update_job_data(out);
process_constraints(c); process_constraints(out);
} }
} }
@ -631,7 +635,7 @@ DFhackCExport command_result plugin_onupdate(Core* c)
* ITEM COUNT CONSTRAINT * * ITEM COUNT CONSTRAINT *
******************************/ ******************************/
static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg) static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg)
{ {
std::vector<std::string> tokens; std::vector<std::string> tokens;
split_string(&tokens, str, "/"); split_string(&tokens, str, "/");
@ -643,7 +647,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
ItemTypeInfo item; ItemTypeInfo item;
if (!item.find(tokens[0]) || !item.isValid()) { if (!item.find(tokens[0]) || !item.isValid()) {
c->con.printerr("Cannot find item type: %s\n", tokens[0].c_str()); out.printerr("Cannot find item type: %s\n", tokens[0].c_str());
return NULL; return NULL;
} }
@ -653,7 +657,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
df::dfhack_material_category mat_mask; df::dfhack_material_category mat_mask;
std::string maskstr = vector_get(tokens,1); std::string maskstr = vector_get(tokens,1);
if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) { if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) {
c->con.printerr("Cannot decode material mask: %s\n", maskstr.c_str()); out.printerr("Cannot decode material mask: %s\n", maskstr.c_str());
return NULL; return NULL;
} }
@ -663,7 +667,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
MaterialInfo material; MaterialInfo material;
std::string matstr = vector_get(tokens,2); std::string matstr = vector_get(tokens,2);
if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) { if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) {
c->con.printerr("Cannot find material: %s\n", matstr.c_str()); out.printerr("Cannot find material: %s\n", matstr.c_str());
return NULL; return NULL;
} }
@ -671,7 +675,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
weight += (material.index >= 0 ? 5000 : 1000); weight += (material.index >= 0 ? 5000 : 1000);
if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) { if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) {
c->con.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str()); out.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str());
return NULL; return NULL;
} }
@ -693,7 +697,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
nct->config = *cfg; nct->config = *cfg;
else else
{ {
nct->config = c->getWorld()->AddPersistentData("workflow/constraints"); nct->config = Core::getInstance().getWorld()->AddPersistentData("workflow/constraints");
nct->init(str); nct->init(str);
} }
@ -701,13 +705,13 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten
return nct; return nct;
} }
static void delete_constraint(Core *c, ItemConstraint *cv) static void delete_constraint(color_ostream &out, ItemConstraint *cv)
{ {
int idx = linear_index(constraints, cv); int idx = linear_index(constraints, cv);
if (idx >= 0) if (idx >= 0)
vector_erase_at(constraints, idx); vector_erase_at(constraints, idx);
c->getWorld()->DeletePersistentData(cv->config); Core::getInstance().getWorld()->DeletePersistentData(cv->config);
delete cv; delete cv;
} }
@ -858,7 +862,7 @@ static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_mater
} }
} }
static void compute_job_outputs(Core *c, ProtectedJob *pj) static void compute_job_outputs(color_ostream &out, ProtectedJob *pj)
{ {
using namespace df::enums::job_type; using namespace df::enums::job_type;
@ -946,7 +950,7 @@ static void compute_job_outputs(Core *c, ProtectedJob *pj)
link_job_constraint(pj, itype, isubtype, mat_mask, mat.type, mat.index); link_job_constraint(pj, itype, isubtype, mat_mask, mat.type, mat.index);
} }
static void map_job_constraints(Core *c) static void map_job_constraints(color_ostream &out)
{ {
melt_active = false; melt_active = false;
@ -968,7 +972,7 @@ static void map_job_constraints(Core *c)
if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject) if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject)
melt_active = pj->isResumed(); melt_active = pj->isResumed();
compute_job_outputs(c, pj); compute_job_outputs(out, pj);
} }
} }
@ -1046,7 +1050,7 @@ static bool itemInRealJob(df::item *item)
!= job_type_class::Hauling; != job_type_class::Hauling;
} }
static void map_job_items(Core *c) static void map_job_items(color_ostream &out)
{ {
for (size_t i = 0; i < constraints.size(); i++) for (size_t i = 0; i < constraints.size(); i++)
{ {
@ -1159,7 +1163,7 @@ static void map_job_items(Core *c)
static std::string shortJobDescription(df::job *job); static std::string shortJobDescription(df::job *job);
static void setJobResumed(Core *c, ProtectedJob *pj, bool goal) static void setJobResumed(color_ostream &out, ProtectedJob *pj, bool goal)
{ {
bool current = pj->isResumed(); bool current = pj->isResumed();
@ -1167,14 +1171,14 @@ static void setJobResumed(Core *c, ProtectedJob *pj, bool goal)
if (goal != current) if (goal != current)
{ {
c->con.print("%s %s%s\n", out.print("%s %s%s\n",
(goal ? "Resuming" : "Suspending"), (goal ? "Resuming" : "Suspending"),
shortJobDescription(pj->actual_job).c_str(), shortJobDescription(pj->actual_job).c_str(),
(!goal || pj->isActuallyResumed() ? "" : " (delayed)")); (!goal || pj->isActuallyResumed() ? "" : " (delayed)"));
} }
} }
static void update_jobs_by_constraints(Core *c) static void update_jobs_by_constraints(color_ostream &out)
{ {
for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it)
{ {
@ -1185,7 +1189,7 @@ static void update_jobs_by_constraints(Core *c)
if (pj->actual_job->job_type == job_type::MeltMetalObject && if (pj->actual_job->job_type == job_type::MeltMetalObject &&
isOptionEnabled(CF_AUTOMELT)) isOptionEnabled(CF_AUTOMELT))
{ {
setJobResumed(c, pj, meltable_count > 0); setJobResumed(out, pj, meltable_count > 0);
continue; continue;
} }
@ -1210,7 +1214,7 @@ static void update_jobs_by_constraints(Core *c)
else if (suspend_weight >= 0 && suspend_weight >= resume_weight) else if (suspend_weight >= 0 && suspend_weight >= resume_weight)
goal = false; goal = false;
setJobResumed(c, pj, goal); setJobResumed(out, pj, goal);
} }
for (size_t i = 0; i < constraints.size(); i++) for (size_t i = 0; i < constraints.size(); i++)
@ -1250,15 +1254,15 @@ static void update_jobs_by_constraints(Core *c)
} }
} }
static void process_constraints(Core *c) static void process_constraints(color_ostream &out)
{ {
if (constraints.empty() && if (constraints.empty() &&
!isOptionEnabled(CF_DRYBUCKETS | CF_AUTOMELT)) !isOptionEnabled(CF_DRYBUCKETS | CF_AUTOMELT))
return; return;
map_job_constraints(c); map_job_constraints(out);
map_job_items(c); map_job_items(out);
update_jobs_by_constraints(c); update_jobs_by_constraints(out);
} }
/****************************** /******************************
@ -1286,7 +1290,7 @@ static std::string shortJobDescription(df::job *job)
return rv; return rv;
} }
static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") static void print_constraint(color_ostream &out, ItemConstraint *cv, bool no_job = false, std::string prefix = "")
{ {
Console::color_value color; Console::color_value color;
if (cv->request_resume) if (cv->request_resume)
@ -1296,24 +1300,24 @@ static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, s
else else
color = Console::COLOR_DARKGREY; color = Console::COLOR_DARKGREY;
c->con.color(color); out.color(color);
c->con << prefix << "Constraint " << flush; out << prefix << "Constraint " << flush;
c->con.color(Console::COLOR_GREY); out.color(Console::COLOR_GREY);
c->con << cv->config.val() << " " << flush; out << cv->config.val() << " " << flush;
c->con.color(color); out.color(color);
c->con << (cv->goalByCount() ? "count " : "amount ") out << (cv->goalByCount() ? "count " : "amount ")
<< cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl;
c->con.reset_color(); out.reset_color();
if (cv->item_count || cv->item_inuse) if (cv->item_count || cv->item_inuse)
c->con << prefix << " items: amount " << cv->item_amount << "; " out << prefix << " items: amount " << cv->item_amount << "; "
<< cv->item_count << " stacks available, " << cv->item_count << " stacks available, "
<< cv->item_inuse << " in use." << endl; << cv->item_inuse << " in use." << endl;
if (no_job) return; if (no_job) return;
if (cv->jobs.empty()) if (cv->jobs.empty())
c->con.printerr(" (no jobs)\n"); out.printerr(" (no jobs)\n");
std::vector<ProtectedJob*> unique_jobs; std::vector<ProtectedJob*> unique_jobs;
std::vector<int> unique_counts; std::vector<int> unique_counts;
@ -1347,79 +1351,79 @@ static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, s
{ {
if (pj->want_resumed) if (pj->want_resumed)
{ {
c->con.color(Console::COLOR_YELLOW); out.color(Console::COLOR_YELLOW);
c->con << start << " (delayed)" << endl; out << start << " (delayed)" << endl;
} }
else else
{ {
c->con.color(Console::COLOR_BLUE); out.color(Console::COLOR_BLUE);
c->con << start << " (suspended)" << endl; out << start << " (suspended)" << endl;
} }
} }
else else
{ {
c->con.color(Console::COLOR_GREEN); out.color(Console::COLOR_GREEN);
c->con << start << endl; out << start << endl;
} }
c->con.reset_color(); out.reset_color();
if (unique_counts[i] > 1) if (unique_counts[i] > 1)
c->con << prefix << " (" << unique_counts[i] << " copies)" << endl; out << prefix << " (" << unique_counts[i] << " copies)" << endl;
} }
} }
static void print_job(Core *c, ProtectedJob *pj) static void print_job(color_ostream &out, ProtectedJob *pj)
{ {
if (!pj) if (!pj)
return; return;
df::job *job = pj->isLive() ? pj->actual_job : pj->job_copy; df::job *job = pj->isLive() ? pj->actual_job : pj->job_copy;
printJobDetails(c, job); printJobDetails(out, job);
if (job->job_type == job_type::MeltMetalObject && if (job->job_type == job_type::MeltMetalObject &&
isOptionEnabled(CF_AUTOMELT)) isOptionEnabled(CF_AUTOMELT))
{ {
if (meltable_count <= 0) if (meltable_count <= 0)
c->con.color(Console::COLOR_CYAN); out.color(Console::COLOR_CYAN);
else if (pj->want_resumed && !pj->isActuallyResumed()) else if (pj->want_resumed && !pj->isActuallyResumed())
c->con.color(Console::COLOR_YELLOW); out.color(Console::COLOR_YELLOW);
else else
c->con.color(Console::COLOR_GREEN); out.color(Console::COLOR_GREEN);
c->con << " Meltable: " << meltable_count << " objects." << endl; out << " Meltable: " << meltable_count << " objects." << endl;
c->con.reset_color(); out.reset_color();
} }
for (size_t i = 0; i < pj->constraints.size(); i++) for (size_t i = 0; i < pj->constraints.size(); i++)
print_constraint(c, pj->constraints[i], true, " "); print_constraint(out, pj->constraints[i], true, " ");
} }
static command_result workflow_cmd(Core *c, vector <string> & parameters) static command_result workflow_cmd(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend(c); CoreSuspender suspend;
if (!c->isWorldLoaded()) { if (!Core::getInstance().isWorldLoaded()) {
c->con.printerr("World is not loaded: please load a game first.\n"); out.printerr("World is not loaded: please load a game first.\n");
return CR_FAILURE; return CR_FAILURE;
} }
if (enabled) { if (enabled) {
check_lost_jobs(c, 0); check_lost_jobs(out, 0);
recover_jobs(c); recover_jobs(out);
update_job_data(c); update_job_data(out);
map_job_constraints(c); map_job_constraints(out);
map_job_items(c); map_job_items(out);
} }
df::building *workshop = NULL; df::building *workshop = NULL;
df::job *job = NULL; df::job *job = NULL;
if (Gui::dwarfmode_hotkey(c, c->getTopViewscreen()) && if (Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::QueryBuilding) ui->main.mode == ui_sidebar_mode::QueryBuilding)
{ {
workshop = world->selected_building; workshop = world->selected_building;
job = Gui::getSelectedWorkshopJob(c, true); job = Gui::getSelectedWorkshopJob(out, true);
} }
std::string cmd = parameters.empty() ? "list" : parameters[0]; std::string cmd = parameters.empty() ? "list" : parameters[0];
@ -1429,7 +1433,7 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
bool enable = (cmd == "enable"); bool enable = (cmd == "enable");
if (enable && !enabled) if (enable && !enabled)
{ {
enable_plugin(c); enable_plugin(out);
} }
else if (!enable && parameters.size() == 1) else if (!enable && parameters.size() == 1)
{ {
@ -1437,10 +1441,10 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
{ {
enabled = false; enabled = false;
setOptionEnabled(CF_ENABLED, false); setOptionEnabled(CF_ENABLED, false);
stop_protect(c); stop_protect(out);
} }
c->con << "The plugin is disabled." << endl; out << "The plugin is disabled." << endl;
return CR_OK; return CR_OK;
} }
@ -1455,38 +1459,38 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
} }
if (enabled) if (enabled)
c->con << "The plugin is enabled." << endl; out << "The plugin is enabled." << endl;
else else
c->con << "The plugin is disabled." << endl; out << "The plugin is disabled." << endl;
if (isOptionEnabled(CF_DRYBUCKETS)) if (isOptionEnabled(CF_DRYBUCKETS))
c->con << "Option drybuckets is enabled." << endl; out << "Option drybuckets is enabled." << endl;
if (isOptionEnabled(CF_AUTOMELT)) if (isOptionEnabled(CF_AUTOMELT))
c->con << "Option auto-melt is enabled." << endl; out << "Option auto-melt is enabled." << endl;
return CR_OK; return CR_OK;
} }
else if (cmd == "count" || cmd == "amount") else if (cmd == "count" || cmd == "amount")
{ {
if (!enabled) if (!enabled)
enable_plugin(c); enable_plugin(out);
} }
if (!enabled) if (!enabled)
c->con << "Note: the plugin is not enabled." << endl; out << "Note: the plugin is not enabled." << endl;
if (cmd == "jobs") if (cmd == "jobs")
{ {
if (workshop) if (workshop)
{ {
for (size_t i = 0; i < workshop->jobs.size(); i++) for (size_t i = 0; i < workshop->jobs.size(); i++)
print_job(c, get_known(workshop->jobs[i]->id)); print_job(out, get_known(workshop->jobs[i]->id));
} }
else else
{ {
for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it)
if (it->second->isLive()) if (it->second->isLive())
print_job(c, it->second); print_job(out, it->second);
} }
bool pending = false; bool pending = false;
@ -1497,11 +1501,11 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
{ {
if (!pending) if (!pending)
{ {
c->con.print("\nPending recovery:\n"); out.print("\nPending recovery:\n");
pending = true; pending = true;
} }
printJobDetails(c, pending_recover[i]->job_copy); printJobDetails(out, pending_recover[i]->job_copy);
} }
} }
@ -1510,7 +1514,7 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
else if (cmd == "list") else if (cmd == "list")
{ {
for (size_t i = 0; i < constraints.size(); i++) for (size_t i = 0; i < constraints.size(); i++)
print_constraint(c, constraints[i]); print_constraint(out, constraints[i]);
return CR_OK; return CR_OK;
} }
@ -1521,11 +1525,11 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
int limit = atoi(parameters[2].c_str()); int limit = atoi(parameters[2].c_str());
if (limit <= 0) { if (limit <= 0) {
c->con.printerr("Invalid limit value.\n"); out.printerr("Invalid limit value.\n");
return CR_FAILURE; return CR_FAILURE;
} }
ItemConstraint *icv = get_constraint(c, parameters[1]); ItemConstraint *icv = get_constraint(out, parameters[1]);
if (!icv) if (!icv)
return CR_FAILURE; return CR_FAILURE;
@ -1536,8 +1540,8 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
else else
icv->setGoalGap(-1); icv->setGoalGap(-1);
process_constraints(c); process_constraints(out);
print_constraint(c, icv); print_constraint(out, icv);
return CR_OK; return CR_OK;
} }
else if (cmd == "unlimit") else if (cmd == "unlimit")
@ -1550,11 +1554,11 @@ static command_result workflow_cmd(Core *c, vector <string> & parameters)
if (constraints[i]->config.val() != parameters[1]) if (constraints[i]->config.val() != parameters[1])
continue; continue;
delete_constraint(c, constraints[i]); delete_constraint(out, constraints[i]);
return CR_OK; return CR_OK;
} }
c->con.printerr("Constraint not found: %s\n", parameters[1].c_str()); out.printerr("Constraint not found: %s\n", parameters[1].c_str());
return CR_FAILURE; return CR_FAILURE;
} }
else else