Merge remote-tracking branch 'main_repository/develop' into combat_skill_rating_polishing

develop
Mikhail Panov 2023-09-26 17:42:27 +03:00
commit 1e4e6ed03f
18 changed files with 294 additions and 87 deletions

@ -139,6 +139,7 @@ moversti moversti
mrrho mrrho
Murad Beybalaev Erquint
Myk Taylor myk002
Najeeb Al-Shabibi master-spike
napagokc napagokc
Neil Little nmlittle
Nick Rart nickrart comestible

@ -56,8 +56,10 @@ Template for new versions:
## New Features
## Fixes
- `autolabor`: now unconditionally re-enables vanilla work details when the fort or the plugin is unloaded
## Misc Improvements
- `dig`: `digtype` command now has options to choose between designating only visible tiles or hidden tiles, as well as "auto" dig mode. Z-level options adjusted to allow choosing z-levels above, below, or the same as the cursor.
## Documentation

@ -2594,11 +2594,18 @@ invalidates the ``texpos`` value that used to point to that texture.
The ``textures`` module solves this problem by providing a stable handle instead of a
raw ``texpos``. When we need to draw a particular tile, we can look up the current
``texpos`` value via the handle.
Texture module can register textures in two ways: to reserved and dynamic ranges.
Reserved range is a limit buffer in a game texture vector, that will never be wiped.
It is good for static assets, which need to be loaded at the very beginning and will be used during the process running.
In other cases, it is better to use dynamic range.
If reserved range buffer limit has been reached, dynamic range will be used by default.
* ``loadTileset(file, tile_px_w, tile_px_h)``
* ``loadTileset(file, tile_px_w, tile_px_h[, reserved])``
Loads a tileset from the image ``file`` with give tile dimensions in pixels. The
image will be sliced in row major order. Returns an array of ``TexposHandle``.
``reserved`` is optional boolean argument, which indicates texpos range.
``true`` - reserved, ``false`` - dynamic (default).
Example usage::
@ -2611,18 +2618,22 @@ raw ``texpos``. When we need to draw a particular tile, we can look up the curre
get the ``texpos`` for your texture. ``texpos`` can change when game textures are
reset, but the handle will be the same.
* ``createTile(pixels, tile_px_w, tile_px_h)``
* ``createTile(pixels, tile_px_w, tile_px_h[, reserved])``
Create and register a new texture with the given tile dimensions and an array of
``pixels`` in row major order. Each pixel is an integer representing color in packed
RBGA format (for example, #0022FF11). Returns a ``TexposHandle``.
``reserved`` is optional boolean argument, which indicates texpos range.
``true`` - reserved, ``false`` - dynamic (default).
* ``createTileset(pixels, texture_px_w, texture_px_h, tile_px_w, tile_px_h)``
* ``createTileset(pixels, texture_px_w, texture_px_h, tile_px_w, tile_px_h[, reserved])``
Create and register a new texture with the given texture dimensions and an array of
``pixels`` in row major order. Then slice it into tiles with the given tile
dimensions. Each pixel is an integer representing color in packed RBGA format (for
example #0022FF11). Returns an array of ``TexposHandle``.
``reserved`` is optional boolean argument, which indicates texpos range.
``true`` - reserved, ``false`` - dynamic (default).
* ``deleteHandle(handle)``

@ -50,7 +50,7 @@ Usage
Designate circles. The diameter is the number of tiles across the center of
the circle that you want to dig. See the `digcircle`_ section below for
options.
``digtype [<designation>] [-p<number>] [-z]``
``digtype [<designation>] [-p<number>] [--zup|-u] [--zdown|-zu] [--cur-zlevel|-z] [--hidden|-h] [--no-auto|-a]``
Designate all vein tiles of the same type as the selected tile. See the
`digtype`_ section below for options.
``digexp [<pattern>] [<filter>] [-p<number>]``
@ -119,9 +119,11 @@ the last selected parameters.
digtype
-------
For every tile on the map of the same vein type as the selected tile, this
command designates it to have the same designation as the selected tile. If the
selected tile has no designation, they will be dig designated.
For every tile on the map of the same vein type as the selected tile, this command
designates it to have the same designation as the selected tile. If the selected
tile has no designation, they will be dig designated. By default, only designates
visible tiles, and in the case of dig designation, applies automatic mining to them
(designates uncovered neighbouring tiles of the same type to be dug).
If an argument is given, the designation of the selected tile is ignored, and
all appropriate tiles are set to the specified designation.
@ -143,9 +145,18 @@ Designation options:
``clear``
Clear any designations.
You can also pass a ``-z`` option, which restricts designations to the current
z-level and down. This is useful when you don't want to designate tiles on the
same z-levels as your carefully dug fort above.
Other options:
``--zdown``, ``-d``
Only designates tiles on the cursor's z-level and below.
``--zup``, ``-u``
Only designates tiles on the cursor's z-level and above.
``--cur-zlevel``, ``-z``
Only designates tiles on the same z-level as the cursor.
``--hidden``, ``-h``
Allows designation of hidden tiles, and picking a hidden tile as the target type.
``--no-auto``, ``-a``
No automatic mining mode designation - useful if you want to avoid dwarves digging where you don't want them.
digexp
------

@ -1459,12 +1459,9 @@ void Core::fatal (std::string output)
con.print("\n");
}
fprintf(stderr, "%s\n", out.str().c_str());
#ifndef LINUX_BUILD
out << "Check file stderr.log for details\n";
MessageBox(0,out.str().c_str(),"DFHack error!", MB_OK | MB_ICONERROR);
#else
out << "Check file stderr.log for details.\n";
std::cout << "DFHack fatal error: " << out.str() << std::endl;
#endif
DFSDL::DFSDL_ShowSimpleMessageBox(0x10 /* SDL_MESSAGEBOX_ERROR */, "DFHack error!", out.str().c_str(), NULL);
bool is_headless = bool(getenv("DFHACK_HEADLESS"));
if (is_headless)
@ -1506,6 +1503,12 @@ bool Core::InitMainThread() {
std::cerr << "DFHack build: " << Version::git_description() << "\n"
<< "Starting with working directory: " << Filesystem::getcwd() << std::endl;
std::cerr << "Binding to SDL.\n";
if (!DFSDL::init(con)) {
fatal("cannot bind SDL libraries");
return false;
}
// find out what we are...
#ifdef LINUX_BUILD
const char * path = "hack/symbols.xml";
@ -1692,11 +1695,6 @@ bool Core::InitSimulationThread()
return false;
}
std::cerr << "Binding to SDL.\n";
if (!DFSDL::init(con)) {
fatal("cannot bind SDL libraries");
return false;
}
if (DFSteam::init(con)) {
std::cerr << "Found Steam.\n";
DFSteam::launchSteamDFHackIfNecessary(con);

@ -1760,7 +1760,8 @@ static int textures_loadTileset(lua_State *state)
std::string file = luaL_checkstring(state, 1);
auto tile_w = luaL_checkint(state, 2);
auto tile_h = luaL_checkint(state, 3);
auto handles = Textures::loadTileset(file, tile_w, tile_h);
bool reserved = lua_isboolean(state, 4) ? lua_toboolean(state, 4) : false;
auto handles = Textures::loadTileset(file, tile_w, tile_h, reserved);
Lua::PushVector(state, handles);
return 1;
}
@ -1798,7 +1799,8 @@ static int textures_createTile(lua_State *state)
Lua::GetVector(state, pixels);
auto tile_w = luaL_checkint(state, 2);
auto tile_h = luaL_checkint(state, 3);
auto handle = Textures::createTile(pixels, tile_w, tile_h);
bool reserved = lua_isboolean(state, 4) ? lua_toboolean(state, 4) : false;
auto handle = Textures::createTile(pixels, tile_w, tile_h, reserved);
Lua::Push(state, handle);
return 1;
}
@ -1811,7 +1813,8 @@ static int textures_createTileset(lua_State *state)
auto texture_h = luaL_checkint(state, 3);
auto tile_w = luaL_checkint(state, 4);
auto tile_h = luaL_checkint(state, 5);
auto handles = Textures::createTileset(pixels, texture_w, texture_h, tile_w, tile_h);
bool reserved = lua_isboolean(state, 6) ? lua_toboolean(state, 6) : false;
auto handles = Textures::createTileset(pixels, texture_w, texture_h, tile_w, tile_h, reserved);
Lua::PushVector(state, handles);
return 1;
}

