Merge remote-tracking branch 'angavrilov/master'

develop
Kelly Martin 2012-05-18 07:38:23 -05:00
commit 6adb78ee0c
10 changed files with 172 additions and 36 deletions

@ -693,7 +693,7 @@ Units module
* ``dfhack.units.getPosition(unit)`` * ``dfhack.units.getPosition(unit)``
Returns true *x,y,z* of the unit; may be not equal to unit.pos if caged. Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged.
* ``dfhack.units.getContainer(unit)`` * ``dfhack.units.getContainer(unit)``
@ -752,7 +752,7 @@ Items module
* ``dfhack.items.getPosition(item)`` * ``dfhack.items.getPosition(item)``
Returns true *x,y,z* of the item; may be not equal to item.pos if in inventory. Returns true *x,y,z* of the item, or *nil* if invalid; may be not equal to item.pos if in inventory.
* ``dfhack.items.getGeneralRef(item, type)`` * ``dfhack.items.getGeneralRef(item, type)``

@ -935,7 +935,7 @@ a lua list containing them.</p>
<h3><a class="toc-backref" href="#id16">Units module</a></h3> <h3><a class="toc-backref" href="#id16">Units module</a></h3>
<ul> <ul>
<li><p class="first"><tt class="docutils literal">dfhack.units.getPosition(unit)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.units.getPosition(unit)</tt></p>
<p>Returns true <em>x,y,z</em> of the unit; may be not equal to unit.pos if caged.</p> <p>Returns true <em>x,y,z</em> of the unit, or <em>nil</em> if invalid; may be not equal to unit.pos if caged.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.units.getContainer(unit)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.units.getContainer(unit)</tt></p>
<p>Returns the container (cage) item or <em>nil</em>.</p> <p>Returns the container (cage) item or <em>nil</em>.</p>
@ -982,7 +982,7 @@ or raws. The <tt class="docutils literal">ignore_noble</tt> boolean disables the
<h3><a class="toc-backref" href="#id17">Items module</a></h3> <h3><a class="toc-backref" href="#id17">Items module</a></h3>
<ul> <ul>
<li><p class="first"><tt class="docutils literal">dfhack.items.getPosition(item)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.items.getPosition(item)</tt></p>
<p>Returns true <em>x,y,z</em> of the item; may be not equal to item.pos if in inventory.</p> <p>Returns true <em>x,y,z</em> of the item, or <em>nil</em> if invalid; may be not equal to item.pos if in inventory.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.items.getGeneralRef(item, type)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.items.getGeneralRef(item, type)</tt></p>
<p>Searches for a general_ref with the given type.</p> <p>Searches for a general_ref with the given type.</p>

