diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl index effcb9327..a13f0948c 100755 --- a/plugins/ruby/codegen.pl +++ b/plugins/ruby/codegen.pl @@ -149,6 +149,9 @@ sub render_struct_fields { for my $field ($type->findnodes('child::ld:field')) { my $name = $field->getAttribute('name'); $name = $field->getAttribute('ld:anon-name') if (!$name); + if (!$name and $field->getAttribute('ld:anon-compound')) { + render_struct_fields($field, $cppvar); + } next if (!$name); my $offset = get_offset($cppvar, $name); diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index 8bf42be04..06f5654ad 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -273,7 +273,7 @@ static void df_rubythread(void *p) r_result = CR_OK; r_type = RB_IDLE; m_irun->unlock(); - tthread::this_thread::yield(); + tthread::this_thread::yield(); } } @@ -374,6 +374,18 @@ static VALUE rb_dfget_global_address(VALUE self, VALUE name) return rb_uint2inum(addr); } +static VALUE rb_dfget_vtable(VALUE self, VALUE name) +{ + uint32_t addr = (uint32_t)Core::getInstance().vinfo->getVTable(rb_string_value_ptr(&name)); + return rb_uint2inum(addr); +} + +static VALUE rb_dfget_rtti_classname(VALUE self, VALUE objptr) +{ + void **ptr = (void**)rb_num2ulong(objptr); + return rb_str_new2(typeid(*ptr).name()); +} + @@ -569,6 +581,8 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "resume", RUBY_METHOD_FUNC(rb_dfresume), 0); rb_define_singleton_method(rb_cDFHack, "do_suspend", RUBY_METHOD_FUNC(rb_dfsuspend), 0); 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); rb_define_singleton_method(rb_cDFHack, "register_dfcommand", RUBY_METHOD_FUNC(rb_dfregister), 2); rb_define_singleton_method(rb_cDFHack, "print_str", RUBY_METHOD_FUNC(rb_dfprint_str), 1); rb_define_singleton_method(rb_cDFHack, "print_err", RUBY_METHOD_FUNC(rb_dfprint_err), 1); diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index 13567c9ec..a75404365 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -29,16 +29,75 @@ module DFHack nil end + # return an Unit + # 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 find_unit(what=nil) + if what == nil + case ui.main.mode + when UiSidebarMode::ViewUnits + # nobody selected => idx == 0 + v = world.units.other[0][ui_selected_unit] + v if v and v.z == cursor.z + when UiSidebarMode::LookAround + k = ui_look_list.items[ui_look_cursor] + k.unit if k.type == MemHack::UiLookList::Unit + end + elsif what.kind_of?(Integer) + world.units.all.find { |u| u.id == what } + elsif what.respond_to?(:x) or what.respond_to?(:pos) + what = what.pos if what.respond_to?(:pos) + x, y, z = what.x, what.y, what.z + world.units.all.find { |u| u.pos.x == x and u.pos.y == y and u.pos.z == z } + else + raise "what what?" + end + end + + # return an Item + # arg similar to find_unit + def find_item(what=nil) + if what == nil + case ui.main.mode + when UiSidebarMode::LookAround + k = ui_look_list.items[ui_look_cursor] + k.item if k.type == MemHack::UiLookList::Item + end + elsif what.kind_of?(Integer) + world.items.all.find { |i| i.id == what } + elsif what.respond_to?(:x) or what.respond_to?(:pos) + what = what.pos if what.respond_to?(:pos) + x, y, z = what.x, what.y, what.z + world.items.all.find { |i| i.pos.x == x and i.pos.y == y and i.pos.z == z } + else + raise "what what?" + end + end + + # return a map block + # can use find_map_block(cursor) or anything that respond to x/y/z + def find_map_block(x=cursor, 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) + if x >= 0 and x < world.map.x_count and y >= 0 and y < world.map.y_count and z >= 0 and z < world.map.z_count + world.map.block_index[x/16][y/16][z] + end + end + def test puts "starting" suspend { puts "cursor pos: #{cursor.x} #{cursor.y} #{cursor.z}" - puts "unit[0] id: #{world.units.all[0].id}" + if u = find_unit + puts "selected unit id: #{u.id}" + end - if cursor.x >= 0 - world.map.block_index[cursor.x/16][cursor.y/16][cursor.z].designation[cursor.x%16][cursor.y%16].dig = TileDigDesignation::Default + if b = find_map_block + b.designation[cursor.x%16][cursor.y%16].dig = TileDigDesignation::Default + b.flags.designated = true puts "dug cursor tile" end }