@ -6,6 +6,7 @@
struct SDL_Surface;
struct SDL_Rect;
struct SDL_PixelFormat;
struct SDL_Window;
union SDL_Event;
namespace DFHack
@ -50,6 +51,7 @@ DFHACK_EXPORT int DFSDL_PushEvent(SDL_Event *event);
DFHACK_EXPORT void DFSDL_free(void *ptr);
DFHACK_EXPORT SDL_PixelFormat* DFSDL_AllocFormat(uint32_t pixel_format);
DFHACK_EXPORT SDL_Surface* DFSDL_CreateRGBSurfaceWithFormat(uint32_t flags, int width, int height, int depth, uint32_t format);
DFHACK_EXPORT int DFSDL_ShowSimpleMessageBox(uint32_t flags, const char *title, const char *message, SDL_Window *window);
// submitted and returned text is UTF-8
// see wrapper functions below for cp-437 variants

@ -26,7 +26,7 @@ const uint32_t TILE_HEIGHT_PX = 12;
* Load texture and get handle.
* Keep it to obtain valid texpos.
*/
DFHACK_EXPORT TexposHandle loadTexture(SDL_Surface* surface);
DFHACK_EXPORT TexposHandle loadTexture(SDL_Surface* surface, bool reserved = false);
/**
* Load tileset from image file.
@ -34,7 +34,8 @@ DFHACK_EXPORT TexposHandle loadTexture(SDL_Surface* surface);
*/
DFHACK_EXPORT std::vector<TexposHandle> loadTileset(const std::string& file,
int tile_px_w = TILE_WIDTH_PX,
int tile_px_h = TILE_HEIGHT_PX);
int tile_px_h = TILE_HEIGHT_PX,
bool reserved = false);
/**
* Get texpos by handle.
@ -53,7 +54,7 @@ DFHACK_EXPORT void deleteHandle(TexposHandle handle);
* Register this texture and return TexposHandle.
*/
DFHACK_EXPORT TexposHandle createTile(std::vector<uint32_t>& pixels, int tile_px_w = TILE_WIDTH_PX,
int tile_px_h = TILE_HEIGHT_PX);
int tile_px_h = TILE_HEIGHT_PX, bool reserved = false);
/**
* Create new textures as tileset with RGBA32 format and pixels as data in row major order.
@ -62,7 +63,8 @@ DFHACK_EXPORT TexposHandle createTile(std::vector<uint32_t>& pixels, int tile_px
DFHACK_EXPORT std::vector<TexposHandle> createTileset(std::vector<uint32_t>& pixels,
int texture_px_w, int texture_px_h,
int tile_px_w = TILE_WIDTH_PX,
int tile_px_h = TILE_HEIGHT_PX);
int tile_px_h = TILE_HEIGHT_PX,
bool reserved = false);
/**
* Call this on DFHack init just once to setup interposed handlers and

@ -6,18 +6,18 @@ local _ENV = mkmodule('gui.textures')
-- Preloaded DFHack Assets.
-- Use this handles if you need to get dfhack standard textures.
---@type table<string, TexposHandle>
---@type table<string, TexposHandle[]>
local texpos_handles = {
green_pin = dfhack.textures.loadTileset('hack/data/art/green-pin.png', 8, 12),
red_pin = dfhack.textures.loadTileset('hack/data/art/red-pin.png', 8, 12),
icons = dfhack.textures.loadTileset('hack/data/art/icons.png', 8, 12),
on_off = dfhack.textures.loadTileset('hack/data/art/on-off.png', 8, 12),
control_panel = dfhack.textures.loadTileset('hack/data/art/control-panel.png', 8, 12),
border_thin = dfhack.textures.loadTileset('hack/data/art/border-thin.png', 8, 12),
border_medium = dfhack.textures.loadTileset('hack/data/art/border-medium.png', 8, 12),
border_bold = dfhack.textures.loadTileset('hack/data/art/border-bold.png', 8, 12),
border_panel = dfhack.textures.loadTileset('hack/data/art/border-panel.png', 8, 12),
border_window = dfhack.textures.loadTileset('hack/data/art/border-window.png', 8, 12),
green_pin = dfhack.textures.loadTileset('hack/data/art/green-pin.png', 8, 12, true),
red_pin = dfhack.textures.loadTileset('hack/data/art/red-pin.png', 8, 12, true),
icons = dfhack.textures.loadTileset('hack/data/art/icons.png', 8, 12, true),
on_off = dfhack.textures.loadTileset('hack/data/art/on-off.png', 8, 12, true),
control_panel = dfhack.textures.loadTileset('hack/data/art/control-panel.png', 8, 12, true),
border_thin = dfhack.textures.loadTileset('hack/data/art/border-thin.png', 8, 12, true),
border_medium = dfhack.textures.loadTileset('hack/data/art/border-medium.png', 8, 12, true),
border_bold = dfhack.textures.loadTileset('hack/data/art/border-bold.png', 8, 12, true),
border_panel = dfhack.textures.loadTileset('hack/data/art/border-panel.png', 8, 12, true),
border_window = dfhack.textures.loadTileset('hack/data/art/border-window.png', 8, 12, true),
}
-- Get valid texpos for preloaded texture in tileset

@ -43,6 +43,7 @@ char * (*g_SDL_GetClipboardText)();
void (*g_SDL_free)(void *);
SDL_PixelFormat* (*g_SDL_AllocFormat)(uint32_t pixel_format) = nullptr;
SDL_Surface* (*g_SDL_CreateRGBSurfaceWithFormat)(uint32_t flags, int width, int height, int depth, uint32_t format) = nullptr;
int (*g_SDL_ShowSimpleMessageBox)(uint32_t flags, const char *title, const char *message, SDL_Window *window) = nullptr;
bool DFSDL::init(color_ostream &out) {
for (auto &lib_str : SDL_LIBS) {
@ -85,6 +86,7 @@ bool DFSDL::init(color_ostream &out) {
bind(g_sdl_handle, SDL_free);
bind(g_sdl_handle, SDL_AllocFormat);
bind(g_sdl_handle, SDL_CreateRGBSurfaceWithFormat);
bind(g_sdl_handle, SDL_ShowSimpleMessageBox);
#undef bind
DEBUG(dfsdl,out).print("sdl successfully loaded\n");
@ -159,6 +161,11 @@ SDL_Surface* DFSDL::DFSDL_CreateRGBSurfaceWithFormat(uint32_t flags, int width,
return g_SDL_CreateRGBSurfaceWithFormat(flags, width, height, depth, format);
}
int DFSDL::DFSDL_ShowSimpleMessageBox(uint32_t flags, const char *title, const char *message, SDL_Window *window) {
if (!g_SDL_ShowSimpleMessageBox)
return -1;
return g_SDL_ShowSimpleMessageBox(flags, title, message, window);
}
DFHACK_EXPORT std::string DFHack::getClipboardTextCp437() {
if (!g_sdl_handle || g_SDL_HasClipboardText() != SDL_TRUE)

@ -1,3 +1,5 @@
#include <algorithm>
#include <atomic>
#include <mutex>
#include <numeric>
#include <unordered_map>
@ -28,9 +30,35 @@ namespace DFHack {
DBG_DECLARE(core, textures, DebugCategory::LINFO);
}
struct ReservedRange {
void init(int32_t start) {
this->start = start;
this->end = start + ReservedRange::size;
this->current = start;
this->is_installed = true;
}
long get_new_texpos() {
if (this->current == this->end)
return -1;
return this->current++;
}
static const int32_t size = 10000; // size of reserved texpos buffer
int32_t start = -1;
int32_t end = -1;
long current = -1;
bool is_installed = false;
};
static ReservedRange reserved_range{};
static std::unordered_map<TexposHandle, long> g_handle_to_texpos;
static std::unordered_map<TexposHandle, long> g_handle_to_reserved_texpos;
static std::unordered_map<TexposHandle, SDL_Surface*> g_handle_to_surface;
static std::unordered_map<std::string, std::vector<TexposHandle>> g_tileset_to_handles;
static std::vector<TexposHandle> g_delayed_regs;
static std::mutex g_adding_mutex;
static std::atomic<bool> loading_state = false;
static SDL_Surface* dummy_surface = NULL;
// Converts an arbitrary Surface to something like the display format
// (32-bit RGBA), and converts magenta to transparency if convert_magenta is set
@ -71,6 +99,12 @@ static long add_texture(SDL_Surface* surface) {
return texpos;
}
// register surface in texture raws to specific texpos
static void insert_texture(SDL_Surface* surface, long texpos) {
std::lock_guard<std::mutex> lg_add_texture(g_adding_mutex);
enabler->textures.raws[texpos] = surface;
}
// delete surface from texture raws
static void delete_texture(long texpos) {
std::lock_guard<std::mutex> lg_add_texture(g_adding_mutex);
@ -94,7 +128,8 @@ SDL_Surface* create_texture(std::vector<uint32_t>& pixels, int texture_px_w, int
// convert single surface into tiles according w/h
// register tiles in texture raws and return handles
std::vector<TexposHandle> slice_tileset(SDL_Surface* surface, int tile_px_w, int tile_px_h) {
std::vector<TexposHandle> slice_tileset(SDL_Surface* surface, int tile_px_w, int tile_px_h,
bool reserved) {
std::vector<TexposHandle> handles{};
if (!surface)
return handles;
@ -102,6 +137,12 @@ std::vector<TexposHandle> slice_tileset(SDL_Surface* surface, int tile_px_w, int
int dimx = surface->w / tile_px_w;
int dimy = surface->h / tile_px_h;
if (reserved && (dimx * dimy > reserved_range.end - reserved_range.current)) {
WARN(textures).print(
"there is not enough space in reserved range for whole tileset, using dynamic range\n");
reserved = false;
}
for (int y = 0; y < dimy; y++) {
for (int x = 0; x < dimx; x++) {
SDL_Surface* tile = DFSDL_CreateRGBSurface(
@ -109,7 +150,7 @@ std::vector<TexposHandle> slice_tileset(SDL_Surface* surface, int tile_px_w, int
surface->format->Bmask, surface->format->Amask);
SDL_Rect vp{tile_px_w * x, tile_px_h * y, tile_px_w, tile_px_h};
DFSDL_UpperBlit(surface, &vp, tile, NULL);
auto handle = Textures::loadTexture(tile);
auto handle = Textures::loadTexture(tile, reserved);
handles.push_back(handle);
}
}
@ -118,20 +159,46 @@ std::vector<TexposHandle> slice_tileset(SDL_Surface* surface, int tile_px_w, int
return handles;
}
TexposHandle Textures::loadTexture(SDL_Surface* surface) {
TexposHandle Textures::loadTexture(SDL_Surface* surface, bool reserved) {
if (!surface || !enabler)
return 0; // should be some error, i guess
if (loading_state)
reserved = true; // use reserved range during loading for all textures
auto handle = reinterpret_cast<uintptr_t>(surface);
g_handle_to_surface.emplace(handle, surface);
surface->refcount++; // prevent destruct on next FreeSurface by game
auto texpos = add_texture(surface);
g_handle_to_texpos.emplace(handle, texpos);
if (reserved && reserved_range.is_installed) {
auto texpos = reserved_range.get_new_texpos();
if (texpos != -1) {
insert_texture(surface, texpos);
g_handle_to_reserved_texpos.emplace(handle, texpos);
dummy_surface->refcount--;
return handle;
}
if (loading_state) { // if we in loading state and reserved range is full -> error
ERR(textures).printerr("reserved range limit has been reached, use dynamic range\n");
return 0;
}
}
// if we here in loading state = true, then it should be dynamic range -> delay reg
if (loading_state) {
g_delayed_regs.push_back(handle);
} else {
auto texpos = add_texture(surface);
g_handle_to_texpos.emplace(handle, texpos);
}
return handle;
}
std::vector<TexposHandle> Textures::loadTileset(const std::string& file, int tile_px_w,
int tile_px_h) {
int tile_px_h, bool reserved) {
if (g_tileset_to_handles.contains(file))
return g_tileset_to_handles[file];
if (!enabler)
return std::vector<TexposHandle>{};
@ -142,9 +209,10 @@ std::vector<TexposHandle> Textures::loadTileset(const std::string& file, int til
}
surface = canonicalize_format(surface);
auto handles = slice_tileset(surface, tile_px_w, tile_px_h);
auto handles = slice_tileset(surface, tile_px_w, tile_px_h, reserved);
DEBUG(textures).print("loaded %zd textures from '%s'\n", handles.size(), file.c_str());
g_tileset_to_handles[file] = handles;
return handles;
}
@ -153,11 +221,18 @@ long Textures::getTexposByHandle(TexposHandle handle) {
if (!handle || !enabler)
return -1;
if (g_handle_to_reserved_texpos.contains(handle))
return g_handle_to_reserved_texpos[handle];
if (g_handle_to_texpos.contains(handle))
return g_handle_to_texpos[handle];
if (std::find(g_delayed_regs.begin(), g_delayed_regs.end(), handle) != g_delayed_regs.end())
return 0;
if (g_handle_to_surface.contains(handle)) {
g_handle_to_surface[handle]->refcount++; // prevent destruct on next FreeSurface by game
if (loading_state) { // reinit dor dynamic range during loading -> delayed
g_delayed_regs.push_back(handle);
return 0;
}
auto texpos = add_texture(g_handle_to_surface[handle]);
g_handle_to_texpos.emplace(handle, texpos);
return texpos;
@ -166,22 +241,24 @@ long Textures::getTexposByHandle(TexposHandle handle) {
return -1;
}
TexposHandle Textures::createTile(std::vector<uint32_t>& pixels, int tile_px_w, int tile_px_h) {
TexposHandle Textures::createTile(std::vector<uint32_t>& pixels, int tile_px_w, int tile_px_h,
bool reserved) {
if (!enabler)
return 0;
auto texture = create_texture(pixels, tile_px_w, tile_px_h);
auto handle = Textures::loadTexture(texture);
auto handle = Textures::loadTexture(texture, reserved);
return handle;
}
std::vector<TexposHandle> Textures::createTileset(std::vector<uint32_t>& pixels, int texture_px_w,
int texture_px_h, int tile_px_w, int tile_px_h) {
int texture_px_h, int tile_px_w, int tile_px_h,
bool reserved) {
if (!enabler)
return std::vector<TexposHandle>{};
auto texture = create_texture(pixels, texture_px_w, texture_px_h);
auto handles = slice_tileset(texture, tile_px_w, tile_px_h);
auto handles = slice_tileset(texture, tile_px_w, tile_px_h, reserved);
return handles;
}
@ -192,8 +269,13 @@ void Textures::deleteHandle(TexposHandle handle) {
auto texpos = Textures::getTexposByHandle(handle);
if (texpos > 0)
delete_texture(texpos);
if (g_handle_to_reserved_texpos.contains(handle))
g_handle_to_reserved_texpos.erase(handle);
if (g_handle_to_texpos.contains(handle))
g_handle_to_texpos.erase(handle);
if (auto it = std::find(g_delayed_regs.begin(), g_delayed_regs.end(), handle);
it != g_delayed_regs.end())
g_delayed_regs.erase(it);
if (g_handle_to_surface.contains(handle)) {
auto surface = g_handle_to_surface[handle];
while (surface->refcount)
@ -207,20 +289,45 @@ static void reset_texpos() {
g_handle_to_texpos.clear();
}
static void reset_reserved_texpos() {
DEBUG(textures).print("resetting reserved texture mappings\n");
g_handle_to_reserved_texpos.clear();
}
static void reset_tilesets() {
DEBUG(textures).print("resetting tileset to handle mappings\n");
g_tileset_to_handles.clear();
}
static void reset_surface() {
DEBUG(textures).print("deleting cached surfaces\n");
for (auto& entry : g_handle_to_surface) {
DFSDL_FreeSurface(entry.second);
}
g_handle_to_surface.clear();
}
static void register_delayed_handles() {
DEBUG(textures).print("register delayed handles, size %zd\n", g_delayed_regs.size());
for (auto& handle : g_delayed_regs) {
auto texpos = add_texture(g_handle_to_surface[handle]);
g_handle_to_texpos.emplace(handle, texpos);
}
g_delayed_regs.clear();
}
// reset point on New Game
struct tracking_stage_new_region : df::viewscreen_new_regionst {
typedef df::viewscreen_new_regionst interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, logic, ()) {
if (this->m_raw_load_stage != this->raw_load_stage) {
TRACE(textures).print("raw_load_stage %d -> %d\n", this->m_raw_load_stage, this->raw_load_stage);
TRACE(textures).print("raw_load_stage %d -> %d\n", this->m_raw_load_stage,
this->raw_load_stage);
bool tmp_state = loading_state;
loading_state = this->raw_load_stage >= 0 && this->raw_load_stage < 3 ? true : false;
if (tmp_state != loading_state && !loading_state)
register_delayed_handles();
this->m_raw_load_stage = this->raw_load_stage;
if (this->m_raw_load_stage == 1)
reset_texpos();
@ -240,6 +347,10 @@ struct tracking_stage_adopt_region : df::viewscreen_adopt_regionst {
DEFINE_VMETHOD_INTERPOSE(void, logic, ()) {
if (this->m_cur_step != this->cur_step) {
TRACE(textures).print("step %d -> %d\n", this->m_cur_step, this->cur_step);
bool tmp_state = loading_state;
loading_state = this->cur_step >= 0 && this->cur_step < 3 ? true : false;
if (tmp_state != loading_state && !loading_state)
register_delayed_handles();
this->m_cur_step = this->cur_step;
if (this->m_cur_step == 1)
reset_texpos();
@ -259,6 +370,10 @@ struct tracking_stage_load_region : df::viewscreen_loadgamest {
DEFINE_VMETHOD_INTERPOSE(void, logic, ()) {
if (this->m_cur_step != this->cur_step) {
TRACE(textures).print("step %d -> %d\n", this->m_cur_step, this->cur_step);
bool tmp_state = loading_state;
loading_state = this->cur_step >= 0 && this->cur_step < 3 ? true : false;
if (tmp_state != loading_state && !loading_state)
register_delayed_handles();
this->m_cur_step = this->cur_step;
if (this->m_cur_step == 1)
reset_texpos();
@ -278,6 +393,10 @@ struct tracking_stage_new_arena : df::viewscreen_new_arenast {
DEFINE_VMETHOD_INTERPOSE(void, logic, ()) {
if (this->m_cur_step != this->cur_step) {
TRACE(textures).print("step %d -> %d\n", this->m_cur_step, this->cur_step);
bool tmp_state = loading_state;
loading_state = this->cur_step >= 0 && this->cur_step < 3 ? true : false;
if (tmp_state != loading_state && !loading_state)
register_delayed_handles();
this->m_cur_step = this->cur_step;
if (this->m_cur_step == 0)
reset_texpos();
@ -304,12 +423,31 @@ static void uninstall_reset_point() {
INTERPOSE_HOOK(tracking_stage_new_arena, logic).remove();
}
static void reserve_static_range() {
if (static_cast<size_t>(enabler->textures.init_texture_size) != enabler->textures.raws.size()) {
WARN(textures).print(
"reserved range can't be installed! all textures will be loaded to dynamic range!");
return;
}
reserved_range.init(enabler->textures.init_texture_size);
dummy_surface =
DFSDL_CreateRGBSurfaceWithFormat(0, 0, 0, 32, SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA32);
dummy_surface->refcount += ReservedRange::size;
for (int32_t i = 0; i < ReservedRange::size; i++) {
add_texture(dummy_surface);
}
enabler->textures.init_texture_size += ReservedRange::size;
}
void Textures::init(color_ostream& out) {
if (!enabler)
return;
reserve_static_range();
install_reset_point();
DEBUG(textures, out).print("dynamic texture loading ready");
DEBUG(textures, out)
.print("dynamic texture loading ready, reserved range %d-%d\n", reserved_range.start,
reserved_range.end);
}
void Textures::cleanup() {
@ -317,6 +455,8 @@ void Textures::cleanup() {
return;
reset_texpos();
reset_reserved_texpos();
reset_tilesets();
reset_surface();
uninstall_reset_point();
}

@ -1 +1 @@
Subproject commit 53a82ea5171cb6fa7e50131eeb0bec801a727fda
Subproject commit e6d83ccaee5b5a3c663b56046ae55a7389742da8

@ -305,6 +305,7 @@ static void cleanup_state()
{
enable_autolabor = false;
labor_infos.clear();
game->external_flag &= ~1; // reinstate DF's work detail system
}
static void reset_labor(df::unit_labor labor)
@ -326,6 +327,8 @@ static void init_state()
if (!enable_autolabor)
return;
game->external_flag |= 1; // bypass DF's work detail system
auto cfg_haulpct = World::GetPersistentData("autolabor/haulpct");
if (cfg_haulpct.isValid())
{
@ -413,8 +416,17 @@ static void enable_plugin(color_ostream &out)
cleanup_state();
init_state();
}
static void disable_plugin(color_ostream& out)
{
if (config.isValid())
setOptionEnabled(CF_ENABLED, false);
game->external_flag |= 1; // shut down DF's work detail system
enable_autolabor = false;
out << "Disabling autolabor." << std::endl;
cleanup_state();
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
@ -1081,12 +1093,7 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable )
}
else if(!enable && enable_autolabor)
{
enable_autolabor = false;
setOptionEnabled(CF_ENABLED, false);
game->external_flag &= ~1; // reenable DF's work detail system
out << "Autolabor is disabled." << std::endl;
disable_plugin(out);
}
return CR_OK;

@ -4,6 +4,7 @@
#include <stack>
#include <string>
#include <cmath>
#include <memory>
#include "Core.h"
#include "Console.h"
@ -1072,14 +1073,13 @@ command_result digv (color_ostream &out, vector <string> & parameters)
con.printerr("I won't dig the borders. That would be cheating!\n");
return CR_FAILURE;
}
MapExtras::MapCache * MCache = new MapExtras::MapCache;
std::unique_ptr<MapExtras::MapCache> MCache = std::make_unique<MapExtras::MapCache>();
df::tile_designation des = MCache->designationAt(xy);
df::tiletype tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->veinMaterialAt(xy);
if( veinmat == -1 )
{
con.printerr("This tile is not a vein.\n");
delete MCache;
return CR_FAILURE;
}
con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
@ -1192,7 +1192,6 @@ command_result digv (color_ostream &out, vector <string> & parameters)
}
}
MCache->WriteAll();
delete MCache;
return CR_OK;
}
@ -1259,7 +1258,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
con.printerr("I won't dig the borders. That would be cheating!\n");
return CR_FAILURE;
}
MapExtras::MapCache * MCache = new MapExtras::MapCache;
std::unique_ptr<MapExtras::MapCache> MCache = std::make_unique<MapExtras::MapCache>();
df::tile_designation des = MCache->designationAt(xy);
df::tiletype tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->veinMaterialAt(xy);
@ -1267,7 +1266,6 @@ command_result digl (color_ostream &out, vector <string> & parameters)
if( veinmat != -1 )
{
con.printerr("This is a vein. Use digv instead!\n");
delete MCache;
return CR_FAILURE;
}
con.print("%d/%d/%d tiletype: %d, basemat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, basemat, des.whole);
@ -1408,7 +1406,6 @@ command_result digl (color_ostream &out, vector <string> & parameters)
}
}
MCache->WriteAll();
delete MCache;
return CR_OK;
}
@ -1424,9 +1421,13 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
return CR_FAILURE;
}
uint32_t zMin = 0;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
bool hidden = false;
bool automine = true;
int32_t targetDigType = -1;
for (string parameter : parameters) {
if ( parameter == "clear" )
@ -1443,8 +1444,16 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
targetDigType = tile_dig_designation::DownStair;
else if ( parameter == "up" )
targetDigType = tile_dig_designation::UpStair;
else if ( parameter == "-z" )
else if ( parameter == "-z" || parameter == "--cur-zlevel" )
{zMax = *window_z + 1; zMin = *window_z;}
else if ( parameter == "--zdown" || parameter == "-d")
zMax = *window_z + 1;
else if ( parameter == "--zup" || parameter == "-u")
zMin = *window_z;
else if ( parameter == "--hidden" || parameter == "-h")
hidden = true;
else if ( parameter == "--no-auto" || parameter == "-a" )
automine = false;
else
{
out.printerr("Invalid parameter: '%s'.\n", parameter.c_str());
@ -1462,14 +1471,21 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
return CR_FAILURE;
}
DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
MapExtras::MapCache * mCache = new MapExtras::MapCache;
std::unique_ptr<MapExtras::MapCache> mCache = std::make_unique<MapExtras::MapCache>();
df::tile_designation baseDes = mCache->designationAt(xy);
if (baseDes.bits.hidden && !hidden) {
out.printerr("Cursor is pointing at a hidden tile. Point the cursor at a visible tile when using the --hidden option.\n");
return CR_FAILURE;
}
df::tile_occupancy baseOcc = mCache->occupancyAt(xy);
df::tiletype tt = mCache->tiletypeAt(xy);
int16_t veinmat = mCache->veinMaterialAt(xy);
if( veinmat == -1 )
{
out.printerr("This tile is not a vein.\n");
delete mCache;
return CR_FAILURE;
}
out.print("(%d,%d,%d) tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, baseDes.whole);
@ -1485,8 +1501,12 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
baseDes.bits.dig = tile_dig_designation::Default;
}
}
// Auto dig only works on default dig designation. Setting dig_auto for any other designation
// prevents dwarves from digging that tile at all.
if (baseDes.bits.dig == tile_dig_designation::Default && automine) baseOcc.bits.dig_auto = true;
else baseOcc.bits.dig_auto = false;
for( uint32_t z = 0; z < zMax; z++ )
for( uint32_t z = zMin; z < zMax; z++ )
{
for( uint32_t x = 1; x < tileXMax-1; x++ )
{
@ -1506,18 +1526,22 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
if ( !mCache->testCoord(current) )
{
out.printerr("testCoord failed at (%d,%d,%d)\n", x, y, z);
delete mCache;
return CR_FAILURE;
}
df::tile_designation designation = mCache->designationAt(current);
if (designation.bits.hidden && !hidden) continue;
df::tile_occupancy occupancy = mCache->occupancyAt(current);
designation.bits.dig = baseDes.bits.dig;
mCache->setDesignationAt(current, designation,priority);
occupancy.bits.dig_auto = baseOcc.bits.dig_auto;
mCache->setDesignationAt(current, designation, priority);
mCache->setOccupancyAt(current, occupancy);
}
}
}
mCache->WriteAll();
delete mCache;
return CR_OK;
}

@ -5,8 +5,8 @@ local helpdb = require('helpdb')
local overlay = require('plugins.overlay')
local widgets = require('gui.widgets')
local logo_textures = dfhack.textures.loadTileset('hack/data/art/logo.png', 8, 12)
local logo_hovered_textures = dfhack.textures.loadTileset('hack/data/art/logo_hovered.png', 8, 12)
local logo_textures = dfhack.textures.loadTileset('hack/data/art/logo.png', 8, 12, true)
local logo_hovered_textures = dfhack.textures.loadTileset('hack/data/art/logo_hovered.png', 8, 12, true)
local function get_command(cmdline)
local first_word = cmdline:trim():split(' +')[1]

@ -36,7 +36,7 @@ namespace DFHack {
static std::vector<TexposHandle> textures;
DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginCommand> &commands) {
textures = Textures::loadTileset("hack/data/art/pathable.png", 32, 32);
textures = Textures::loadTileset("hack/data/art/pathable.png", 32, 32, true);
return CR_OK;
}

@ -130,7 +130,6 @@
using namespace DFHack;
using namespace df::enums;
using namespace RemoteFortressReader;
using namespace std;
DFHACK_PLUGIN("RemoteFortressReader");
@ -193,7 +192,7 @@ const char* growth_locations[] = {
#include "df/art_image.h"
#include "df/art_image_chunk.h"
#include "df/art_image_ref.h"
command_result loadArtImageChunk(color_ostream &out, vector <string> & parameters)
command_result loadArtImageChunk(color_ostream &out, std::vector<std::string> & parameters)
{
if (parameters.size() != 1)
return CR_WRONG_USAGE;
@ -214,7 +213,7 @@ command_result loadArtImageChunk(color_ostream &out, vector <string> & parameter
return CR_OK;
}
command_result RemoteFortressReader_version(color_ostream &out, vector<string> &parameters)
command_result RemoteFortressReader_version(color_ostream &out, std::vector<std::string> &parameters)
{
out.print(RFR_VERSION);
return CR_OK;
@ -645,7 +644,7 @@ void CopyMat(RemoteFortressReader::MatPair * mat, int type, int index)
}
map<DFCoord, uint16_t> hashes;
std::map<DFCoord, uint16_t> hashes;
bool IsTiletypeChanged(DFCoord pos)
{
@ -663,7 +662,7 @@ bool IsTiletypeChanged(DFCoord pos)
return false;
}
map<DFCoord, uint16_t> waterHashes;
std::map<DFCoord, uint16_t> waterHashes;
bool IsDesignationChanged(DFCoord pos)
{
@ -681,7 +680,7 @@ bool IsDesignationChanged(DFCoord pos)
return false;
}
map<DFCoord, uint8_t> buildingHashes;
std::map<DFCoord, uint8_t> buildingHashes;
bool IsBuildingChanged(DFCoord pos)
{
@ -700,7 +699,7 @@ bool IsBuildingChanged(DFCoord pos)
return changed;
}
map<DFCoord, uint16_t> spatterHashes;
std::map<DFCoord, uint16_t> spatterHashes;
bool IsspatterChanged(DFCoord pos)
{
@ -737,7 +736,7 @@ bool IsspatterChanged(DFCoord pos)
return false;
}
map<int, uint16_t> itemHashes;
std::map<int, uint16_t> itemHashes;
bool isItemChanged(int i)
{
@ -755,7 +754,7 @@ bool isItemChanged(int i)
return false;
}
bool areItemsChanged(vector<int> * items)
bool areItemsChanged(std::vector<int> * items)
{
bool result = false;
for (size_t i = 0; i < items->size(); i++)
@ -766,7 +765,7 @@ bool areItemsChanged(vector<int> * items)
return result;
}
map<int, int> engravingHashes;
std::map<int, int> engravingHashes;
bool isEngravingNew(int index)
{

@ -1 +1 @@
Subproject commit e0591830b72cdfaec5c9bdb1bf713a74fe744788
Subproject commit a8aacf9b3e8d71c338f8d087792ee8aa39a85220