From 60bb486abac5d79f0fc9053739b6ec52dfa8519f Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Sat, 12 May 2012 20:12:09 +0400
Subject: [PATCH] Add api for enabling liquid and temperature updates for
blocks.
Now updates also have to be enabled for the z level to work.
---
LUA_API.rst | 12 +++++
Lua API.html | 9 ++++
library/LuaApi.cpp | 3 ++
library/include/modules/Job.h | 4 ++
library/include/modules/MapCache.h | 25 ++++-----
library/include/modules/Maps.h | 3 ++
library/modules/Buildings.cpp | 9 ++--
library/modules/Job.cpp | 12 +++++
library/modules/Maps.cpp | 33 +++++++++---
plugins/liquids.cpp | 83 +++++++++++++++++-------------
10 files changed, 127 insertions(+), 66 deletions(-)
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;
}