@ -71,6 +71,7 @@ using namespace DFHack;
using namespace tthread; using namespace tthread;
using namespace df::enums; using namespace df::enums;
using df::global::init; using df::global::init;
using df::global::world;
// FIXME: A lot of code in one file, all doing different things... there's something fishy about it. // FIXME: A lot of code in one file, all doing different things... there's something fishy about it.
@ -1017,7 +1018,7 @@ int Core::Update()
Lua::Core::Reset(out, "DF code execution"); Lua::Core::Reset(out, "DF code execution");
if (first_update) if (first_update)
plug_mgr->OnStateChange(out, SC_CORE_INITIALIZED); onStateChange(out, SC_CORE_INITIALIZED);
// 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;
@ -1043,11 +1044,11 @@ int Core::Update()
// and if the world is going away, we report the map change first // and if the world is going away, we report the map change first
if(had_map) if(had_map)
plug_mgr->OnStateChange(out, SC_MAP_UNLOADED); onStateChange(out, SC_MAP_UNLOADED);
// and if the world is appearing, we report map change after that // and if the world is appearing, we report map change after that
plug_mgr->OnStateChange(out, new_wdata ? SC_WORLD_LOADED : SC_WORLD_UNLOADED); onStateChange(out, new_wdata ? SC_WORLD_LOADED : SC_WORLD_UNLOADED);
if(isMapLoaded()) if(isMapLoaded())
plug_mgr->OnStateChange(out, SC_MAP_LOADED); onStateChange(out, SC_MAP_LOADED);
} }
// otherwise just check for map change... // otherwise just check for map change...
else if (new_mapdata != last_local_map_ptr) else if (new_mapdata != last_local_map_ptr)
@ -1058,7 +1059,7 @@ int Core::Update()
if (isMapLoaded() != had_map) if (isMapLoaded() != had_map)
{ {
getWorld()->ClearPersistentCache(); getWorld()->ClearPersistentCache();
plug_mgr->OnStateChange(out, new_mapdata ? SC_MAP_LOADED : SC_MAP_UNLOADED); onStateChange(out, new_mapdata ? SC_MAP_LOADED : SC_MAP_UNLOADED);
} }
} }
@ -1071,15 +1072,12 @@ int Core::Update()
if (screen != top_viewscreen) if (screen != top_viewscreen)
{ {
top_viewscreen = screen; top_viewscreen = screen;
plug_mgr->OnStateChange(out, SC_VIEWSCREEN_CHANGED); onStateChange(out, SC_VIEWSCREEN_CHANGED);
} }
} }
// notify all the plugins that a game tick is finished // Execute per-frame handlers
plug_mgr->OnUpdate(out); onUpdate(out);
// process timers in lua
Lua::Core::onUpdate(out);
// Release the fake suspend lock // Release the fake suspend lock
{ {
@ -1116,6 +1114,34 @@ int Core::Update()
return 0; return 0;
}; };
extern bool buildings_do_onupdate;
void buildings_onStateChange(color_ostream &out, state_change_event event);
void buildings_onUpdate(color_ostream &out);
static int buildings_timer = 0;
void Core::onUpdate(color_ostream &out)
{
// convert building reagents
if (buildings_do_onupdate && (++buildings_timer & 1))
buildings_onUpdate(out);
// notify all the plugins that a game tick is finished
plug_mgr->OnUpdate(out);
// process timers in lua
Lua::Core::onUpdate(out);
}
void Core::onStateChange(color_ostream &out, state_change_event event)
{
buildings_onStateChange(out, event);
plug_mgr->OnStateChange(out, event);
Lua::Core::onStateChange(out, event);
}
// FIXME: needs to terminate the IO threads and properly dismantle all the machinery involved. // FIXME: needs to terminate the IO threads and properly dismantle all the machinery involved.
int Core::Shutdown ( void ) int Core::Shutdown ( void )
{ {

@ -609,8 +609,6 @@ void PluginManager::OnStateChange(color_ostream &out, state_change_event event)
{ {
all_plugins[i]->on_state_change(out, event); all_plugins[i]->on_state_change(out, event);
} }
Lua::Core::onStateChange(out, event);
} }
// FIXME: doesn't check name collisions! // FIXME: doesn't check name collisions!

@ -68,6 +68,17 @@ namespace DFHack
class df_window; class df_window;
} }
enum state_change_event
{
SC_WORLD_LOADED = 0,
SC_WORLD_UNLOADED = 1,
SC_MAP_LOADED = 2,
SC_MAP_UNLOADED = 3,
SC_VIEWSCREEN_CHANGED = 4,
SC_CORE_INITIALIZED = 5,
SC_BEGIN_UNLOAD = 6
};
// Core is a singleton. Why? Because it is closely tied to SDL calls. It tracks the global state of DF. // Core is a singleton. Why? Because it is closely tied to SDL calls. It tracks the global state of DF.
// There should never be more than one instance // There should never be more than one instance
// Better than tracking some weird variables all over the place. // Better than tracking some weird variables all over the place.
@ -162,6 +173,9 @@ namespace DFHack
int SDL_Event(SDL::Event* event); int SDL_Event(SDL::Event* event);
bool ncurses_wgetch(int in, int & out); bool ncurses_wgetch(int in, int & out);
void onUpdate(color_ostream &out);
void onStateChange(color_ostream &out, state_change_event event);
Core(Core const&); // Don't Implement Core(Core const&); // Don't Implement
void operator=(Core const&); // Don't implement void operator=(Core const&); // Don't implement

