v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Editing Utility:DFHack/Programming

Jump to navigation Jump to search

Warning: You are not logged in.
Your IP address will be recorded in this page's edit history.


The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 3: Line 3:
 
== INTRODUCTION ==
 
== INTRODUCTION ==
  
DFHack is a Dwarf Fortress (DF) memory access library and a set of basic tools that use it (see the documentation at https://docs.dfhack.org/en/stable/ ).
+
DFHack is a Dwarf Fortress (DF) memory access library and a set of basic tools that use it (see the readme at https://github.com/DFHack/dfhack/blob/master/Readme.rst ).
  
 
It is possible for developers to write plugins for DFHack, in order to extend the capabilities of DFHack (and therefore DF's gameplay). The plugins come mainly in two flavours:
 
It is possible for developers to write plugins for DFHack, in order to extend the capabilities of DFHack (and therefore DF's gameplay). The plugins come mainly in two flavours:
 
* C++ plugins: libraries written in C++ that need to be compiled. They can use DFHack's low level functions very closely, and they will be able to perform complex functions ''very'' quickly.
 
* C++ plugins: libraries written in C++ that need to be compiled. They can use DFHack's low level functions very closely, and they will be able to perform complex functions ''very'' quickly.
* Lua and Ruby scripts: text-based scripts which can be dropped into place and modified on the fly. Certain things can be easier to do, and error handling is better in general, but the downside is that they can be quite ''slow'' - for example, trying to reveal the entire map from Lua may take an entire minute, while the C++ plugin can do it in a tiny fraction of a second. This document is focused entirely on plugins - if you would like to learn more about writing scripts, see https://docs.dfhack.org/en/stable/docs/Lua%20API.html
+
* Lua and Ruby scripts: text-based scripts which can be dropped into place and modified on the fly. Certain things can be easier to do, and error handling is better in general, but the downside is that they can be quite ''slow'' - for example, trying to reveal the entire map from Lua may take an entire minute, while the C++ plugin can do it in a tiny fraction of a second. This document is focused entirely on plugins - if you would like to learn more about writing scripts, see https://github.com/DFHack/dfhack/blob/master/Lua%20API.rst
  
 
This document explains how to get started at writing C++ plugins with Microsoft Visual C++ 2010, step by step. It is intended for people who are totally new to DFHack.
 
This document explains how to get started at writing C++ plugins with Microsoft Visual C++ 2010, step by step. It is intended for people who are totally new to DFHack.
Line 20: Line 20:
  
 
You must download the sources, and build them.
 
You must download the sources, and build them.
* Follow exactly the steps described in DFHack's documentation: https://docs.dfhack.org/en/stable/docs/Compile.html
+
* Follow exactly the steps described in DFHack's readme: https://github.com/DFHack/dfhack/blob/master/Compile.rst
  
 
== Make yourself comfy ==
 
== Make yourself comfy ==
=== Windows ===
+
 
As explained in the compiling guidelines (above), there are several scripts available, that will do different things : some will just build, some will also install the results to your DF's "hack" folder. To save some time, here is how you can set up Visual C++ to do a build+install every time you press <code>F7</code>:
+
As explained in the compiling guidelines (above), there are several scripts available, that will do different things : some will just build, some will also install the results to your DF's DFHack folder. To save some time, here is how you can set up Visual C++ to do a build+install every time you press <code>F7</code>:
 
* Open <code>dfhack.sln</code> in Visual C++
 
* Open <code>dfhack.sln</code> in Visual C++
 
* Right-click on the Solution, and select "Properties"
 
* Right-click on the Solution, and select "Properties"
Line 47: Line 47:
 
Now you need to run DFHack's awesome build scripts, to make them generate all the relevant project files for you:
 
Now you need to run DFHack's awesome build scripts, to make them generate all the relevant project files for you:
 
* Observe all the batch files in <code>dfhack/build</code> starting with "generate"  
 
* Observe all the batch files in <code>dfhack/build</code> starting with "generate"  
* Run your favourite one. For example, you can choose <code>generate-MSVC-minimal.bat</code>
+
* Run your favourite one. For example you can choose <code>generate-MSVC-minimal.bat</code>
 
Once this finishes, Visual C++ will prompt you to reload the project if you have it open, and once you do so you'll notice that your project "myplugin" has magically appeared. However, since the source file is still blank, it's not exactly ready to compile.
 
Once this finishes, Visual C++ will prompt you to reload the project if you have it open, and once you do so you'll notice that your project "myplugin" has magically appeared. However, since the source file is still blank, it's not exactly ready to compile.
  
Line 79: Line 79:
  
 
; Each plugin has two central functions:
 
; Each plugin has two central functions:
* <code>DFhackCExport command_result plugin_init(color_ostream&, std::vector<PluginCommand>&)</code>. This is run when the plugin gets loaded, whether or not its command gets run from the command line.
+
* <code>plugin_init</code>. This is run when the plugin gets loaded, whether or not its command gets run from the command line.
* <code>DFhackCExport command_result plugin_shutdown(color_ostream)&</code>. This is run when the plugin gets unloaded (i.e. when DFHack shuts down).
+
* <code>plugin_shutdown</code>. This is run when the plugin gets unloaded (i.e. when DFHack shuts down).
'''Note the <code>DFhackCExport</code> before the function signatures. This is required so that DFHack can load your plugin.'''
+
You'll notice that tubefill's <code>plugin_shutdown</code> is empty (it just returns the standardized "OK" return code : <code>CR_OK</code>). That's because the plugin is simple and doesn't need to delete objects, or close connections, or do any kind of post-processing.
 
 
The <code>color_ostream&</code> parameter to these functions is an output stream that prints to the DFHack console. You can use this to output debug messages when your plugin is being loaded/unloaded. (An example of using such an output stream is given in the section [http://dwarffortresswiki.org/index.php/Utility:DFHack/Programming#Simplest_possible_plugin:_Hello_world.21 Simplest possible plugin].)
 
 
 
The second parameter to the <code>plugin_init</code> function is important -- it is a reference to the list of available commands. You use this to add your own command which calls the <code>myplugin</code> function you declared earlier.
 
  
As an example, <code>tubefill</code> uses this code to add the "tubefill" command so it can be run in the console:
+
However, tubefill's <code>plugin_init</code> contains an important instruction, that will tell DFHack to be aware of a new custom command-line instruction:
  
<pre>DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
+
<pre>commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill, false,
{
+
    "Replenishes mined out adamantine but does not fill hollow adamantine tubes.\n"
    commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill, false,
+
    "Specify 'hollow' to fill hollow tubes, but beware glitchy HFS spawns.\n"));</pre>
        "Replenishes mined out adamantine but does not fill hollow adamantine tubes.\n"
 
        "Specify 'hollow' to fill hollow tubes, but beware glitchy HFS spawns.\n"));
 
    return CR_OK;
 
}</pre>
 
 
Details:
 
Details:
  
Line 101: Line 93:
 
* <code>tubefill</code> is the function that must be called when the command is typed into the command line.  
 
* <code>tubefill</code> is the function that must be called when the command is typed into the command line.  
 
* <code>"Fill in all the adamantine tubes again."</code> and <code>"Replenishes mined out adamantine..."</code> are the "manual" that will be displayed in the help or when the command is called with the wrong parameters (see below how to test that).
 
* <code>"Fill in all the adamantine tubes again."</code> and <code>"Replenishes mined out adamantine..."</code> are the "manual" that will be displayed in the help or when the command is called with the wrong parameters (see below how to test that).
 
<code>tubefill</code>'s <code>plugin_shutdown</code>, however, is empty (it just returns the standardized "OK" return code : <code>CR_OK</code>). That's because the plugin is simple and doesn't need to delete objects, or close connections, or do any kind of post-processing.
 
 
 
Finally, you'll find the actual function definition:
 
Finally, you'll find the actual function definition:
  
Line 109: Line 98:
 
{
 
{
 
     ...
 
     ...
    return CR_OK;
 
 
}
 
}
</pre>
+
return CR_OK;</pre>
 
 
  
 
== Simplest possible plugin: Hello world! ==
 
== Simplest possible plugin: Hello world! ==
Line 121: Line 108:
 
{
 
{
 
     out.print("Hello Monsieur Ouxx!\n");
 
     out.print("Hello Monsieur Ouxx!\n");
    return CR_OK;
 
 
}
 
}
</pre>
+
return CR_OK;</pre>
 
Please note that you have other outputs available:
 
Please note that you have other outputs available:
  
Line 167: Line 153:
 
}</pre>
 
}</pre>
  
