diff --git a/LUA_API.rst b/LUA_API.rst index e20b946d8..093dd943c 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -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. diff --git a/Lua API.html b/Lua API.html index 7aa8e651a..b6242712a 100644 --- a/Lua API.html +++ b/Lua API.html @@ -912,6 +912,12 @@ The is_bright boolean actually seems to invert the brightness.

  • dfhack.job.getWorker(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)

    Compares important fields in the job and nested item structures.

  • @@ -1023,6 +1029,9 @@ Returns false in case of error.

  • dfhack.maps.getRegionBiome(region_coord2d)

    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.

  • diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index d554754e4..1baa4045d 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -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), diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index a4e173a8d..9ce72c326 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -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; diff --git a/library/include/modules/MapCache.h b/library/include/modules/MapCache.h index 0b4e78b21..109a20a41 100644 --- a/library/include/modules/MapCache.h +++ b/library/include/modules/MapCache.h @@ -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(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; diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index fc18ca7e1..c6dc7c404 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -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, diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 557eb1881..65cf009f3 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -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; } diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 149707c6e..1207c97b3 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -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; diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 69f591a0f..a8b7945d1 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -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); diff --git a/plugins/liquids.cpp b/plugins/liquids.cpp index f644398f5..c4a925964 100644 --- a/plugins/liquids.cpp +++ b/plugins/liquids.cpp @@ -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 ::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; }