@ -65,16 +65,6 @@ namespace DFHack
// Close a plugin library // Close a plugin library
void ClosePlugin (DFLibrary * plugin); void ClosePlugin (DFLibrary * plugin);
enum state_change_event
{
SC_WORLD_LOADED = 0,
SC_WORLD_UNLOADED = 1,
SC_MAP_LOADED = 2,
SC_MAP_UNLOADED = 3,
SC_VIEWSCREEN_CHANGED = 4,
SC_CORE_INITIALIZED = 5,
SC_BEGIN_UNLOAD = 6
};
struct DFHACK_EXPORT CommandReg { struct DFHACK_EXPORT CommandReg {
const char *name; const char *name;
int (*command)(lua_State*); int (*command)(lua_State*);

@ -178,7 +178,20 @@ local building_inputs = {
}, },
[df.building_type.Slab] = { { item_type=df.item_type.SLAB } }, [df.building_type.Slab] = { { item_type=df.item_type.SLAB } },
[df.building_type.NestBox] = { { has_tool_use=df.tool_uses.NEST_BOX, item_type=df.item_type.TOOL } }, [df.building_type.NestBox] = { { has_tool_use=df.tool_uses.NEST_BOX, item_type=df.item_type.TOOL } },
[df.building_type.Hive] = { { has_tool_use=df.tool_uses.HIVE, item_type=df.item_type.TOOL } } [df.building_type.Hive] = { { has_tool_use=df.tool_uses.HIVE, item_type=df.item_type.TOOL } },
[df.building_type.Rollers] = {
{
name='mechanism',
item_type=df.item_type.TRAPPARTS,
quantity=-1,
vector_id=df.job_item_vector_id.TRAPPARTS
},
{
name='chain',
item_type=df.item_type.CHAIN,
vector_id=df.job_item_vector_id.CHAIN
}
}
} }
--[[ Furnace building input material table. ]] --[[ Furnace building input material table. ]]
@ -318,7 +331,8 @@ local trap_inputs = {
item_type=df.item_type.TRAPPARTS, item_type=df.item_type.TRAPPARTS,
vector_id=df.job_item_vector_id.TRAPPARTS vector_id=df.job_item_vector_id.TRAPPARTS
} }
} },
[df.trap_type.TrackStop] = { { flags2={ building_material=true, non_economic=true } } }
} }
--[[ Functions for lookup in tables. ]] --[[ Functions for lookup in tables. ]]

@ -66,6 +66,7 @@ using namespace DFHack;
#include "df/building_screw_pumpst.h" #include "df/building_screw_pumpst.h"
#include "df/building_water_wheelst.h" #include "df/building_water_wheelst.h"
#include "df/building_wellst.h" #include "df/building_wellst.h"
#include "df/building_rollersst.h"
using namespace df::enums; using namespace df::enums;
using df::global::ui; using df::global::ui;
@ -86,6 +87,58 @@ static uint8_t *getExtentTile(df::building_extents &extent, df::coord2d tile)
return &extent.extents[dx + dy*extent.width]; return &extent.extents[dx + dy*extent.width];
} }
/*
* A monitor to work around this bug, in its application to buildings:
*
* http://www.bay12games.com/dwarves/mantisbt/view.php?id=1416
*/
bool buildings_do_onupdate = false;
void buildings_onStateChange(color_ostream &out, state_change_event event)
{
switch (event) {
case SC_MAP_LOADED:
buildings_do_onupdate = true;
break;
case SC_MAP_UNLOADED:
buildings_do_onupdate = false;
break;
default:
break;
}
}
void buildings_onUpdate(color_ostream &out)
{
buildings_do_onupdate = false;
df::job_list_link *link = world->job_list.next;
for (; link; link = link->next) {
df::job *job = link->item;
if (job->job_type != job_type::ConstructBuilding)
continue;
if (job->job_items.empty())
continue;
buildings_do_onupdate = true;
for (size_t i = 0; i < job->items.size(); i++)
{
df::job_item_ref *iref = job->items[i];
if (iref->role != df::job_item_ref::Reagent)
continue;
df::job_item *item = vector_get(job->job_items, iref->job_item_idx);
if (!item)
continue;
// Convert Reagent to Hauled, while decrementing quantity
item->quantity = std::max(0, item->quantity-1);
iref->role = df::job_item_ref::Hauled;
iref->job_item_idx = -1;
}
}
}
uint32_t Buildings::getNumBuildings() uint32_t Buildings::getNumBuildings()
{ {
return world->buildings.all.size(); return world->buildings.all.size();
@ -289,6 +342,10 @@ bool Buildings::getCorrectSize(df::coord2d &size, df::coord2d &center,
makeOneDim(size, center, direction); makeOneDim(size, center, direction);
return true; return true;
case Rollers:
makeOneDim(size, center, (direction&1) == 0);
return true;
case WaterWheel: case WaterWheel:
size = df::coord2d(3,3); size = df::coord2d(3,3);
makeOneDim(size, center, direction); makeOneDim(size, center, direction);
@ -592,6 +649,12 @@ bool Buildings::setSize(df::building *bld, df::coord2d size, int direction)
obj->direction = (df::screw_pump_direction)direction; obj->direction = (df::screw_pump_direction)direction;
break; break;
} }
case Rollers:
{
auto obj = (df::building_rollersst*)bld;
obj->direction = (df::screw_pump_direction)direction;
break;
}
case Bridge: case Bridge:
{ {
auto obj = (df::building_bridgest*)bld; auto obj = (df::building_bridgest*)bld;
@ -881,7 +944,11 @@ bool Buildings::constructWithFilters(df::building *bld, std::vector<df::job_item
if (items[i]->quantity < 0) if (items[i]->quantity < 0)
items[i]->quantity = computeMaterialAmount(bld); items[i]->quantity = computeMaterialAmount(bld);
job->job_items.push_back(items[i]); /* The game picks up explicitly listed items in reverse
* order, but processes filters straight. This reverses
* the order of filters so as to produce the same final
* contained_items ordering as the normal ui way. */
vector_insert_at(job->job_items, 0, items[i]);
if (items[i]->item_type == item_type::BOULDER) if (items[i]->item_type == item_type::BOULDER)
rough = true; rough = true;
@ -891,6 +958,8 @@ bool Buildings::constructWithFilters(df::building *bld, std::vector<df::job_item
bld->mat_index = items[i]->mat_index; bld->mat_index = items[i]->mat_index;
} }
buildings_do_onupdate = true;
createDesign(bld, rough); createDesign(bld, rough);
return true; return true;
} }
@ -954,3 +1023,4 @@ bool Buildings::deconstruct(df::building *bld)
return true; return true;
} }