== Suspend the core! ==
+
== Suspend the core!!!!!111!!11 ==
  
 
This might be the MOST IMPORTANT section in this document. Never ever forget to suspend the game's core execution before you manipulate anything in its internal data. It is done by adding the following statement:
 
This might be the MOST IMPORTANT section in this document. Never ever forget to suspend the game's core execution before you manipulate anything in its internal data. It is done by adding the following statement:
Line 181: Line 167:
 
Many plugins add menus to DF in order to extend capabilities (or, at least, sort out DF's mess). A good example of that is the plugin <code>buildingplan</code>. It displays a menu with lists of materials, and allows to filter the materials. Lists and filters. That's what DF is all about!
 
Many plugins add menus to DF in order to extend capabilities (or, at least, sort out DF's mess). A good example of that is the plugin <code>buildingplan</code>. It displays a menu with lists of materials, and allows to filter the materials. Lists and filters. That's what DF is all about!
  
[[File:DFHack_Plugin-_buildingplan_screenshot.png|300px]]
+
http://imageshack.us/a/img28/4686/materials.png
  
 
You make them fit into a "viewscreen", that is: an additional screen that will fit into DF. This section is about creating a NEW viewscreen, not replacing one already existing in DF.
 
You make them fit into a "viewscreen", that is: an additional screen that will fit into DF. This section is about creating a NEW viewscreen, not replacing one already existing in DF.
Line 214: Line 200:
  
 
<pre>Screen::clear();                                    //delete the screen
 
<pre>Screen::clear();                                    //delete the screen
Screen::drawBorder("  Building Material  ");        //create a new DF-style screen, with a title and a border
+
Screen::drawBorder("  Building Material  ");        //create a new DF-stryle screen, with a title and a border
  
 
masks_column.display(selected_column == 0);        //display our column (read this tutorial further)
 
masks_column.display(selected_column == 0);        //display our column (read this tutorial further)

Please note that all contributions to Dwarf Fortress Wiki are considered to be released under the GFDL & MIT (see Dwarf Fortress Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following CAPTCHA:

Cancel Editing help (opens in new window)