2012-04-24 17:20:35 -06:00
|
|
|
This plugins embeds a ruby interpreter inside DFHack (ie inside Dwarf Fortress).
|
|
|
|
|
|
|
|
The plugin maps all the structures available in library/xml/ to ruby objects.
|
|
|
|
|
|
|
|
These objects are described in ruby-autogen.rb, they are all in the DFHack::
|
2012-05-29 09:28:51 -06:00
|
|
|
module. The toplevel 'df' method is a shortcut to the DFHack module.
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
The plugin does *not* map most of dfhack methods (MapCache, ...) ; only direct
|
|
|
|
access to the raw DF data structures in memory is provided.
|
|
|
|
|
|
|
|
Some library methods are stored in the ruby.rb file, with shortcuts to read a
|
|
|
|
map block, find an unit or an item, etc.
|
|
|
|
|
2012-06-12 10:51:33 -06:00
|
|
|
Global objects are accessible through the 'df' accessor (eg df.world).
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
The ruby plugin defines 2 dfhack console commands:
|
|
|
|
rb_load <filename> ; load a ruby script. Ex: rb_load hack/plants.rb (no quotes)
|
|
|
|
rb_eval <ruby expression> ; evaluate a ruby expression, show the result in the
|
|
|
|
console. Ex: rb_eval df.find_unit.name.first_name
|
|
|
|
You can use single-quotes for strings ; avoid double-quotes that are parsed
|
|
|
|
and removed by the dfhack console.
|
|
|
|
|
2012-06-12 10:51:33 -06:00
|
|
|
If dfhack reports 'rb_eval is not a recognized command', check stderr.log. You
|
|
|
|
need a valid 32-bit ruby library to work, and ruby1.8 is prefered (ruby1.9 may
|
|
|
|
crash DF on startup for now). Install the library in the df root folder (or
|
|
|
|
hack/ on linux), the library should be named 'libruby.dll' (.so on linux).
|
|
|
|
You can download a tested version at http://github.com/jjyg/dfhack/downloads/
|
|
|
|
|
2012-04-24 17:20:35 -06:00
|
|
|
The plugin also interfaces with dfhack 'onupdate' hook.
|
|
|
|
To register ruby code to be run every graphic frame, use:
|
2012-05-29 09:28:51 -06:00
|
|
|
handle = df.onupdate_register { puts 'i love flooding the console' }
|
2012-04-24 17:20:35 -06:00
|
|
|
To stop being called, use:
|
|
|
|
df.onupdate_unregister handle
|
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
The same mechanism is available for onstatechange.
|
|
|
|
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
Exemples
|
|
|
|
--------
|
|
|
|
|
2012-06-12 10:51:33 -06:00
|
|
|
For more complex exemples, check the ruby/plugins/ source folder.
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
Show info on the currently selected unit ('v' or 'k' DF menu)
|
|
|
|
p df.find_unit.flags1
|
|
|
|
|
|
|
|
Set a custom nickname to unit with id '123'
|
|
|
|
df.find_unit(123).name.nickname = 'moo'
|
|
|
|
|
|
|
|
Show current unit profession
|
2012-05-10 17:34:03 -06:00
|
|
|
p df.find_unit.profession
|
2012-04-24 17:20:35 -06:00
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
Change current unit profession
|
|
|
|
df.find_unit.profession = :MASON
|
|
|
|
|
2012-04-24 17:20:35 -06:00
|
|
|
Center the screen on unit '123'
|
|
|
|
df.center_viewscreen(df.find_unit(123))
|
|
|
|
|
|
|
|
Find an item at a given position, show its C++ classname
|
|
|
|
df.find_item(df.cursor)._rtti_classname
|
|
|
|
|
|
|
|
Find the raws name of the plant under cursor
|
2012-05-29 09:28:51 -06:00
|
|
|
plant = df.world.plants.all.find { |plt| df.at_cursor?(plt) }
|
|
|
|
p df.world.raws.plants.all[plant.mat_index].id
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
Dig a channel under the cursor
|
2012-05-29 09:28:51 -06:00
|
|
|
df.map_designation_at(df.cursor).dig = :Channel
|
2012-04-24 17:20:35 -06:00
|
|
|
df.map_block_at(df.cursor).flags.designated = true
|
|
|
|
|
|
|
|
|
|
|
|
Compilation
|
|
|
|
-----------
|
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
The plugin consists of the ruby.rb file including user comfort functions and
|
|
|
|
describing basic classes used by the autogenerated code, and ruby-autogen.rb,
|
|
|
|
the auto-generated code.
|
2012-04-24 17:20:35 -06:00
|
|
|
|
|
|
|
The generated code is generated by codegen.pl, which takes the codegen.out.xml
|
|
|
|
file as input.
|
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
For exemple,
|
2012-04-24 17:20:35 -06:00
|
|
|
<ld:global-type ld:meta="struct-type" type-name="unit">
|
|
|
|
<ld:field type-name="language_name" name="name" ld:meta="global"/>
|
|
|
|
<ld:field name="custom_profession" ld:meta="primitive" ld:subtype="stl-string"/>
|
|
|
|
<ld:field ld:subtype="enum" base-type="int16_t" name="profession" type-name="profession" ld:meta="global"/>
|
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
Will generate
|
2012-04-24 17:20:35 -06:00
|
|
|
class Unit < MemHack::Compound
|
|
|
|
field(:name, 0) { global :LanguageName }
|
|
|
|
field(:custom_profession, 60) { stl_string }
|
|
|
|
field(:profession, 64) { number 16, true }
|
|
|
|
|
2012-05-29 09:28:51 -06:00
|
|
|
The syntax for the 'field' method is:
|
|
|
|
1st argument = name of the method
|
|
|
|
2nd argument = offset of this field from the beginning of the struct.
|
|
|
|
|
|
|
|
The block argument describes the type of the field: uint32, ptr to global...
|
|
|
|
|
2012-04-24 17:20:35 -06:00
|
|
|
Primitive type access is done through native methods in ruby.cpp (vector length,
|
|
|
|
raw memory access, etc)
|
|
|
|
|
2012-04-27 09:11:01 -06:00
|
|
|
MemHack::Pointers are automatically dereferenced ; so a vector of pointer to
|
|
|
|
Units will yield Units directly. Null pointers yield the 'nil' value.
|
2012-04-24 17:20:35 -06:00
|
|
|
|
2012-04-27 09:11:01 -06:00
|
|
|
This allows to use code such as 'df.world.units.all[0].pos', with 'all' being
|
2012-05-29 09:28:51 -06:00
|
|
|
in fact a vector of *pointers* to DFHack::Unit objects.
|