@ -69,6 +69,7 @@ using namespace std;
#include "df/general_ref_unit_itemownerst.h" #include "df/general_ref_unit_itemownerst.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_contained_in_itemst.h"
#include "df/vermin.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
@ -512,9 +513,12 @@ df::coord Items::getPosition(df::item *item)
{ {
CHECK_NULL_POINTER(item); CHECK_NULL_POINTER(item);
if (item->flags.bits.in_inventory || /* Function reverse-engineered from DF code. */
item->flags.bits.in_chest ||
item->flags.bits.in_building) if (item->flags.bits.removed)
return df::coord();
if (item->flags.bits.in_inventory)
{ {
for (size_t i = 0; i < item->itemrefs.size(); i++) for (size_t i = 0; i < item->itemrefs.size(); i++)
{ {
@ -532,15 +536,31 @@ df::coord Items::getPosition(df::item *item)
return Units::getPosition(unit); return Units::getPosition(unit);
break; break;
case general_ref_type::BUILDING_HOLDER: /*case general_ref_type::BUILDING_HOLDER:
if (auto bld = ref->getBuilding()) if (auto bld = ref->getBuilding())
return df::coord(bld->centerx, bld->centery, bld->z); return df::coord(bld->centerx, bld->centery, bld->z);
break;*/
default:
break; break;
}
}
for (size_t i = 0; i < item->specific_refs.size(); i++)
{
df::specific_ref *ref = item->specific_refs[i];
switch (ref->type)
{
case specific_ref_type::VERMIN_ESCAPED_PET:
return ref->vermin->pos;
default: default:
break; break;
} }
} }
return df::coord();
} }
return item->pos; return item->pos;
@ -625,6 +645,10 @@ bool DFHack::Items::moveToContainer(MapExtras::MapCache &mc, df::item *item, df:
CHECK_NULL_POINTER(item); CHECK_NULL_POINTER(item);
CHECK_NULL_POINTER(container); CHECK_NULL_POINTER(container);
auto cpos = getPosition(container);
if (!cpos.isValid())
return false;
if (!detachItem(mc, item)) if (!detachItem(mc, item))
return false; return false;
@ -635,7 +659,7 @@ bool DFHack::Items::moveToContainer(MapExtras::MapCache &mc, df::item *item, df:
{ {
delete ref1; delete ref2; delete ref1; delete ref2;
Core::printerr("Could not allocate container refs.\n"); Core::printerr("Could not allocate container refs.\n");
putOnGround(mc, item, getPosition(container)); putOnGround(mc, item, cpos);
return false; return false;
} }

@ -1 +1 @@
Subproject commit b0d8e71dc9f6e697409bd999801097acdc57fcd8 Subproject commit ab102b93fca9b1ae8b5fbfc3ae5a9ee06ee60811