Add api for enabling liquid and temperature updates for blocks.

Now updates also have to be enabled for the z level to work.
develop
Alexander Gavrilov 2012-05-12 20:12:09 +04:00
parent af3e389093
commit 60bb486aba
10 changed files with 127 additions and 66 deletions

@ -666,6 +666,14 @@ Job module
Returns the unit performing the job. Returns the unit performing the job.
* ``dfhack.job.checkBuildingsNow()``
Instructs the game to check buildings for jobs next frame and assign workers.
* ``dfhack.job.checkDesignationsNow()``
Instructs the game to check designations for jobs next frame and assign workers.
* ``dfhack.job.is_equal(job1,job2)`` * ``dfhack.job.is_equal(job1,job2)``
Compares important fields in the job and nested item structures. Compares important fields in the job and nested item structures.
@ -803,6 +811,10 @@ Maps module
Returns the biome info struct for the given global map region. Returns the biome info struct for the given global map region.
* ``dfhack.maps.enableBlockUpdates(block[,flow,temperature])``
Enables updates for liquid flow or temperature, unless already active.
* ``dfhack.maps.getGlobalInitFeature(index)`` * ``dfhack.maps.getGlobalInitFeature(index)``
Returns the global feature object with the given index. Returns the global feature object with the given index.

@ -912,6 +912,12 @@ The is_bright boolean actually seems to invert the brightness.</p>
<li><p class="first"><tt class="docutils literal">dfhack.job.getWorker(job)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.job.getWorker(job)</tt></p>
<p>Returns the unit performing the job.</p> <p>Returns the unit performing the job.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.job.checkBuildingsNow()</tt></p>
<p>Instructs the game to check buildings for jobs next frame and assign workers.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.checkDesignationsNow()</tt></p>
<p>Instructs the game to check designations for jobs next frame and assign workers.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.is_equal(job1,job2)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.job.is_equal(job1,job2)</tt></p>
<p>Compares important fields in the job and nested item structures.</p> <p>Compares important fields in the job and nested item structures.</p>
</li> </li>
@ -1023,6 +1029,9 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt></p>
<p>Returns the biome info struct for the given global map region.</p> <p>Returns the biome info struct for the given global map region.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.maps.enableBlockUpdates(block[,flow,temperature])</span></tt></p>
<p>Enables updates for liquid flow or temperature, unless already active.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getGlobalInitFeature(index)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getGlobalInitFeature(index)</tt></p>
<p>Returns the global feature object with the given index.</p> <p>Returns the global feature object with the given index.</p>
</li> </li>

