Any files with the .lua extension placed into hack/scripts/*
are automatically used by the DFHack core as commands. The
matching command name consists of the name of the file sans
diff --git a/library/lua/utils.lua b/library/lua/utils.lua
index f303091d6..38a1e6c42 100644
--- a/library/lua/utils.lua
+++ b/library/lua/utils.lua
@@ -57,10 +57,10 @@ function is_container(obj)
end
-- Make a sequence of numbers in 1..size
-function make_index_sequence(size)
+function make_index_sequence(istart,iend)
local index = {}
- for i=1,size do
- index[i] = i
+ for i=istart,iend do
+ index[i-istart+1] = i
end
return index
end
@@ -114,7 +114,7 @@ function make_sort_order(data,ordering)
end
-- Make an order table
- local index = make_index_sequence(size)
+ local index = make_index_sequence(1,size)
-- Sort the ordering table
table.sort(index, function(ia,ib)
@@ -379,7 +379,7 @@ function prompt_yes_no(msg,default)
elseif string.match(rv,'^[Nn]') then
return false
elseif rv == 'abort' then
- qerror('User abort in utils.prompt_yes_no()')
+ qerror('User abort')
elseif rv == '' and default ~= nil then
return default
end
@@ -393,7 +393,7 @@ function prompt_input(prompt,check,quit_str)
while true do
local rv = dfhack.lineedit(prompt)
if rv == quit_str then
- return nil
+ qerror('User abort')
end
local rtbl = table.pack(check(rv))
if rtbl[1] then
From 1c013486d5e39c9c946cda40e3bdd71136010a14 Mon Sep 17 00:00:00 2001
From: Warmist
Date: Mon, 25 Jun 2012 22:22:20 +0300
Subject: [PATCH 04/31] Removed non-working onfunction.
---
.../Dfusion/luafiles/onfunction/compile.bat | 1 -
.../Dfusion/luafiles/onfunction/functions.asm | 23 ------
.../Dfusion/luafiles/onfunction/functions.o | Bin 404 -> 0 bytes
plugins/Dfusion/luafiles/onfunction/init.lua | 68 ------------------
.../Dfusion/luafiles/onfunction/locations.lua | 16 -----
.../Dfusion/luafiles/onfunction/plugin.lua | 15 ----
6 files changed, 123 deletions(-)
delete mode 100644 plugins/Dfusion/luafiles/onfunction/compile.bat
delete mode 100644 plugins/Dfusion/luafiles/onfunction/functions.asm
delete mode 100644 plugins/Dfusion/luafiles/onfunction/functions.o
delete mode 100644 plugins/Dfusion/luafiles/onfunction/init.lua
delete mode 100644 plugins/Dfusion/luafiles/onfunction/locations.lua
delete mode 100644 plugins/Dfusion/luafiles/onfunction/plugin.lua
diff --git a/plugins/Dfusion/luafiles/onfunction/compile.bat b/plugins/Dfusion/luafiles/onfunction/compile.bat
deleted file mode 100644
index f06fb8c4c..000000000
--- a/plugins/Dfusion/luafiles/onfunction/compile.bat
+++ /dev/null
@@ -1 +0,0 @@
-as -anl --32 -o functions.o functions.asm
\ No newline at end of file
diff --git a/plugins/Dfusion/luafiles/onfunction/functions.asm b/plugins/Dfusion/luafiles/onfunction/functions.asm
deleted file mode 100644
index 13ef23191..000000000
--- a/plugins/Dfusion/luafiles/onfunction/functions.asm
+++ /dev/null
@@ -1,23 +0,0 @@
-.intel_syntax
-push eax
-push ebp
-push esp
-push esi
-push edi
-push edx
-push ecx
-push ebx
-push eax
-mov eax,[esp+36]
-push eax
-function:
-call 0xdeadbee0
-function2:
-mov [0xdeadbeef],eax
-pop eax
-function3:
-jmp [0xdeadbeef]
-
-
-
-
diff --git a/plugins/Dfusion/luafiles/onfunction/functions.o b/plugins/Dfusion/luafiles/onfunction/functions.o
deleted file mode 100644
index 7b7d4a33f044cd95156cb204eede5e0cb155714a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 404
zcmeZaWM%+?Z9vQoX0b5pm84dbfY}g20Z8=#@frx1fe}b6Fc>80r6iUlLd9@V4h#kd
z^pc8;ammBP8-VHpLPNsBg93vCx?NOM0$#k|xAxv*5E1cT6+}(o2P*y#1R@N2X_+~x
zP_6&|GccqxrX^;>1fb$+rFqFEnfZBqKt9ODY+!K~ASsL@0+N@6iy-?Qq>GtR9x4Z<
hpa9w5Oh7SakU}(o>}OC2V^bpm6o material esp->block type
- onfunction.AddFunction(0x3d4301+offsets.base(),"Make_Item",{item_type="esp"})
- onfunction.AddFunction(0x5af826+offsets.base(),"Hurt",{target="esi",attacker={off=0x74,rtype=DWORD,reg="esp"}})
- onfunction.AddFunction(0x3D5886+offsets.base(),"Flip",{building="esi"})
- onfunction.AddFunction(0x35E340+offsets.base(),"ItemCreate")--]=]
- --onfunction.AddFunction(0x4B34B6+offsets.base(),"ReactionFinish") --esp item. Ecx creature, edx? 0.34.07
- onfunction.AddFunction(0x72aB6+offsets.base(),"Die",{creature="edi"}) --0.34.07
-else --linux
- --[=[onfunction.AddFunction(0x899befe+offsets.base(),"Move") -- found out by attaching watch...
- onfunction.AddFunction(0x850eecd+offsets.base(),"Die",{creature="ebx"}) -- same--]=]
-end
diff --git a/plugins/Dfusion/luafiles/onfunction/plugin.lua b/plugins/Dfusion/luafiles/onfunction/plugin.lua
deleted file mode 100644
index 60360817c..000000000
--- a/plugins/Dfusion/luafiles/onfunction/plugin.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-mypos=engine.getmod("functions")
-function DeathMsg(values)
- local name
- local u=engine.cast(df.unit,values[onfunction.hints["Die"].creature])
-
- print(u.name.first_name.." died")
-end
-if mypos then
- print("Onfunction already installed")
- --onfunction.patch(0x189dd6+offsets.base())
-else
- onfunction.install()
- dofile("dfusion/onfunction/locations.lua")
- onfunction.SetCallback("Die",DeathMsg)
-end
From 85f9d35f6f4897eb44a6b893bdf4822983ec7a3d Mon Sep 17 00:00:00 2001
From: Warmist
Date: Mon, 25 Jun 2012 22:26:08 +0300
Subject: [PATCH 05/31] Temporary fix for memory accessor.
---
plugins/Dfusion/luafiles/common.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua
index bdcda5e89..752d07cf6 100644
--- a/plugins/Dfusion/luafiles/common.lua
+++ b/plugins/Dfusion/luafiles/common.lua
@@ -36,7 +36,7 @@ function GetTextRegion()
--if num>=100 then
--print(string.format("%d %x->%x %s %s",k,v["start"],v["end"],v.name or "",flgs))
--end
- local pos=string.find(v.name,".text") or string.find(v.name,"libs/Dwarf_Fortress")
+ local pos=string.find(v.name,"Dwarf Fortress.exe") or string.find(v.name,"libs/Dwarf_Fortress")
if(pos~=nil) and v["execute"] then
__TEXT=v;
return v;
From f0d4d799d838eacc1cc5d4a6eb267fcd9d62e748 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Wed, 27 Jun 2012 16:38:39 -0500
Subject: [PATCH 06/31] Don't index world_data->region_map beyond its bounds
---
plugins/probe.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/plugins/probe.cpp b/plugins/probe.cpp
index b7b7d298f..2ae6846d5 100644
--- a/plugins/probe.cpp
+++ b/plugins/probe.cpp
@@ -221,10 +221,11 @@ command_result df_probe (color_ostream &out, vector & parameters)
out.print("temperature2: %d U\n",mc.temperature2At(cursor));
int offset = block.region_offset[des.bits.biome];
- df::coord2d region_pos = block.region_pos + df::coord2d ((offset % 3) - 1, (offset / 3) -1);
+ int bx = clip_range(block.region_pos.x + (offset % 3) - 1, 0, world->world_data->world_width-1);
+ int by = clip_range(block.region_pos.y + (offset / 3) - 1, 0, world->world_data->world_height-1);
df::world_data::T_region_map* biome =
- &world->world_data->region_map[region_pos.x][region_pos.y];
+ &world->world_data->region_map[bx][by];
int sav = biome->savagery;
int evi = biome->evilness;
From 07dc20055a599811b6ae517467d6a75392e47a60 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Sat, 30 Jun 2012 16:25:41 +0400
Subject: [PATCH 07/31] Tweak documentation for utils.make_sort_order and
devel/prepare-save
---
LUA_API.rst | 16 ++++++++++++++--
Lua API.html | 19 ++++++++++++++++---
scripts/devel/prepare-save.lua | 15 +++++++++++++++
3 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/LUA_API.rst b/LUA_API.rst
index 252be3374..2bb2c949e 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -1428,7 +1428,7 @@ utils
* ``utils.make_sort_order(data, ordering)``
- Computes an ordering of objects in data, as a table of integer
+ Computes a sorted permutation of objects in data, as a table of integer
indices into the data sequence. Uses ``data.n`` as input length
if present.
@@ -1436,7 +1436,7 @@ utils
as lua tables with following possible fields:
ord.key = *function(value)*
- Computes comparison key from a data value. Not called on nil.
+ Computes comparison key from input data value. Not called on nil.
If omitted, the comparison key is the value itself.
ord.key_table = *function(data)*
Computes a key table from the data table in one go.
@@ -1448,6 +1448,18 @@ utils
ord.reverse = *true/false*
If true, sort non-nil keys in descending order.
+ For every comparison during sorting the specs are applied in
+ order until an unambiguous decision is reached. Sorting is stable.
+
+ Example of sorting a sequence by field foo::
+
+ local spec = { key = function(v) return v.foo end }
+ local order = utils.make_sort_order(data, { spec })
+ local output = {}
+ for i = 1,#order do output[i] = data[order[i]] end
+
+ Separating the actual reordering of the sequence in this
+ way enables applying the same permutation to multiple arrays.
This function is used by the sort plugin.
* ``utils.assign(tgt, src)``
diff --git a/Lua API.html b/Lua API.html
index 0496d7e50..2c9a6a8df 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -1571,14 +1571,14 @@ Returns nil if any of obj or indices is nil, or a numeric inde
Returns a lua sequence of numbers in start..end.
utils.make_sort_order(data, ordering)
-Computes an ordering of objects in data, as a table of integer
+
Computes a sorted permutation of objects in data, as a table of integer
indices into the data sequence. Uses data.n as input length
if present.
The ordering argument is a sequence of ordering specs, represented
as lua tables with following possible fields:
- ord.key = function(value)
-Computes comparison key from a data value. Not called on nil.
+
Computes comparison key from input data value. Not called on nil.
If omitted, the comparison key is the value itself.
- ord.key_table = function(data)
@@ -1595,7 +1595,18 @@ Called on non-nil keys; nil sorts last.
This function is used by the sort plugin.
For every comparison during sorting the specs are applied in
+order until an unambiguous decision is reached. Sorting is stable.
Separating the actual reordering of the sequence in this
+way enables applying the same permutation to multiple arrays.
+This function is used by the sort plugin.
utils.assign(tgt, src)
Does a recursive assignment of src into tgt.
@@ -1728,6 +1739,8 @@ calls lua code to perform the actual ordering of list items.
are automatically used by the DFHack core as commands. The
matching command name consists of the name of the file sans
the extension.
+If the first line of the script is a one-line comment, it is
+used by the built-in ls and help commands.
NOTE: Scripts placed in subdirectories still can be accessed, but
do not clutter the ls command list; thus it is preferred
for obscure developer-oriented scripts and scripts used by tools.
diff --git a/scripts/devel/prepare-save.lua b/scripts/devel/prepare-save.lua
index 781e3b892..c282c8a43 100644
--- a/scripts/devel/prepare-save.lua
+++ b/scripts/devel/prepare-save.lua
@@ -1,7 +1,22 @@
-- Prepare the current save for use with devel/find-offsets.
+local utils = require 'utils'
+
df.global.pause_state = true
+print[[
+WARNING: THIS SCRIPT IS STRICTLY FOR DFHACK DEVELOPERS.
+
+This script prepares the current savegame to be used
+with devel/find-offsets. It CHANGES THE GAME STATE
+to predefined values, and initiates an immediate
+quicksave, thus PERMANENTLY MODIFYING the save.
+]]
+
+if not utils.prompt_yes_no('Proceed?') then
+ return
+end
+
--[[print('Placing anchor...')
do
From b9425474a1006a2f713462e171894f476c58bbb7 Mon Sep 17 00:00:00 2001
From: jj
Date: Mon, 2 Jul 2012 21:57:53 +0200
Subject: [PATCH 08/31] ruby: fix codegen for darwin
---
plugins/ruby/codegen.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl
index c7fb210c9..1fcebfffe 100755
--- a/plugins/ruby/codegen.pl
+++ b/plugins/ruby/codegen.pl
@@ -8,7 +8,7 @@ use XML::LibXML;
our @lines_rb;
my $os;
-if ($^O =~ /linux/i) {
+if ($^O =~ /linux/i or $^O =~ /darwin/i) {
$os = 'linux';
} else {
$os = 'windows';
From 0bdff401ca75d85490db621be367c80068e8e448 Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 14:12:32 +0200
Subject: [PATCH 09/31] ruby: fix codegen align int64_t on windows
---
plugins/ruby/codegen.pl | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl
index 1fcebfffe..67b86f835 100755
--- a/plugins/ruby/codegen.pl
+++ b/plugins/ruby/codegen.pl
@@ -516,7 +516,9 @@ sub get_field_align {
if ($meta eq 'number') {
$al = $field->getAttribute('ld:bits')/8;
- $al = 4 if $al > 4;
+ # linux aligns int64_t to 4, windows to 8
+ # floats are 4 bytes so no pb
+ $al = 4 if ($al > 4 and ($os eq 'linux' or $al != 8));
} elsif ($meta eq 'global') {
$al = get_global_align($field);
} elsif ($meta eq 'compound') {
From a7a25b80a0349d967a762b66ef12132f256da879 Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 16:10:10 +0200
Subject: [PATCH 10/31] ruby: use the color_ostream argument from dfhack to
output to dfhack-run
---
library/Core.cpp | 6 +++---
library/PluginManager.cpp | 2 +-
library/include/PluginManager.h | 4 ++--
plugins/ruby/ruby.cpp | 37 ++++++++++++++++++++++-----------
4 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index 09344135c..59334906d 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -281,7 +281,7 @@ static command_result runLuaScript(color_ostream &out, std::string name, vector<
return ok ? CR_OK : CR_FAILURE;
}
-static command_result runRubyScript(PluginManager *plug_mgr, std::string name, vector &args)
+static command_result runRubyScript(color_ostream &out, PluginManager *plug_mgr, std::string name, vector &args)
{
std::string rbcmd = "$script_args = [";
for (size_t i = 0; i < args.size(); i++)
@@ -290,7 +290,7 @@ static command_result runRubyScript(PluginManager *plug_mgr, std::string name, v
rbcmd += "load './hack/scripts/" + name + ".rb'";
- return plug_mgr->eval_ruby(rbcmd.c_str());
+ return plug_mgr->eval_ruby(out, rbcmd.c_str());
}
command_result Core::runCommand(color_ostream &out, const std::string &command)
@@ -632,7 +632,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
if (fileExists(filename + ".lua"))
res = runLuaScript(con, first, parts);
else if (plug_mgr->eval_ruby && fileExists(filename + ".rb"))
- res = runRubyScript(plug_mgr, first, parts);
+ res = runRubyScript(con, plug_mgr, first, parts);
else
con.printerr("%s is not a recognized command.\n", first.c_str());
}
diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp
index a314883e1..ff7524318 100644
--- a/library/PluginManager.cpp
+++ b/library/PluginManager.cpp
@@ -188,7 +188,7 @@ bool Plugin::load(color_ostream &con)
plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
plugin_rpcconnect = (RPCService* (*)(color_ostream &)) LookupPlugin(plug, "plugin_rpcconnect");
- plugin_eval_ruby = (command_result (*)(const char*)) LookupPlugin(plug, "plugin_eval_ruby");
+ plugin_eval_ruby = (command_result (*)(color_ostream &, const char*)) LookupPlugin(plug, "plugin_eval_ruby");
index_lua(plug);
this->name = *plug_name;
plugin_lib = plug;
diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h
index 5da9fc92f..22171a15c 100644
--- a/library/include/PluginManager.h
+++ b/library/include/PluginManager.h
@@ -209,7 +209,7 @@ namespace DFHack
command_result (*plugin_onupdate)(color_ostream &);
command_result (*plugin_onstatechange)(color_ostream &, state_change_event);
RPCService* (*plugin_rpcconnect)(color_ostream &);
- command_result (*plugin_eval_ruby)(const char*);
+ command_result (*plugin_eval_ruby)(color_ostream &, const char*);
};
class DFHACK_EXPORT PluginManager
{
@@ -238,7 +238,7 @@ namespace DFHack
{
return all_plugins.size();
}
- command_result (*eval_ruby)(const char*);
+ command_result (*eval_ruby)(color_ostream &, const char*);
// DATA
private:
tthread::mutex * cmdlist_mutex;
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index 0f5264515..f1f007263 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -35,9 +35,12 @@ tthread::mutex *m_irun;
tthread::mutex *m_mutex;
static volatile RB_command r_type;
static volatile command_result r_result;
+static color_ostream *r_console; // color_ostream given as argument, if NULL resort to console_proxy
static const char *r_command;
static tthread::thread *r_thread;
static int onupdate_active;
+static color_ostream_proxy *console_proxy;
+
DFHACK_PLUGIN("ruby")
@@ -115,7 +118,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
}
// send a single ruby line to be evaluated by the ruby thread
-DFhackCExport command_result plugin_eval_ruby(const char *command)
+DFhackCExport command_result plugin_eval_ruby( color_ostream &out, const char *command)
{
// if dlopen failed
if (!r_thread)
@@ -136,6 +139,7 @@ DFhackCExport command_result plugin_eval_ruby(const char *command)
r_type = RB_EVAL;
r_command = command;
+ r_console = &out;
// wake ruby thread up
m_irun->unlock();
@@ -144,6 +148,7 @@ DFhackCExport command_result plugin_eval_ruby(const char *command)
tthread::this_thread::yield();
ret = r_result;
+ r_console = NULL;
// block ruby thread
m_irun->lock();
@@ -164,7 +169,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (!onupdate_active)
return CR_OK;
- return plugin_eval_ruby("DFHack.onupdate");
+ return plugin_eval_ruby(out, "DFHack.onupdate");
}
DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_change_event e)
@@ -187,7 +192,7 @@ DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_ch
#undef SCASE
}
- return plugin_eval_ruby(cmd.c_str());
+ return plugin_eval_ruby(out, cmd.c_str());
}
static command_result df_rubyeval(color_ostream &out, std::vector & parameters)
@@ -209,7 +214,7 @@ static command_result df_rubyeval(color_ostream &out, std::vector
full += " ";
}
- return plugin_eval_ruby(full.c_str());
+ return plugin_eval_ruby(out, full.c_str());
}
@@ -265,7 +270,7 @@ static int df_loadruby(void)
#if defined(WIN32)
"./libruby.dll";
#elif defined(__APPLE__)
- "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/libruby.1.dylib";
+ "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/libruby.1.dylib";
#else
"hack/libruby.so";
#endif
@@ -310,6 +315,13 @@ static void df_unloadruby(void)
}
}
+static void printerr(const char* fmt, const char *arg)
+{
+ if (r_console)
+ r_console->printerr(fmt, arg);
+ else
+ Core::printerr(fmt, arg);
+}
// ruby thread code
static void dump_rb_error(void)
@@ -320,19 +332,17 @@ static void dump_rb_error(void)
s = rb_funcall(err, rb_intern("class"), 0);
s = rb_funcall(s, rb_intern("name"), 0);
- Core::printerr("E: %s: ", rb_string_value_ptr(&s));
+ printerr("E: %s: ", rb_string_value_ptr(&s));
s = rb_funcall(err, rb_intern("message"), 0);
- Core::printerr("%s\n", rb_string_value_ptr(&s));
+ printerr("%s\n", rb_string_value_ptr(&s));
err = rb_funcall(err, rb_intern("backtrace"), 0);
for (int i=0 ; i<8 ; ++i)
if ((s = rb_ary_shift(err)) != Qnil)
- Core::printerr(" %s\n", rb_string_value_ptr(&s));
+ printerr(" %s\n", rb_string_value_ptr(&s));
}
-static color_ostream_proxy *console_proxy;
-
// ruby thread main loop
static void df_rubythread(void *p)
{
@@ -428,13 +438,16 @@ static VALUE rb_dfonupdateactiveset(VALUE self, VALUE val)
static VALUE rb_dfprint_str(VALUE self, VALUE s)
{
- console_proxy->print("%s", rb_string_value_ptr(&s));
+ if (r_console)
+ r_console->print("%s", rb_string_value_ptr(&s));
+ else
+ console_proxy->print("%s", rb_string_value_ptr(&s));
return Qnil;
}
static VALUE rb_dfprint_err(VALUE self, VALUE s)
{
- Core::printerr("%s", rb_string_value_ptr(&s));
+ printerr("%s", rb_string_value_ptr(&s));
return Qnil;
}
From 1d6160de02c72513ab5e1b89152daae976744545 Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 17:41:09 +0200
Subject: [PATCH 11/31] added fixstuckdoors.rb script
---
scripts/fixstuckdoors.rb | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 scripts/fixstuckdoors.rb
diff --git a/scripts/fixstuckdoors.rb b/scripts/fixstuckdoors.rb
new file mode 100644
index 000000000..619ceeeb6
--- /dev/null
+++ b/scripts/fixstuckdoors.rb
@@ -0,0 +1,20 @@
+# fix doors that are frozen in 'open' state
+
+# door is stuck in open state if the map occupancy flag incorrectly indicates
+# that an unit is present (and creatures will prone to pass through)
+
+count = 0
+df.world.buildings.all.each { |bld|
+ # for all doors
+ next if bld._rtti_classname != :building_doorst
+ # check if it is open
+ next if bld.close_timer == 0
+ # check if occupancy is set
+ occ = df.map_occupancy_at(bld.x1, bld.y1, bld.z)
+ next if not occ.unit
+ # check if an unit is present
+ next if df.world.units.active.find { |u| u.pos.x == bld.x1 and u.pos.y == bld.y1 and u.pos.z == bld.z }
+ count += 1
+ occ.unit = false
+}
+puts "unstuck #{count} doors"
From 501fd43dda221fb94aae2da4ce4cfba8e349ae5c Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 18:40:10 +0200
Subject: [PATCH 12/31] ruby: fix handling of
---
plugins/ruby/ruby-autogen-defs.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 64da12ff9..3c004b41a 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -277,6 +277,7 @@ module DFHack
def _get
addr = _getp
return if addr == 0
+ return addr if not @_tg
@_tg._at(addr)._get
end
From 2e42e31754720e2bce830cec9b3a69b2966c15d5 Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 19:51:52 +0200
Subject: [PATCH 13/31] ruby: add curview, fix item_find/unit_find wrt gview
mode, fix refers-to to use binsearch
---
plugins/ruby/codegen.pl | 21 ++++++++++++++++++---
plugins/ruby/item.rb | 16 ++++++++++++----
plugins/ruby/ui.rb | 7 +++++++
plugins/ruby/unit.rb | 21 +++++++++++++--------
4 files changed, 50 insertions(+), 15 deletions(-)
diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl
index 67b86f835..9ec1eb788 100755
--- a/plugins/ruby/codegen.pl
+++ b/plugins/ruby/codegen.pl
@@ -298,8 +298,21 @@ sub render_field_reftarget {
return if (!$tg);
my $tgvec = $tg->getAttribute('instance-vector');
return if (!$tgvec);
+ my $idx = $tg->getAttribute('key-field') || 'id';
- render_field_refto($parent, $name, $tgvec);
+ $tgvec =~ s/^\$global/df/;
+ return if $tgvec !~ /^[\w\.]+$/;
+
+ my $tgname = "${name}_tg";
+ $tgname =~ s/_id(.?.?)_tg/_tg$1/;
+
+ for my $othername (map { $_->getAttribute('name') } $parent->findnodes('child::ld:field')) {
+ $tgname .= '_' if ($othername and $tgname eq $othername);
+ }
+
+ my $fidx = '';
+ $fidx = ', :' . $idx if ($idx ne 'id');
+ push @lines_rb, "def $tgname ; ${tgvec}.binsearch($name$fidx) ; end";
}
sub render_field_refto {
@@ -329,9 +342,9 @@ sub render_container_reftarget {
return if (!$tg);
my $tgvec = $tg->getAttribute('instance-vector');
return if (!$tgvec);
+ my $idx = $tg->getAttribute('key-field') || 'id';
$tgvec =~ s/^\$global/df/;
- $tgvec =~ s/\[\$\]$//;
return if $tgvec !~ /^[\w\.]+$/;
my $tgname = "${name}_tg";
@@ -341,7 +354,9 @@ sub render_container_reftarget {
$tgname .= '_' if ($othername and $tgname eq $othername);
}
- push @lines_rb, "def $tgname ; $name.map { |i| ${tgvec}[i] } ; end";
+ my $fidx = '';
+ $fidx = ', :' . $idx if ($idx ne 'id');
+ push @lines_rb, "def $tgname ; $name.map { |i| $tgvec.binsearch(i$fidx) } ; end";
}
sub render_class_vmethods {
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index cd95e82a9..87917bad5 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -4,10 +4,18 @@ module DFHack
# arg similar to unit.rb/unit_find; no arg = 'k' menu
def item_find(what=:selected)
if what == :selected
- case ui.main.mode
- when :LookAround
- k = ui_look_list.items[ui_look_cursor]
- k.item if k.type == :Item
+ if curview._rtti_classname == :viewscreen_itemst
+ ref = curview.entry_ref[curview.cursor_pos]
+ ref.item_tg if ref.kind_of?(GeneralRefItem)
+ else
+ case ui.main.mode
+ when :LookAround
+ k = ui_look_list.items[ui_look_cursor]
+ k.item if k.type == :Item
+ when :BuildingItems
+ bld = world.selected_building
+ bld.contained_items[ui_building_item_cursor].item if bld
+ end
end
elsif what.kind_of?(Integer)
world.items.all.binsearch(what)
diff --git a/plugins/ruby/ui.rb b/plugins/ruby/ui.rb
index fbe7ced77..6d2b5c2cd 100644
--- a/plugins/ruby/ui.rb
+++ b/plugins/ruby/ui.rb
@@ -1,6 +1,13 @@
# df user-interface related methods
module DFHack
class << self
+ # returns the current active viewscreen
+ def curview
+ ret = gview.view
+ ret = ret.child while ret.child
+ ret
+ end
+
# center the DF screen on something
# updates the cursor position if visible
def center_viewscreen(x, y=nil, z=nil)
diff --git a/plugins/ruby/unit.rb b/plugins/ruby/unit.rb
index e7d4335f0..b2f23e25f 100644
--- a/plugins/ruby/unit.rb
+++ b/plugins/ruby/unit.rb
@@ -6,14 +6,19 @@ module DFHack
# with an argument that respond to x/y/z (eg cursor), find first unit at this position
def unit_find(what=:selected)
if what == :selected
- case ui.main.mode
- when :ViewUnits
- # nobody selected => idx == 0
- v = world.units.active[ui_selected_unit]
- v if v and v.pos.z == cursor.z
- when :LookAround
- k = ui_look_list.items[ui_look_cursor]
- k.unit if k.type == :Unit
+ if curview._rtti_classname == :viewscreen_itemst
+ ref = curview.entry_ref[curview.cursor_pos]
+ ref.unit_tg if ref.kind_of?(GeneralRefUnit)
+ else
+ case ui.main.mode
+ when :ViewUnits
+ # nobody selected => idx == 0
+ v = world.units.active[ui_selected_unit]
+ v if v and v.pos.z == cursor.z
+ when :LookAround
+ k = ui_look_list.items[ui_look_cursor]
+ k.unit if k.type == :Unit
+ end
end
elsif what.kind_of?(Integer)
world.units.all.binsearch(what)
From 877b879e57b6c080a38df1d3a1af27530acf4eb2 Mon Sep 17 00:00:00 2001
From: jj
Date: Tue, 3 Jul 2012 23:57:15 +0200
Subject: [PATCH 14/31] ruby: item_find handle v/i unit inventory
---
plugins/ruby/item.rb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index 87917bad5..5df1aed87 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -15,6 +15,10 @@ module DFHack
when :BuildingItems
bld = world.selected_building
bld.contained_items[ui_building_item_cursor].item if bld
+ when :ViewUnits
+ u = world.units.active[ui_selected_unit]
+ u.inventory[ui_look_cursor].item if u and u.pos.z == cursor.z and
+ ui_unit_view_mode == :Inventory and u.inventory[ui_look_cursor]
end
end
elsif what.kind_of?(Integer)
From cb17bde8f47cc0e47c79d8dc33b38c5a8245a5e9 Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 15:18:36 +0200
Subject: [PATCH 15/31] ruby: refix codegen for refers-to without key-field,
add translate_name
---
plugins/ruby/codegen.pl | 25 ++++++++++-----
plugins/ruby/item.rb | 2 +-
plugins/ruby/ruby-autogen-defs.rb | 2 +-
plugins/ruby/ruby.rb | 51 +++++++++++++++++++++++++++++++
plugins/ruby/unit.rb | 6 ++++
5 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl
index 9ec1eb788..cbe7c932a 100755
--- a/plugins/ruby/codegen.pl
+++ b/plugins/ruby/codegen.pl
@@ -298,7 +298,7 @@ sub render_field_reftarget {
return if (!$tg);
my $tgvec = $tg->getAttribute('instance-vector');
return if (!$tgvec);
- my $idx = $tg->getAttribute('key-field') || 'id';
+ my $idx = $tg->getAttribute('key-field');
$tgvec =~ s/^\$global/df/;
return if $tgvec !~ /^[\w\.]+$/;
@@ -310,9 +310,14 @@ sub render_field_reftarget {
$tgname .= '_' if ($othername and $tgname eq $othername);
}
- my $fidx = '';
- $fidx = ', :' . $idx if ($idx ne 'id');
- push @lines_rb, "def $tgname ; ${tgvec}.binsearch($name$fidx) ; end";
+ if ($idx) {
+ my $fidx = '';
+ $fidx = ', :' . $idx if ($idx ne 'id');
+ push @lines_rb, "def $tgname ; ${tgvec}.binsearch($name$fidx) ; end";
+ } else {
+ push @lines_rb, "def $tgname ; ${tgvec}[$name] ; end";
+ }
+
}
sub render_field_refto {
@@ -342,7 +347,7 @@ sub render_container_reftarget {
return if (!$tg);
my $tgvec = $tg->getAttribute('instance-vector');
return if (!$tgvec);
- my $idx = $tg->getAttribute('key-field') || 'id';
+ my $idx = $tg->getAttribute('key-field');
$tgvec =~ s/^\$global/df/;
return if $tgvec !~ /^[\w\.]+$/;
@@ -354,9 +359,13 @@ sub render_container_reftarget {
$tgname .= '_' if ($othername and $tgname eq $othername);
}
- my $fidx = '';
- $fidx = ', :' . $idx if ($idx ne 'id');
- push @lines_rb, "def $tgname ; $name.map { |i| $tgvec.binsearch(i$fidx) } ; end";
+ if ($idx) {
+ my $fidx = '';
+ $fidx = ', :' . $idx if ($idx ne 'id');
+ push @lines_rb, "def $tgname ; $name.map { |i| $tgvec.binsearch(i$fidx) } ; end";
+ } else {
+ push @lines_rb, "def $tgname ; $name.map { |i| ${tgvec}[i] } ; end";
+ }
}
sub render_class_vmethods {
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index 5df1aed87..4acf45d60 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -18,7 +18,7 @@ module DFHack
when :ViewUnits
u = world.units.active[ui_selected_unit]
u.inventory[ui_look_cursor].item if u and u.pos.z == cursor.z and
- ui_unit_view_mode == :Inventory and u.inventory[ui_look_cursor]
+ ui_unit_view_mode.value == :Inventory and u.inventory[ui_look_cursor]
end
end
elsif what.kind_of?(Integer)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 3c004b41a..945eebceb 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -87,7 +87,7 @@ module DFHack
def compound(name=nil, &b)
m = Class.new(Compound)
DFHack.const_set(name, m) if name
- m.instance_eval(&b)
+ m.class_eval(&b)
m.new
end
def rtti_classname(n)
diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb
index 64592e3eb..4c692c92c 100644
--- a/plugins/ruby/ruby.rb
+++ b/plugins/ruby/ruby.rb
@@ -85,6 +85,57 @@ module DFHack
may = rawlist.find_all { |r| r.downcase.index(name.downcase) }
may.first if may.length == 1
end
+
+ def translate_name(name, english=true, onlylastpart=false)
+ out = []
+
+ if not onlylastpart
+ out << name.first_name if name.first_name != ''
+ if name.nickname != ''
+ case respond_to?(:d_init) && d_init.nickname_dwarf
+ when :REPLACE_ALL; return "`#{name.nickname}'"
+ when :REPLACE_FIRST; out.pop
+ end
+ out << "`#{name.nickname}'"
+ end
+ end
+ return out.join(' ') unless name.words.find { |w| w >= 0 }
+
+ if not english
+ tsl = world.raws.language.translations[name.language]
+ if name.words[0] >= 0 or name.words[1] >= 0
+ out << ''
+ out.last << tsl.words[name.words[0]] if name.words[0] >= 0
+ out.last << tsl.words[name.words[1]] if name.words[1] >= 0
+ end
+ if name.words[5] >= 0
+ out << ''
+ (2..5).each { |i| out.last << tsl.words[name.words[i]] if name.words[i] >= 0 }
+ end
+ if name.words[6] >= 0
+ out << tsl.words[name.words[6]]
+ end
+ else
+ wl = world.raws.language
+ if name.words[0] >= 0 or name.words[1] >= 0
+ out << ''
+ out.last << wl.words[name.words[0]].forms[name.parts_of_speech[0]] if name.words[0] >= 0
+ out.last << wl.words[name.words[1]].forms[name.parts_of_speech[1]] if name.words[1] >= 0
+ end
+ if name.words[5] >= 0
+ out << 'the '
+ out.last.capitalize! if out.length == 1
+ (2..5).each { |i| out.last << wl.words[name.words[i]].forms[name.parts_of_speech[i]] if name.words[i] >= 0 }
+ end
+ if name.words[6] >= 0
+ out << 'of'
+ out.last.capitalize! if out.length == 1
+ out << wl.words[name.words[6]].forms[name.parts_of_speech[6]]
+ end
+ end
+
+ out.join(' ')
+ end
end
end
diff --git a/plugins/ruby/unit.rb b/plugins/ruby/unit.rb
index b2f23e25f..3b5cebc43 100644
--- a/plugins/ruby/unit.rb
+++ b/plugins/ruby/unit.rb
@@ -80,4 +80,10 @@ module DFHack
list
end
end
+
+ class LanguageName
+ def to_s(english=true)
+ df.translate_name(self, english)
+ end
+ end
end
From edf0a9cb3d2d0a1696566fc0795609f27f74ac55 Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 17:24:03 +0200
Subject: [PATCH 16/31] ruby: add decode_mat method for mat_type/mat_index
---
plugins/ruby/README | 8 ++
plugins/ruby/material.rb | 199 +++++++++++++++++++++++++++++++++++++++
2 files changed, 207 insertions(+)
create mode 100644 plugins/ruby/material.rb
diff --git a/plugins/ruby/README b/plugins/ruby/README
index 690e83ca0..a3f9bf945 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -106,6 +106,14 @@ See buildings.rb/buildbed for an exemple.
df.each_tree(material) { |t| }
Iterates over every tree of the given material (eg 'maple').
+ df.translate_name(name, in_english=true, only_lastpart=false)
+Decode the LanguageName structure as a String as displayed in the game UI.
+A shortcut is available through name.to_s
+
+ df.decode_mat(obj)
+Returns a MaterialInfo definition for the given object, using its mat_type
+and mat_index fields. Also works with a token string argument ('STONE:DOLOMITE')
+
DFHack callbacks
----------------
diff --git a/plugins/ruby/material.rb b/plugins/ruby/material.rb
new file mode 100644
index 000000000..4a92118d6
--- /dev/null
+++ b/plugins/ruby/material.rb
@@ -0,0 +1,199 @@
+module DFHack
+ class MaterialInfo
+ attr_accessor :mat_type, :mat_index
+ attr_accessor :mode, :material, :creature, :figure, :plant, :inorganic
+ def initialize(what, idx=nil)
+ case what
+ when Integer
+ @mat_type, @mat_index = what, idx
+ decode_type_index
+ when String
+ decode_string(what)
+ else
+ @mat_type, @mat_index = what.mat_type, what.mat_index
+ decode_type_index
+ end
+ end
+
+ CREATURE_BASE = 19
+ FIGURE_BASE = CREATURE_BASE+200
+ PLANT_BASE = FIGURE_BASE+200
+ END_BASE = PLANT_BASE+200
+
+ # interpret the mat_type and mat_index fields
+ def decode_type_index
+ if @mat_index < 0 or @mat_type >= END_BASE
+ @mode = :Builtin
+ @material = df.world.raws.mat_table.builtin[@mat_type]
+
+ elsif @mat_type >= PLANT_BASE
+ @mode = :Plant
+ @plant = df.world.raws.plants.all[@mat_index]
+ @material = @plant.material[@mat_type-PLANT_BASE] if @plant
+
+ elsif @mat_type >= FIGURE_BASE
+ @mode = :Figure
+ @figure = df.world.history.figures.binsearch(@mat_index)
+ @creature = df.world.raws.creatures.all[@figure.race] if @figure
+ @material = @creature.material[@mat_type-FIGURE_BASE] if @creature
+
+ elsif @mat_type >= CREATURE_BASE
+ @mode = :Creature
+ @creature = df.world.raws.creatures.all[@mat_index]
+ @material = @creature.material[@mat_type-CREATURE_BASE] if @creature
+
+ elsif @mat_type > 0
+ @mode = :Builtin
+ @material = df.world.raws.mat_table.builtin[@mat_type]
+
+ elsif @mat_type == 0
+ @mode = :Inorganic
+ @inorganic = df.world.raws.inorganics[@mat_index]
+ @material = @inorganic.material if @inorganic
+ end
+ end
+
+ def decode_string(str)
+ parts = str.split(':')
+ case parts[0].chomp('_MAT')
+ when 'INORGANIC', 'STONE', 'METAL'
+ decode_string_inorganic(parts)
+ when 'PLANT'
+ decode_string_plant(parts)
+ when 'CREATURE'
+ if parts[3] and parts[3] != 'NONE'
+ decode_string_figure(parts)
+ else
+ decode_string_creature(parts)
+ end
+ when 'INVALID'
+ @mat_type = parts[1].to_i
+ @mat_index = parts[2].to_i
+ else
+ decode_string_builtin(parts)
+ end
+ end
+
+ def decode_string_inorganic(parts)
+ @@inorganics_index ||= (0...df.world.raws.inorganics.length).inject({}) { |h, i| h.update df.world.raws.inorganics[i].id => i }
+
+ @mode = :Inorganic
+ @mat_type = 0
+
+ if parts[1] and parts[1] != 'NONE'
+ @mat_index = @@inorganics_index[parts[1]]
+ raise "invalid inorganic token #{parts.join(':').inspect}" if not @mat_index
+ @inorganic = df.world.raws.inorganics[@mat_index]
+ @material = @inorganic.material
+ end
+ end
+
+ def decode_string_builtin(parts)
+ @@builtins_index ||= (1...df.world.raws.mat_table.builtin.length).inject({}) { |h, i| b = df.world.raws.mat_table.builtin[i] ; b ? h.update(b.id => i) : h }
+
+ @mode = :Builtin
+ @mat_index = -1
+ @mat_type = @@builtins_index[parts[0]]
+ raise "invalid builtin token #{parts.join(':').inspect}" if not @mat_type
+ @material = df.world.raws.mat_table.builtin[@mat_type]
+
+ if parts[0] == 'COAL' and parts[1]
+ @mat_index = ['COKE', 'CHARCOAL'].index(parts[1]) || -1
+ end
+ end
+
+ def decode_string_creature(parts)
+ @@creatures_index ||= (0...df.world.raws.creatures.all.length).inject({}) { |h, i| h.update df.world.raws.creatures.all[i].creature_id => i }
+
+ @mode = :Creature
+
+ if parts[1] and parts[1] != 'NONE'
+ @mat_index = @@creatures_index[parts[1]]
+ raise "invalid creature token #{parts.join(':').inspect}" if not @mat_index
+ @creature = df.world.raws.creatures.all[@mat_index]
+ end
+
+ if @creature and parts[2] and parts[2] != 'NONE'
+ @mat_type = @creature.material.index { |m| m.id == parts[2] }
+ @material = @creature.material[@mat_type]
+ @mat_type += CREATURE_BASE
+ end
+ end
+
+ def decode_string_figure(parts)
+ @mode = :Figure
+ @mat_index = parts[3].to_i
+ @figure = df.world.history.figures.binsearch(@mat_index)
+ raise "invalid creature histfig #{parts.join(':').inspect}" if not @figure
+
+ @creature = df.world.raws.creatures.all[@figure.race]
+ if parts[1] and parts[1] != 'NONE'
+ raise "invalid histfig race #{parts.join(':').inspect}" if @creature.creature_id != parts[1]
+ end
+
+ if @creature and parts[2] and parts[2] != 'NONE'
+ @mat_type = @creature.material.index { |m| m.id == parts[2] }
+ @material = @creature.material[@mat_type]
+ @mat_type += FIGURE_BASE
+ end
+ end
+
+ def decode_string_plant(parts)
+ @@plants_index ||= (0...df.world.raws.plants.all.length).inject({}) { |h, i| h.update df.world.raws.plants.all[i].id => i }
+
+ @mode = :Plant
+
+ if parts[1] and parts[1] != 'NONE'
+ @mat_index = @@plants_index[parts[1]]
+ raise "invalid plant token #{parts.join(':').inspect}" if not @mat_index
+ @plant = df.world.raws.plants.all[@mat_index]
+ end
+
+ if @plant and parts[2] and parts[2] != 'NONE'
+ @mat_type = @plant.material.index { |m| m.id == parts[2] }
+ raise "invalid plant type #{parts.join(':').inspect}" if not @mat_type
+ @material = @plant.material[@mat_type]
+ @mat_type += PLANT_BASE
+ end
+ end
+
+ # delete the caches of raws id => index used in decode_string
+ def self.flush_raws_cache
+ @@inorganics_index = @@plants_index = @@creatures_index = @@builtins_index = nil
+ end
+
+ def token
+ out = []
+ case @mode
+ when :Builtin
+ out << (@material ? @material.id : 'NONE')
+ out << (['COKE', 'CHARCOAL'][@mat_index] || 'NONE') if @material and @material.id == 'COAL' and @mat_index >= 0
+ when :Inorganic
+ out << 'INORGANIC'
+ out << @inorganic.id if @inorganic
+ when :Plant
+ out << 'PLANT_MAT'
+ out << @plant.id if @plant
+ out << @material.id if @plant and @material
+ when :Creature, :Figure
+ out << 'CREATURE_MAT'
+ out << @creature.creature_id if @creature
+ out << @material.id if @creature and @material
+ out << @figure.id.to_s if @creature and @material and @figure
+ else
+ out << 'INVALID'
+ out << @mat_type.to_s
+ out << @mat_index.to_s
+ end
+ out.join(':')
+ end
+
+ def to_s ; token ; end
+ end
+
+ class << self
+ def decode_mat(what, idx=nil)
+ MaterialInfo.new(what, idx)
+ end
+ end
+end
From 15cfc1d00b0ed1729a61171927deedd4e40c649b Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 17:24:46 +0200
Subject: [PATCH 17/31] ruby: handle constructed beds in item_find in
LookAround mode
---
plugins/ruby/item.rb | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index 4acf45d60..00f1ebf1f 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -11,7 +11,13 @@ module DFHack
case ui.main.mode
when :LookAround
k = ui_look_list.items[ui_look_cursor]
- k.item if k.type == :Item
+ case k.type
+ when :Item
+ k.item
+ when :Building
+ # hilight a constructed bed
+ k.building.contained_items[0].item if k.building.contained_items.length == 1
+ end
when :BuildingItems
bld = world.selected_building
bld.contained_items[ui_building_item_cursor].item if bld
From cdd711efa4654bcf1c2385bdf3ed943ad26f0895 Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 17:31:41 +0200
Subject: [PATCH 18/31] add COAL subtypes in MaterialInfo::getToken
---
library/modules/Materials.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp
index f8f99f81e..50cf21a9c 100644
--- a/library/modules/Materials.cpp
+++ b/library/modules/Materials.cpp
@@ -293,6 +293,12 @@ std::string MaterialInfo::getToken()
switch (mode) {
case Builtin:
+ if (material->id == "COAL") {
+ if (index == 0)
+ return "COAL:COKE";
+ else if (index == 1)
+ return "COAL:CHARCOAL";
+ }
return material->id;
case Inorganic:
return "INORGANIC:" + inorganic->id;
From 7c4f60df1d84ce3d70b62e165b1e1045c1b4808d Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 17:48:44 +0200
Subject: [PATCH 19/31] ruby: extend item_find to work on constructed coffers
---
plugins/ruby/item.rb | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index 00f1ebf1f..3b86f5e4f 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -15,8 +15,9 @@ module DFHack
when :Item
k.item
when :Building
- # hilight a constructed bed
- k.building.contained_items[0].item if k.building.contained_items.length == 1
+ # hilight a constructed bed/coffer
+ mats = k.building.contained_items.find_all { |i| i.use_mode == 2 }
+ mats[0].item if mats.length == 1
end
when :BuildingItems
bld = world.selected_building
From f80ca239d02c5e130a4df918a4144912bcdef26c Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 18:34:41 +0200
Subject: [PATCH 20/31] ruby: allow coords arguments to *_find, add
building_find
---
plugins/ruby/building.rb | 40 ++++++++++++++++++++++++++++++++++++++++
plugins/ruby/item.rb | 8 ++++++--
plugins/ruby/unit.rb | 8 ++++++--
3 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/plugins/ruby/building.rb b/plugins/ruby/building.rb
index 826cd26b9..9a59411f9 100644
--- a/plugins/ruby/building.rb
+++ b/plugins/ruby/building.rb
@@ -1,5 +1,45 @@
module DFHack
class << self
+ def building_find(what=:selected, y=nil, z=nil)
+ if what == :selected
+ case ui.main.mode
+ when :LookAround
+ k = ui_look_list.items[ui_look_cursor]
+ k.building if k.type == :Building
+ when :BuildingItems, :QueryBuilding
+ world.selected_building
+ end
+
+ elsif what.kind_of?(Integer)
+ # search by building.id
+ return world.buildings.all.binsearch(what) if not z
+
+ # search by coordinates
+ x = what
+ world.buildings.all.find { |b|
+ b.z == z and
+ if b.room.extents
+ dx = x - b.room.x
+ dy = y - b.room.y
+ dx >= 0 and dx <= b.room.width and
+ dy >= 0 and dy <= b.room.height and
+ b.room.extents[ dy*b.room.width + dx ] > 0
+ else
+ b.x1 <= x and b.x2 >= x and
+ b.y1 <= y and b.y2 >= y
+ end
+ }
+
+ elsif what.respond_to?(:x) or what.respond_to?(:pos)
+ # find the building at the same position
+ what = what.pos if what.respond_to?(:pos)
+ building_find(what.x, what.y, what.z)
+
+ else
+ raise "what what?"
+ end
+ end
+
# allocate a new building object
def building_alloc(type, subtype=-1, custom=-1)
cls = rtti_n2c[BuildingType::Classname[type].to_sym]
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index 3b86f5e4f..a3fe68b97 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -2,7 +2,7 @@ module DFHack
class << self
# return an Item
# arg similar to unit.rb/unit_find; no arg = 'k' menu
- def item_find(what=:selected)
+ def item_find(what=:selected, y=nil, z=nil)
if what == :selected
if curview._rtti_classname == :viewscreen_itemst
ref = curview.entry_ref[curview.cursor_pos]
@@ -29,7 +29,11 @@ module DFHack
end
end
elsif what.kind_of?(Integer)
- world.items.all.binsearch(what)
+ # search by id
+ return world.items.all.binsearch(what) if not z
+ # search by position
+ x = what
+ world.items.all.find { |i| i.pos.x == x and i.pos.y == y and i.pos.z == z }
elsif what.respond_to?(:x) or what.respond_to?(:pos)
world.items.all.find { |i| same_pos?(what, i) }
else
diff --git a/plugins/ruby/unit.rb b/plugins/ruby/unit.rb
index 3b5cebc43..04deee0e3 100644
--- a/plugins/ruby/unit.rb
+++ b/plugins/ruby/unit.rb
@@ -4,7 +4,7 @@ module DFHack
# with no arg, return currently selected unit in df UI ('v' or 'k' menu)
# with numeric arg, search unit by unit.id
# with an argument that respond to x/y/z (eg cursor), find first unit at this position
- def unit_find(what=:selected)
+ def unit_find(what=:selected, y=nil, z=nil)
if what == :selected
if curview._rtti_classname == :viewscreen_itemst
ref = curview.entry_ref[curview.cursor_pos]
@@ -21,7 +21,11 @@ module DFHack
end
end
elsif what.kind_of?(Integer)
- world.units.all.binsearch(what)
+ # search by id
+ return world.units.all.binsearch(what) if not z
+ # search by coords
+ x = what
+ world.units.all.find { |u| u.pos.x == x and u.pos.y == y and u.pos.z == z }
elsif what.respond_to?(:x) or what.respond_to?(:pos)
world.units.all.find { |u| same_pos?(what, u) }
else
From e4d4bf23ae0a919ba7b2d5575ff74a01f63bd808 Mon Sep 17 00:00:00 2001
From: jj
Date: Wed, 4 Jul 2012 19:05:44 +0200
Subject: [PATCH 21/31] update xml, fix autolabor with new trade depot flags
name
---
library/xml | 2 +-
plugins/autolabor.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/library/xml b/library/xml
index ad38c5e96..eb6f706d7 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit ad38c5e96b05fedf16114fd16bd463e933f13582
+Subproject commit eb6f706d702367ea3121272670e603000bbdd42a
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index de1a1aef6..3bae1e1b3 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -740,7 +740,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
else if (df::enums::building_type::TradeDepot == type)
{
df::building_tradedepotst* depot = (df::building_tradedepotst*) build;
- trader_requested = depot->flags.bits.trader_requested;
+ trader_requested = depot->trade_flags.bits.trader_requested;
if (print_debug)
out.print("Trade depot found and trader requested, trader will be excluded from all labors.\n");
}
From f560d2de1137940942c3b9cb926a0093359e80fa Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 5 Jul 2012 14:15:34 +0200
Subject: [PATCH 22/31] ruby: add MapTile class
---
plugins/ruby/README | 3 ++
plugins/ruby/item.rb | 2 +-
plugins/ruby/map.rb | 112 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/plugins/ruby/README b/plugins/ruby/README
index a3f9bf945..493e3c821 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -66,6 +66,9 @@ obj1 and 2 should respond to #pos and #x #y #z.
df.map_block_at(pos) / map_block_at(x, y, z)
Returns the MapBlock for the coordinates or nil.
+ df.map_tile_at(pos)
+Returns a MapTile, holds all information relative to the map tile.
+
df.each_map_block { |b| }
df.each_map_block_z(zlevel) { |b| }
Iterates over every map block (opt. on a single z-level).
diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb
index a3fe68b97..34b404505 100644
--- a/plugins/ruby/item.rb
+++ b/plugins/ruby/item.rb
@@ -33,7 +33,7 @@ module DFHack
return world.items.all.binsearch(what) if not z
# search by position
x = what
- world.items.all.find { |i| i.pos.x == x and i.pos.y == y and i.pos.z == z }
+ world.items.all.find { |i| i.pos.x == x and i.pos.y == y and i.pos.z == z }
elsif what.respond_to?(:x) or what.respond_to?(:pos)
world.items.all.find { |i| same_pos?(what, i) }
else
diff --git a/plugins/ruby/map.rb b/plugins/ruby/map.rb
index af9e8b804..a0438670d 100644
--- a/plugins/ruby/map.rb
+++ b/plugins/ruby/map.rb
@@ -26,6 +26,13 @@ module DFHack
end
end
+ def map_tile_at(x, y=nil, z=nil)
+ x = x.pos if x.respond_to?(:pos)
+ x, y, z = x.x, x.y, x.z if x.respond_to?(:x)
+ b = map_block_at(x, y, z)
+ MapTile.new(b, x, y, z) if b
+ end
+
# yields every map block
def each_map_block
(0...world.map.x_count_block).each { |xb|
@@ -51,4 +58,109 @@ module DFHack
}
end
end
+
+ class MapTile
+ attr_accessor :x, :y, :z, :dx, :dy, :mapblock
+ def initialize(b, x, y, z)
+ @x, @y, @z = x, y, z
+ @dx, @dy = @x&15, @y&15
+ @mapblock = b
+ end
+
+ def designation
+ @mapblock.designation[@dx][@dy]
+ end
+
+ def occupancy
+ @mapblock.occupancy[@dx][@dy]
+ end
+
+ def tiletype
+ @mapblock.tiletype[@dx][@dy]
+ end
+
+ def tiletype=(t)
+ @mapblock.tiletype[@dx][@dy] = t
+ end
+
+ def caption
+ Tiletype::Caption[tiletype]
+ end
+
+ def shape
+ Tiletype::Shape[tiletype]
+ end
+
+ def tilemat
+ Tiletype::Material[tiletype]
+ end
+
+ def variant
+ Tiletype::Variant[tiletype]
+ end
+
+ def special
+ Tiletype::Special[tiletype]
+ end
+
+ def direction
+ Tiletype::Direction[tiletype]
+ end
+
+ # return all veins for current mapblock
+ def all_veins
+ mapblock.block_events.grep(BlockSquareEventMineralst)
+ end
+
+ # return the vein applicable to current tile
+ def vein
+ # last vein wins
+ all_veins.reverse.find { |v|
+ (v.tile_bitmask.bits[@dy] & (1 << @dx)) > 0
+ }
+ end
+
+ # return the mat_index for the current tile (if in vein)
+ def mat_index_vein
+ v = vein
+ v.inorganic_mat if v
+ end
+
+ # return the world_data.geo_biome for current tile
+ def geo_biome
+ b = designation.biome
+ wd = df.world.world_data
+
+ # region coords + [[-1, -1], [0, -1], ..., [1, 1]][b]
+ # clipped to world dimensions
+ rx = df.world.map.region_x/16
+ rx -= 1 if b % 3 == 0 and rx > 0
+ rx += 1 if b % 3 == 2 and rx < wd.world_width-1
+
+ ry = df.world.map.region_y/16
+ ry -= 1 if b < 3 and ry > 0
+ ry += 1 if b > 5 and ry < wd.world_height-1
+
+ wd.geo_biomes[ wd.region_map[rx][ry].geo_index ]
+ end
+
+ # return the world_data.geo_biome.layer for current tile
+ def stone_layer
+ geo_biome.layers[designation.geolayer_index]
+ end
+
+ # current tile mat_index (vein if applicable, or base material)
+ def mat_index
+ mat_index_vein or stone_layer.mat_index
+ end
+
+ # MaterialInfo: inorganic token for current tile
+ def mat_info
+ MaterialInfo.new(0, mat_index)
+ end
+
+ def inspect
+ "#"
+ end
+ end
end
From 7732901b6ec1af9ed5e77a118bade7285da3e018 Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 5 Jul 2012 15:35:37 +0200
Subject: [PATCH 23/31] ruby: tweak onupdate to allow tick rate-limiting
---
plugins/ruby/README | 4 +++
plugins/ruby/ruby.cpp | 45 +++++++++++++++++++++++++++-----
plugins/ruby/ruby.rb | 60 ++++++++++++++++++++++++++++++++++++++++---
3 files changed, 98 insertions(+), 11 deletions(-)
diff --git a/plugins/ruby/README b/plugins/ruby/README
index 493e3c821..97a4cbd30 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -124,6 +124,10 @@ DFHack callbacks
The plugin interfaces with dfhack 'onupdate' hook.
To register ruby code to be run every graphic frame, use:
handle = df.onupdate_register { puts 'i love flooding the console' }
+You can also rate-limit when your callback is called to a number of game ticks:
+ handle = df.onupdate_register(10) { puts '10 more in-game ticks elapsed' }
+In this case, the callback is called immediately, and then every X in-game
+ticks (advances only when the game is unpaused).
To stop being called, use:
df.onupdate_unregister handle
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index f1f007263..6dd0b39c8 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -6,8 +6,7 @@
#include "VersionInfo.h"
#include "DataDefs.h"
-#include "df/world.h"
-#include "df/unit.h"
+#include "df/global_objects.h"
#include "tinythread.h"
@@ -39,6 +38,7 @@ static color_ostream *r_console; // color_ostream given as argument, if NU
static const char *r_command;
static tthread::thread *r_thread;
static int onupdate_active;
+static int onupdate_minyear, onupdate_minyeartick;
static color_ostream_proxy *console_proxy;
@@ -165,10 +165,15 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
// ruby sets this flag when needed, to avoid lag running ruby code every
// frame if not necessary
- // TODO dynamic check on df::cur_year{_tick}
if (!onupdate_active)
return CR_OK;
+ if (*df::global::cur_year < onupdate_minyear)
+ return CR_OK;
+ if (*df::global::cur_year == onupdate_minyear &&
+ *df::global::cur_year_tick < onupdate_minyeartick)
+ return CR_OK;
+
return plugin_eval_ruby(out, "DFHack.onupdate");
}
@@ -422,7 +427,7 @@ static VALUE rb_cDFHack;
// DFHack module ruby methods, binds specific dfhack methods
// enable/disable calls to DFHack.onupdate()
-static VALUE rb_dfonupdateactive(VALUE self)
+static VALUE rb_dfonupdate_active(VALUE self)
{
if (onupdate_active)
return Qtrue;
@@ -430,12 +435,34 @@ static VALUE rb_dfonupdateactive(VALUE self)
return Qfalse;
}
-static VALUE rb_dfonupdateactiveset(VALUE self, VALUE val)
+static VALUE rb_dfonupdate_active_set(VALUE self, VALUE val)
{
onupdate_active = (BOOL_ISFALSE(val) ? 0 : 1);
return Qtrue;
}
+static VALUE rb_dfonupdate_minyear(VALUE self)
+{
+ return rb_uint2inum(onupdate_minyear);
+}
+
+static VALUE rb_dfonupdate_minyear_set(VALUE self, VALUE val)
+{
+ onupdate_minyear = rb_num2ulong(val);
+ return Qtrue;
+}
+
+static VALUE rb_dfonupdate_minyeartick(VALUE self)
+{
+ return rb_uint2inum(onupdate_minyeartick);
+}
+
+static VALUE rb_dfonupdate_minyeartick_set(VALUE self, VALUE val)
+{
+ onupdate_minyeartick = rb_num2ulong(val);
+ return Qtrue;
+}
+
static VALUE rb_dfprint_str(VALUE self, VALUE s)
{
if (r_console)
@@ -777,8 +804,12 @@ static VALUE rb_dfvcall(VALUE self, VALUE cppobj, VALUE cppvoff, VALUE a0, VALUE
static void ruby_bind_dfhack(void) {
rb_cDFHack = rb_define_module("DFHack");
- rb_define_singleton_method(rb_cDFHack, "onupdate_active", RUBY_METHOD_FUNC(rb_dfonupdateactive), 0);
- rb_define_singleton_method(rb_cDFHack, "onupdate_active=", RUBY_METHOD_FUNC(rb_dfonupdateactiveset), 1);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_active", RUBY_METHOD_FUNC(rb_dfonupdate_active), 0);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_active=", RUBY_METHOD_FUNC(rb_dfonupdate_active_set), 1);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_minyear", RUBY_METHOD_FUNC(rb_dfonupdate_minyear), 0);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_minyear=", RUBY_METHOD_FUNC(rb_dfonupdate_minyear_set), 1);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_minyeartick", RUBY_METHOD_FUNC(rb_dfonupdate_minyeartick), 0);
+ rb_define_singleton_method(rb_cDFHack, "onupdate_minyeartick=", RUBY_METHOD_FUNC(rb_dfonupdate_minyeartick_set), 1);
rb_define_singleton_method(rb_cDFHack, "get_global_address", RUBY_METHOD_FUNC(rb_dfget_global_address), 1);
rb_define_singleton_method(rb_cDFHack, "get_vtable", RUBY_METHOD_FUNC(rb_dfget_vtable), 1);
rb_define_singleton_method(rb_cDFHack, "get_rtti_classname", RUBY_METHOD_FUNC(rb_dfget_rtti_classname), 1);
diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb
index 4c692c92c..eda6ffd52 100644
--- a/plugins/ruby/ruby.rb
+++ b/plugins/ruby/ruby.rb
@@ -23,26 +23,78 @@ module Kernel
end
module DFHack
+ class OnupdateCallback
+ attr_accessor :callback, :timelimit, :minyear, :minyeartick
+ def initialize(cb, tl)
+ @callback = cb
+ @ticklimit = tl
+ @minyear = (tl ? df.cur_year : 0)
+ @minyeartick = (tl ? df.cur_year_tick : 0)
+ end
+
+ # run callback if timedout
+ def check_run(year, yeartick, yearlen)
+ if !@ticklimit
+ @callback.call
+ else
+ if year > @minyear or (year == @minyear and yeartick >= @minyeartick)
+ @callback.call
+ @minyear = year
+ @minyeartick = yeartick + @ticklimit
+ if @minyeartick > yearlen
+ @minyear += 1
+ @minyeartick -= yearlen
+ end
+ end
+ end
+ end
+
+ def <=>(o)
+ [@minyear, @minyeartick] <=> [o.minyear, o.minyeartick]
+ end
+ end
+
class << self
+ attr_accessor :onupdate_list, :onstatechange_list
+
# register a callback to be called every gframe or more
# ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 }
- def onupdate_register(&b)
+ def onupdate_register(ticklimit=nil, &b)
@onupdate_list ||= []
- @onupdate_list << b
+ @onupdate_list << OnupdateCallback.new(b, ticklimit)
DFHack.onupdate_active = true
+ if onext = @onupdate_list.sort.first
+ DFHack.onupdate_minyear = onext.minyear
+ DFHack.onupdate_minyeartick = onext.minyeartick
+ end
@onupdate_list.last
end
# delete the callback for onupdate ; use the value returned by onupdate_register
def onupdate_unregister(b)
@onupdate_list.delete b
- DFHack.onupdate_active = false if @onupdate_list.empty?
+ if @onupdate_list.empty?
+ DFHack.onupdate_active = false
+ DFHack.onupdate_minyear = DFHack.onupdate_minyeartick = 0
+ end
end
+ TICKS_PER_YEAR = 1200*28*12
# this method is called by dfhack every 'onupdate' if onupdate_active is true
def onupdate
@onupdate_list ||= []
- @onupdate_list.each { |cb| cb.call }
+
+ ticks_per_year = TICKS_PER_YEAR
+ ticks_per_year *= 72 if gametype == :ADVENTURE_MAIN or gametype == :ADVENTURE_ARENA
+
+ @onupdate_list.each { |o|
+ o.check_run(cur_year, cur_year_tick, ticks_per_year)
+ }
+
+ if onext = @onupdate_list.sort.first
+ DFHack.onupdate_minyear = onext.minyear
+ DFHack.onupdate_minyeartick = onext.minyeartick
+ end
end
# register a callback to be called every gframe or more
From 70740481463bbde3f078b612e529e6c7a3b6704d Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 5 Jul 2012 16:17:41 +0200
Subject: [PATCH 24/31] showmood: display number of items already collected
---
plugins/ruby/ruby.rb | 2 +-
plugins/showmood.cpp | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb
index eda6ffd52..5ae63ebfe 100644
--- a/plugins/ruby/ruby.rb
+++ b/plugins/ruby/ruby.rb
@@ -66,7 +66,7 @@ module DFHack
if onext = @onupdate_list.sort.first
DFHack.onupdate_minyear = onext.minyear
DFHack.onupdate_minyeartick = onext.minyeartick
- end
+ end
@onupdate_list.last
end
diff --git a/plugins/showmood.cpp b/plugins/showmood.cpp
index 7926e2ac5..10d7b52c2 100644
--- a/plugins/showmood.cpp
+++ b/plugins/showmood.cpp
@@ -165,6 +165,8 @@ command_result df_showmood (color_ostream &out, vector & parameters)
out.print("not yet claimed a workshop but will want");
out.print(" the following items:\n");
+ int count_got = job->items.size(), got;
+
for (size_t i = 0; i < job->job_items.size(); i++)
{
df::job_item *item = job->job_items[i];
@@ -267,7 +269,11 @@ command_result df_showmood (color_ostream &out, vector & parameters)
}
}
- out.print(", quantity %i\n", item->quantity);
+ got = count_got;
+ if (got > item->quantity)
+ got = item->quantity;
+ out.print(", quantity %i (got %i)\n", item->quantity, got);
+ count_got -= got;
}
}
if (!found)
From 8e17ebbefc5da79b34219b87b310038af1077871 Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 5 Jul 2012 18:03:02 +0200
Subject: [PATCH 25/31] add SC_PAUSED / SC_UNPAUSED onStateChange events
---
library/Core.cpp | 10 ++++++++++
library/include/Core.h | 5 ++++-
library/lua/dfhack.lua | 2 ++
plugins/ruby/ruby.cpp | 2 ++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index 59334906d..826576b77 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -752,6 +752,7 @@ Core::Core()
misc_data_mutex=0;
last_world_data_ptr = NULL;
last_local_map_ptr = NULL;
+ last_pause_state = false;
top_viewscreen = NULL;
screen_window = NULL;
server = NULL;
@@ -1116,6 +1117,15 @@ int Core::Update()
}
}
+ if (df::global::pause_state)
+ {
+ if (*df::global::pause_state != last_pause_state)
+ {
+ onStateChange(out, last_pause_state ? SC_UNPAUSED : SC_PAUSED);
+ last_pause_state = *df::global::pause_state;
+ }
+ }
+
// Execute per-frame handlers
onUpdate(out);
diff --git a/library/include/Core.h b/library/include/Core.h
index e4d1080d6..0d5d3150e 100644
--- a/library/include/Core.h
+++ b/library/include/Core.h
@@ -75,7 +75,9 @@ namespace DFHack
SC_MAP_UNLOADED = 3,
SC_VIEWSCREEN_CHANGED = 4,
SC_CORE_INITIALIZED = 5,
- SC_BEGIN_UNLOAD = 6
+ SC_BEGIN_UNLOAD = 6,
+ SC_PAUSED = 7,
+ SC_UNPAUSED = 8
};
// Core is a singleton. Why? Because it is closely tied to SDL calls. It tracks the global state of DF.
@@ -221,6 +223,7 @@ namespace DFHack
// for state change tracking
void *last_local_map_ptr;
df::viewscreen *top_viewscreen;
+ bool last_pause_state;
// Very important!
bool started;
diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua
index d56d4df60..86ea1459f 100644
--- a/library/lua/dfhack.lua
+++ b/library/lua/dfhack.lua
@@ -39,6 +39,8 @@ if dfhack.is_core_context then
SC_MAP_UNLOADED = 3
SC_VIEWSCREEN_CHANGED = 4
SC_CORE_INITIALIZED = 5
+ SC_PAUSED = 7
+ SC_UNPAUSED = 8
end
-- Error handling
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index 6dd0b39c8..08ea13b9f 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -194,6 +194,8 @@ DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_ch
// if we go through plugin_eval at BEGIN_UNLOAD, it'll
// try to get the suspend lock and deadlock at df exit
case SC_BEGIN_UNLOAD : return CR_OK;
+ SCASE(PAUSED);
+ SCASE(UNPAUSED);
#undef SCASE
}
From fb8f0510a4b8c1760e44fcbe35d04d9b03f709df Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 6 Jul 2012 13:00:38 +0200
Subject: [PATCH 26/31] ruby: update gitignore
---
.gitignore | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.gitignore b/.gitignore
index 81b55ffdb..1fc1acae0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,10 @@ dfhack/python/PyDFHack.egg-info
dfhack/python/build
dfhack/python/dist
+# Ruby binding binaries
+plugins/ruby/libruby*
+plugins/ruby/ruby-autogen.rb
+
# CPack stuff
build/CPack*Config.cmake
From 1c5b5b956f1a92bd25f7bab544c463fbff9d8f4a Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 6 Jul 2012 13:01:53 +0200
Subject: [PATCH 27/31] gitignore build/install_manifest
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 1fc1acae0..ceb0aa27a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ build/library
build/tools
build/plugins
build/depends
+build/install_manifest.txt
#ignore Kdevelop stuff
.kdev4
From bef5079d436c70be897d9b25e9bfe12ffa9d0eea Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 6 Jul 2012 13:25:47 +0200
Subject: [PATCH 28/31] ruby: add vector.first/last
---
plugins/ruby/ruby-autogen-defs.rb | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 945eebceb..f9858c949 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -354,7 +354,9 @@ module DFHack
end
def empty? ; length == 0 ; end
def flatten ; map { |e| e.respond_to?(:flatten) ? e.flatten : e }.flatten ; end
- def index(elem=nil, &b) ; (0...length).find { |i| b ? b[self[i]] : self[i] == elem } ; end
+ def index(e=nil, &b) ; (0...length).find { |i| b ? b[self[i]] : self[i] == e } ; end
+ def first ; self[0] ; end
+ def last ; self[length-1] ; end
end
class StaticArray < MemStruct
attr_accessor :_tglen, :_length, :_indexenum, :_tg
From d645d6b0465e4a280aa975e9a78b3508d316ce2f Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 6 Jul 2012 13:32:39 +0200
Subject: [PATCH 29/31] ruby: better message on out of bounds array access
---
plugins/ruby/ruby-autogen-defs.rb | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index f9858c949..a1cba4168 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -380,12 +380,18 @@ module DFHack
def [](i)
i = _indexenum.int(i) if _indexenum
i += @_length if i < 0
- _tgat(i)._get
+ if t = _tgat(i)
+ t._get
+ end
end
def []=(i, v)
i = _indexenum.int(i) if _indexenum
i += @_length if i < 0
- _tgat(i)._set(v)
+ if t = _tgat(i)
+ t._set(v)
+ else
+ raise 'index out of bounds'
+ end
end
include Enumerable
@@ -444,7 +450,7 @@ module DFHack
if idx >= length
insert_at(idx, 0)
elsif idx < 0
- raise 'invalid idx'
+ raise 'index out of bounds'
end
@_tg._at(valueptr_at(idx))._set(v)
end
@@ -530,7 +536,7 @@ module DFHack
if idx >= length
insert_at(idx, v)
elsif idx < 0
- raise 'invalid idx'
+ raise 'index out of bounds'
else
DFHack.memory_vectorbool_setat(@_memaddr, idx, v)
end
@@ -582,7 +588,7 @@ module DFHack
idx = _indexenum.int(idx) if _indexenum
idx += length if idx < 0
if idx >= length or idx < 0
- raise 'invalid idx'
+ raise 'index out of bounds'
else
DFHack.memory_bitarray_set(@_memaddr, idx, v)
end
@@ -608,11 +614,17 @@ module DFHack
end
def [](i)
i += _length if i < 0
- _tgat(i)._get
+ if t = _tgat(i)
+ t._get
+ end
end
def []=(i, v)
i += _length if i < 0
- _tgat(i)._set(v)
+ if t = _tgat(i)
+ t._set(v)
+ else
+ raise 'index out of bounds'
+ end
end
def _set(a)
a.each_with_index { |v, i| self[i] = v }
From 4bbb185f7ba546fbab44e275fa243abb764e7571 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Fri, 6 Jul 2012 20:11:20 +0400
Subject: [PATCH 30/31] Fix build and allow autodump to any walkable tile (e.g.
a stair).
---
library/xml | 2 +-
plugins/autodump.cpp | 2 +-
plugins/autolabor.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/library/xml b/library/xml
index ad38c5e96..b646637f8 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit ad38c5e96b05fedf16114fd16bd463e933f13582
+Subproject commit b646637f8eb901a95c82e60ccd4713e763e00179
diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp
index 536b2501b..cfb73fa8b 100644
--- a/plugins/autodump.cpp
+++ b/plugins/autodump.cpp
@@ -140,7 +140,7 @@ static command_result autodump_main(color_ostream &out, vector & parame
return CR_FAILURE;
}
df::tiletype ttype = MC.tiletypeAt(pos_cursor);
- if(!DFHack::isFloorTerrain(ttype))
+ if(!DFHack::isWalkable(ttype) || DFHack::isOpenTerrain(ttype))
{
out.printerr("Cursor should be placed over a floor.\n");
return CR_FAILURE;
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index de1a1aef6..3bae1e1b3 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -740,7 +740,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
else if (df::enums::building_type::TradeDepot == type)
{
df::building_tradedepotst* depot = (df::building_tradedepotst*) build;
- trader_requested = depot->flags.bits.trader_requested;
+ trader_requested = depot->trade_flags.bits.trader_requested;
if (print_debug)
out.print("Trade depot found and trader requested, trader will be excluded from all labors.\n");
}
From 028b47a3213ef951690a1006dc7f9ad60f03917f Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 6 Jul 2012 20:36:53 +0200
Subject: [PATCH 31/31] update xml
---
library/xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/xml b/library/xml
index eb6f706d7..b646637f8 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit eb6f706d702367ea3121272670e603000bbdd42a
+Subproject commit b646637f8eb901a95c82e60ccd4713e763e00179