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.
* ``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)``
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.
* ``dfhack.maps.enableBlockUpdates(block[,flow,temperature])``
Enables updates for liquid flow or temperature, unless already active.
* ``dfhack.maps.getGlobalInitFeature(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>
<p>Returns the unit performing the job.</p>
</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>
<p>Compares important fields in the job and nested item structures.</p>
</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>
<p>Returns the biome info struct for the given global map region.</p>
</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>
<p>Returns the global feature object with the given index.</p>
</li>

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

@ -57,6 +57,10 @@ namespace DFHack
DFHACK_EXPORT df::building *getHolder(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);
// lists jobs with ids >= *id_var, and sets *id_var = *job_next_id;

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

@ -709,8 +709,7 @@ static void linkBuilding(df::building *bld)
linkRooms(bld);
if (process_jobs)
*process_jobs = true;
Job::checkBuildingsNow();
}
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::world;
using df::global::process_jobs;
using df::global::process_dig;
using df::global::ui_look_list;
CHECK_NULL_POINTER(bld);
@ -952,8 +949,8 @@ bool Buildings::deconstruct(df::building *bld)
}
}
if (process_dig) *process_dig = true;
if (process_jobs) *process_jobs = true;
Job::checkBuildingsNow();
Job::checkDesignationsNow();
return true;
}

@ -256,6 +256,18 @@ df::unit *DFHack::Job::getWorker(df::job *job)
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)
{
using df::global::world;

@ -54,6 +54,7 @@ using namespace std;
#include "df/world_region_details.h"
#include "df/builtin_mats.h"
#include "df/block_square_event_grassst.h"
#include "df/z_level_flags.h"
using namespace DFHack;
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];
}
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)
{
auto data = world->world_data;
@ -426,7 +451,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
dirty_designations = false;
dirty_tiles = false;
dirty_temperatures = false;
dirty_blockflags = false;
dirty_occupancies = false;
valid = false;
bcoord = _bcoord;
@ -440,7 +464,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
{
COPY(designation, block->designation);
COPY(occupancy, block->occupancy);
blockflags = block->flags;
COPY(temp1, block->temperature_1);
COPY(temp2, block->temperature_2);
@ -449,7 +472,6 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
}
else
{
blockflags.whole = 0;
memset(designation,0,sizeof(designation));
memset(occupancy,0,sizeof(occupancy));
memset(temp1,0,sizeof(temp1));
@ -634,11 +656,6 @@ bool MapExtras::Block::Write ()
{
if(!valid) return false;
if(dirty_blockflags)
{
block->flags = blockflags;
dirty_blockflags = false;
}
if(dirty_designations)
{
COPY(block->designation, designation);

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