@ -637,6 +637,8 @@ static const LuaWrapper::FunctionReg dfhack_job_module[] = {
WRAPM(Job,printJobDetails), WRAPM(Job,printJobDetails),
WRAPM(Job,getHolder), WRAPM(Job,getHolder),
WRAPM(Job,getWorker), WRAPM(Job,getWorker),
WRAPM(Job,checkBuildingsNow),
WRAPM(Job,checkDesignationsNow),
WRAPN(is_equal, jobEqual), WRAPN(is_equal, jobEqual),
WRAPN(is_item_equal, jobItemEqual), WRAPN(is_item_equal, jobItemEqual),
{ NULL, NULL } { NULL, NULL }
@ -753,6 +755,7 @@ static const luaL_Reg dfhack_items_funcs[] = {
static const LuaWrapper::FunctionReg dfhack_maps_module[] = { static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
WRAPM(Maps, getRegionBiome), WRAPM(Maps, getRegionBiome),
WRAPM(Maps, enableBlockUpdates),
WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getGlobalInitFeature),
WRAPM(Maps, getLocalInitFeature), WRAPM(Maps, getLocalInitFeature),
WRAPM(Maps, canWalkBetween), WRAPM(Maps, canWalkBetween),

@ -57,6 +57,10 @@ namespace DFHack
DFHACK_EXPORT df::building *getHolder(df::job *job); DFHACK_EXPORT df::building *getHolder(df::job *job);
DFHACK_EXPORT df::unit *getWorker(df::job *job); DFHACK_EXPORT df::unit *getWorker(df::job *job);
// Instruct the game to check and assign workers
DFHACK_EXPORT void checkBuildingsNow();
DFHACK_EXPORT void checkDesignationsNow();
DFHACK_EXPORT bool linkIntoWorld(df::job *job, bool new_id = true); DFHACK_EXPORT bool linkIntoWorld(df::job *job, bool new_id = true);
// lists jobs with ids >= *id_var, and sets *id_var = *job_next_id; // lists jobs with ids >= *id_var, and sets *id_var = *job_next_id;

@ -93,6 +93,12 @@ public:
Block(MapCache *parent, DFCoord _bcoord); Block(MapCache *parent, DFCoord _bcoord);
~Block(); ~Block();
DFCoord getCoord() { return bcoord; }
void enableBlockUpdates(bool flow = false, bool temp = false) {
Maps::enableBlockUpdates(block, flow, temp);
}
/* /*
* All coordinates are taken mod 16. * All coordinates are taken mod 16.
*/ */
@ -208,11 +214,8 @@ public:
dirty_designations = true; dirty_designations = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y); //printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
index_tile<df::tile_designation&>(designation,p) = des; index_tile<df::tile_designation&>(designation,p) = des;
if(des.bits.dig) if(des.bits.dig && block)
{ block->flags.bits.designated = true;
dirty_blockflags = true;
blockflags.bits.designated = true;
}
return true; return true;
} }
@ -236,15 +239,7 @@ public:
t_blockflags BlockFlags() t_blockflags BlockFlags()
{ {
return blockflags; return block ? block->flags : t_blockflags();
}
bool setBlockFlags(t_blockflags des)
{
if(!valid) return false;
dirty_blockflags = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
blockflags = des;
return true;
} }
bool Write(); bool Write();
@ -273,7 +268,6 @@ private:
bool dirty_designations:1; bool dirty_designations:1;
bool dirty_tiles:1; bool dirty_tiles:1;
bool dirty_temperatures:1; bool dirty_temperatures:1;
bool dirty_blockflags:1;
bool dirty_occupancies:1; bool dirty_occupancies:1;
DFCoord bcoord; DFCoord bcoord;
@ -328,7 +322,6 @@ private:
designations40d designation; designations40d designation;
occupancies40d occupancy; occupancies40d occupancy;
t_blockflags blockflags;
t_temperatures temp1; t_temperatures temp1;
t_temperatures temp2; t_temperatures temp2;

@ -257,6 +257,9 @@ inline df::tile_occupancy *getTileOccupancy(df::coord pos) {
DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos); DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos);
// Enables per-frame updates for liquid flow and/or temperature.
DFHACK_EXPORT void enableBlockUpdates(df::map_block *blk, bool flow = false, bool temperature = false);
/// sorts the block event vector into multiple vectors by type /// sorts the block event vector into multiple vectors by type
/// mineral veins, what's under ice, blood smears and mud /// mineral veins, what's under ice, blood smears and mud
extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block, extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block,

@ -709,8 +709,7 @@ static void linkBuilding(df::building *bld)
linkRooms(bld); linkRooms(bld);
if (process_jobs) Job::checkBuildingsNow();
*process_jobs = true;
} }
static void createDesign(df::building *bld, bool rough) static void createDesign(df::building *bld, bool rough)
@ -900,8 +899,6 @@ bool Buildings::deconstruct(df::building *bld)
{ {
using df::global::ui; using df::global::ui;
using df::global::world; using df::global::world;
using df::global::process_jobs;
using df::global::process_dig;
using df::global::ui_look_list; using df::global::ui_look_list;
CHECK_NULL_POINTER(bld); CHECK_NULL_POINTER(bld);
@ -952,8 +949,8 @@ bool Buildings::deconstruct(df::building *bld)
} }
} }
if (process_dig) *process_dig = true; Job::checkBuildingsNow();
if (process_jobs) *process_jobs = true; Job::checkDesignationsNow();
return true; return true;
} }

@ -256,6 +256,18 @@ df::unit *DFHack::Job::getWorker(df::job *job)
return NULL; return NULL;
} }
void DFHack::Job::checkBuildingsNow()
{
if (df::global::process_jobs)
*df::global::process_jobs = true;
}
void DFHack::Job::checkDesignationsNow()
{
if (df::global::process_dig)
*df::global::process_dig = true;
}
bool DFHack::Job::linkIntoWorld(df::job *job, bool new_id) bool DFHack::Job::linkIntoWorld(df::job *job, bool new_id)
{ {
using df::global::world; using df::global::world;

@ -54,6 +54,7 @@ using namespace std;
#include "df/world_region_details.h" #include "df/world_region_details.h"
#include "df/builtin_mats.h" #include "df/builtin_mats.h"
#include "df/block_square_event_grassst.h" #include "df/block_square_event_grassst.h"
#include "df/z_level_flags.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
@ -176,6 +177,30 @@ df::world_data::T_region_map *Maps::getRegionBiome(df::coord2d rgn_pos)
return &data->region_map[rgn_pos.x][rgn_pos.y]; return &data->region_map[rgn_pos.x][rgn_pos.y];
} }
void Maps::enableBlockUpdates(df::map_block *blk, bool flow, bool temperature)
{
if (!blk || !(flow || temperature)) return;
if (temperature)
blk->flags.bits.update_temperature = true;
if (flow)
{
blk->flags.bits.update_liquid = true;
blk->flags.bits.update_liquid_twice = true;
}
auto z_flags = world->map.z_level_flags;
int z_level = blk->map_pos.z;
if (z_flags && z_level >= 0 && z_level < world->map.z_count_block)
{
z_flags += z_level;
z_flags->bits.update = true;
z_flags->bits.update_twice = true;
}
}
df::feature_init *Maps::getGlobalInitFeature(int32_t index) df::feature_init *Maps::getGlobalInitFeature(int32_t index)
{ {
auto data = world->world_data; auto data = world->world_data;
@ -426,7 +451,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
dirty_designations = false; dirty_designations = false;
dirty_tiles = false; dirty_tiles = false;
dirty_temperatures = false; dirty_temperatures = false;
dirty_blockflags = false;
dirty_occupancies = false; dirty_occupancies = false;
valid = false; valid = false;
bcoord = _bcoord; bcoord = _bcoord;
@ -440,7 +464,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
{ {
COPY(designation, block->designation); COPY(designation, block->designation);
COPY(occupancy, block->occupancy); COPY(occupancy, block->occupancy);
blockflags = block->flags;
COPY(temp1, block->temperature_1); COPY(temp1, block->temperature_1);
COPY(temp2, block->temperature_2); COPY(temp2, block->temperature_2);
@ -449,7 +472,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
} }
else else
{ {
blockflags.whole = 0;
memset(designation,0,sizeof(designation)); memset(designation,0,sizeof(designation));
memset(occupancy,0,sizeof(occupancy)); memset(occupancy,0,sizeof(occupancy));
memset(temp1,0,sizeof(temp1)); memset(temp1,0,sizeof(temp1));
@ -634,11 +656,6 @@ bool MapExtras::Block::Write ()
{ {
if(!valid) return false; if(!valid) return false;
if(dirty_blockflags)
{
block->flags = blockflags;
dirty_blockflags = false;
}
if(dirty_designations) if(dirty_designations)
{ {
COPY(block->designation, designation); COPY(block->designation, designation);

@ -418,10 +418,7 @@ command_result df_liquids_execute(color_ostream &out)
mcache.setDesignationAt(*iter,a); mcache.setDesignationAt(*iter,a);
Block * b = mcache.BlockAt((*iter)/16); Block * b = mcache.BlockAt((*iter)/16);
DFHack::t_blockflags bf = b->BlockFlags(); b->enableBlockUpdates(true);
bf.bits.update_liquid = true;
bf.bits.update_liquid_twice = true;
b->setBlockFlags(bf);
iter++; iter++;
} }
@ -448,7 +445,8 @@ command_result df_liquids_execute(color_ostream &out)
DFHack::DFCoord current = *iter; // current tile coord DFHack::DFCoord current = *iter; // current tile coord
DFHack::DFCoord curblock = current /16; // current block coord DFHack::DFCoord curblock = current /16; // current block coord
// check if the block is actually there // check if the block is actually there
if(!mcache.BlockAt(curblock)) auto block = mcache.BlockAt(curblock);
if(!block)
{ {
iter ++; iter ++;
continue; continue;
@ -463,64 +461,77 @@ command_result df_liquids_execute(color_ostream &out)
} }
if(mode != "flowbits") if(mode != "flowbits")
{ {
unsigned old_amount = des.bits.flow_size;
unsigned new_amount = old_amount;
df::tile_liquid old_liquid = des.bits.liquid_type;
df::tile_liquid new_liquid = old_liquid;
// Compute new liquid type and amount
if(setmode == "s.") if(setmode == "s.")
{ {
des.bits.flow_size = amount; new_amount = amount;
} }
else if(setmode == "s+") else if(setmode == "s+")
{ {
if(des.bits.flow_size < amount) if(old_amount < amount)
des.bits.flow_size = amount; new_amount = amount;
} }
else if(setmode == "s-") else if(setmode == "s-")
{ {
if (des.bits.flow_size > amount) if (old_amount > amount)
des.bits.flow_size = amount; new_amount = amount;
} }
if(amount != 0 && mode == "magma") if (mode == "magma")
new_liquid = tile_liquid::Magma;
else if (mode == "water")
new_liquid = tile_liquid::Water;
// Store new amount and type
des.bits.flow_size = new_amount;
des.bits.liquid_type = new_liquid;
// Compute temperature
if (!old_amount)
old_liquid = tile_liquid::Water;
if (!new_amount)
new_liquid = tile_liquid::Water;
if (old_liquid != new_liquid)
{
if (new_liquid == tile_liquid::Water)
{ {
des.bits.liquid_type = tile_liquid::Magma;
mcache.setTemp1At(current,12000);
mcache.setTemp2At(current,12000);
}
else if(amount != 0 && mode == "water")
{
des.bits.liquid_type = tile_liquid::Water;
mcache.setTemp1At(current,10015); mcache.setTemp1At(current,10015);
mcache.setTemp2At(current,10015); mcache.setTemp2At(current,10015);
} }
else if(amount == 0 && (mode == "water" || mode == "magma")) else
{ {
// reset temperature to sane default mcache.setTemp1At(current,12000);
mcache.setTemp1At(current,10015); mcache.setTemp2At(current,12000);
mcache.setTemp2At(current,10015); }
} }
// mark the tile passable or impassable like the game does // mark the tile passable or impassable like the game does
des.bits.flow_forbid = des.bits.flow_size && des.bits.flow_forbid = (new_liquid == tile_liquid::Magma || new_amount > 3);
(des.bits.liquid_type == tile_liquid::Magma || des.bits.flow_size > 3);
mcache.setDesignationAt(current,des); mcache.setDesignationAt(current,des);
// request flow engine updates
block->enableBlockUpdates(new_amount != old_amount, new_liquid != old_liquid);
} }
seen_blocks.insert(mcache.BlockAt(current / 16)); seen_blocks.insert(block);
iter++; iter++;
} }
set <Block *>::iterator biter = seen_blocks.begin(); set <Block *>::iterator biter = seen_blocks.begin();
while (biter != seen_blocks.end()) while (biter != seen_blocks.end())
{ {
DFHack::t_blockflags bflags = (*biter)->BlockFlags();
if(flowmode == "f+") if(flowmode == "f+")
{ {
bflags.bits.update_liquid = true; (*biter)->enableBlockUpdates(true);
bflags.bits.update_liquid_twice = true;
(*biter)->setBlockFlags(bflags);
} }
else if(flowmode == "f-") else if(flowmode == "f-")
{ {
bflags.bits.update_liquid = false; if (auto block = (*biter)->getRaw())
bflags.bits.update_liquid_twice = false; {
(*biter)->setBlockFlags(bflags); block->flags.bits.update_liquid = false;
block->flags.bits.update_liquid_twice = false;
}
} }
else else
{ {
auto bflags = (*biter)->BlockFlags();
out << "flow bit 1 = " << bflags.bits.update_liquid << endl; out << "flow bit 1 = " << bflags.bits.update_liquid << endl;
out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl; out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl;
} }