Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ cmake_policy(SET CMP0074 NEW)

# set up versioning.
set(DF_VERSION "53.11")
set(DFHACK_RELEASE "r2")
set(DFHACK_PRERELEASE FALSE)
set(DFHACK_RELEASE "r3rc1")
set(DFHACK_PRERELEASE TRUE)

set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
set(DFHACK_ABI_VERSION 2)
Expand Down Expand Up @@ -226,13 +226,10 @@ set(DFHACK_DATA_DESTINATION hack)

## where to install things (after the build is done, classic 'make install' or package structure)
# the dfhack libraries will be installed here:
if(UNIX)
# put the lib into DF/hack
set(DFHACK_LIBRARY_DESTINATION ${DFHACK_DATA_DESTINATION})
else()
# windows is crap, therefore we can't do nice things with it. leave the libs on a nasty pile...
set(DFHACK_LIBRARY_DESTINATION .)
endif()

# put the lib into DF/hack
# windows will find it because dfhooks will `AddDllDirectory` the hack folder at runtime
set(DFHACK_LIBRARY_DESTINATION ${DFHACK_DATA_DESTINATION})

# external tools will be installed here:
set(DFHACK_BINARY_DESTINATION .)
Expand Down Expand Up @@ -267,7 +264,7 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -march=i686")
endif()
string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_INSTALL_RPATH ${DFHACK_LIBRARY_DESTINATION})
set(CMAKE_INSTALL_RPATH "$ORIGIN")
elseif(MSVC)
# for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm /MP")
Expand Down
2 changes: 1 addition & 1 deletion depends/dfhooks
2 changes: 2 additions & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ Template for new versions:
## New Features

## Fixes
- Steam launcher: Switch to injection strategy, allowing Dwarf Fortress and DFHack to be installed in disparate locations

## Misc Improvements
- Make DFHack relocatable so that it doesn't depend on being fully co-installed with Dwarf Fortress

## Documentation

Expand Down
25 changes: 16 additions & 9 deletions library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ endif()

set(MAIN_SOURCES_WINDOWS
${CONSOLE_SOURCES}
Hooks.cpp
)

if(WIN32)
Expand Down Expand Up @@ -318,8 +317,6 @@ endif()

# Compilation

add_definitions(-DBUILD_DFHACK_LIB)

if(UNIX)
if(CONSOLE_NO_CATCH)
add_definitions(-DCONSOLE_NO_CATCH)
Expand Down Expand Up @@ -373,6 +370,7 @@ if(EXISTS ${dfhack_SOURCE_DIR}/.git/index AND EXISTS ${dfhack_SOURCE_DIR}/.git/m
endif()

add_library(dfhack SHARED ${PROJECT_SOURCES})
target_compile_definitions(dfhack PRIVATE BUILD_DFHACK_LIB)
target_include_directories(dfhack PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/proto)

get_target_property(xlsxio_INCLUDES xlsxio_read_STATIC INTERFACE_INCLUDE_DIRECTORIES)
Expand All @@ -381,6 +379,7 @@ add_dependencies(dfhack generate_proto_core)
add_dependencies(dfhack generate_headers)

add_library(dfhack-client SHARED RemoteClient.cpp ColorText.cpp MiscUtils.cpp Error.cpp ${PROJECT_PROTO_SRCS} ${CONSOLE_SOURCES})
target_compile_definitions(dfhack-client PRIVATE BUILD_DFHACK_LIB)
target_include_directories(dfhack-client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/proto)
add_dependencies(dfhack-client dfhack)

Expand All @@ -391,16 +390,16 @@ add_executable(binpatch binpatch.cpp)
target_link_libraries(binpatch dfhack-md5)

if(WIN32)
set_target_properties(dfhack PROPERTIES OUTPUT_NAME "dfhooks_dfhack" )
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
else()
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" )
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "-include Export.h" )
add_library(dfhooks_dfhack SHARED Hooks.cpp)
target_link_libraries(dfhooks_dfhack dfhack ${FMTLIB})
endif()

add_library(dfhooks_dfhack SHARED Hooks.cpp)
target_link_libraries(dfhooks_dfhack PUBLIC dfhack ${FMTLIB})

# effectively disables debug builds...
set_target_properties(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )

Expand Down Expand Up @@ -450,11 +449,13 @@ if(UNIX)
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
DESTINATION .)
endif()
install(TARGETS dfhooks_dfhack
LIBRARY DESTINATION .
RUNTIME DESTINATION .)
endif()

install(TARGETS dfhooks_dfhack
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})


# install the main lib
install(TARGETS dfhack
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
Expand All @@ -464,6 +465,12 @@ install(TARGETS dfhack-run dfhack-client binpatch
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})

file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dfhooks_dfhack.ini
CONTENT "${DFHACK_DATA_DESTINATION}/$<TARGET_FILE_NAME:dfhooks_dfhack>")

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dfhooks_dfhack.ini
DESTINATION .)

endif(BUILD_LIBRARY)

# install the offset file
Expand Down
72 changes: 52 additions & 20 deletions library/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,22 @@ bool Core::loadScriptFile(color_ostream &out, std::filesystem::path fname, bool
INFO(script,out) << "Running script: " << fname << std::endl;
std::cerr << "Running script: " << fname << std::endl;
}
std::ifstream script{ fname.c_str() };

auto pathlist = {getHackPath(), getHackPath().parent_path(), std::filesystem::current_path()};

std::filesystem::path path;

for (auto& p : pathlist)
{
auto candidate = fname.is_relative() ? p / fname : fname;
if (std::filesystem::exists(candidate))
{
path = candidate;
break;
}
}

std::ifstream script{ path };
if ( !script )
{
if(!silent)
Expand Down Expand Up @@ -1054,16 +1069,17 @@ void Core::fatal (std::string output, const char * title)

std::filesystem::path Core::getHackPath()
{
return Filesystem::get_initial_cwd() / "hack";
return hack_path;
}

df::viewscreen * Core::getTopViewscreen() {
return getInstance().top_viewscreen;
}

bool Core::InitMainThread() {
bool Core::InitMainThread(std::filesystem::path path) {
// this hook is always called from DF's main (render) thread, so capture this thread id
df_render_thread = std::this_thread::get_id();
hack_path = path;

Filesystem::init();

Expand Down Expand Up @@ -1091,6 +1107,7 @@ bool Core::InitMainThread() {
std::cerr << "Build url: " << Version::dfhack_run_url() << std::endl;
}
std::cerr << "Starting with working directory: " << Filesystem::getcwd() << std::endl;
std::cerr << "Hack path: " << getHackPath() << std::endl;

std::cerr << "Binding to SDL.\n";
if (!DFSDL::init(con)) {
Expand Down Expand Up @@ -1232,9 +1249,9 @@ bool Core::InitSimulationThread()
{
// the update hook is only called from the simulation thread, so capture this thread id
df_simulation_thread = std::this_thread::get_id();
if(started)
if (started)
return true;
if(errorstate)
if (errorstate)
return false;

// Lock the CoreSuspendMutex until the thread exits or call Core::Shutdown
Expand Down Expand Up @@ -1276,20 +1293,20 @@ bool Core::InitSimulationThread()
std::cout << "Console disabled.\n";
}
}
else if(con.init(false))
else if (con.init(false))
std::cerr << "Console is running.\n";
else
std::cerr << "Console has failed to initialize!\n";
/*
// dump offsets to a file
std::ofstream dump("offsets.log");
if(!dump.fail())
{
//dump << vinfo->PrintOffsets();
dump.close();
}
*/
// initialize data defs
/*
// dump offsets to a file
std::ofstream dump("offsets.log");
if(!dump.fail())
{
//dump << vinfo->PrintOffsets();
dump.close();
}
*/
// initialize data defs
virtual_identity::Init(this);

// create config directory if it doesn't already exist
Expand All @@ -1306,7 +1323,8 @@ bool Core::InitSimulationThread()
else
{
// ensure all config file directories exist before we start copying files
for (auto &entry : default_config_files) {
for (auto& entry : default_config_files)
{
// skip over files
if (!entry.second)
continue;
Expand All @@ -1316,19 +1334,22 @@ bool Core::InitSimulationThread()
}

// copy files from the default tree that don't already exist in the config tree
for (auto &entry : default_config_files) {
for (auto& entry : default_config_files)
{
// skip over directories
if (entry.second)
continue;
std::filesystem::path filename = entry.first;
if (!config_files.contains(filename)) {
if (!config_files.contains(filename))
{
std::filesystem::path src_file = getConfigDefaultsPath() / filename;
if (!Filesystem::isfile(src_file))
continue;
std::filesystem::path dest_file = getConfigPath() / filename;
std::ifstream src(src_file, std::ios::binary);
std::ofstream dest(dest_file, std::ios::binary);
if (!src.good() || !dest.good()) {
if (!src.good() || !dest.good())
{
con.printerr("Copy failed: '{}'\n", filename);
continue;
}
Expand All @@ -1339,6 +1360,17 @@ bool Core::InitSimulationThread()
}
}

// set lua default path if not already set
if (std::getenv("DFHACK_LUA_PATH") == nullptr)
{
std::filesystem::path lua_path = getHackPath() / "lua" / "?.lua";
#ifdef WIN32
_putenv_s("DFHACK_LUA_PATH", lua_path.string().c_str());
#else
setenv("DFHACK_LUA_PATH", lua_path.string().c_str(), 1);
#endif
}

loadScriptPaths(con);

// initialize common lua context
Expand Down
35 changes: 34 additions & 1 deletion library/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,43 @@

#include "df/gamest.h"

#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <Windows.h>
# include <libloaderapi.h>
#else
# include <dlfcn.h>
#endif

static bool disabled = false;

DFhackCExport const int32_t dfhooks_priority = 100;

static std::filesystem::path getModulePath()
{
#ifdef _WIN32
HMODULE module = nullptr;
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)getModulePath, &module);
if (!module) return std::filesystem::path(); // should never happen, but just in case, return an empty path instead of crashing

wchar_t path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
return std::filesystem::path(path);
#else
Dl_info info;
dladdr((const void*)getModulePath, &info);
return std::filesystem::path(info.dli_fname);
#endif
}

static std::filesystem::path basepath{getModulePath()};

// called by the chainloader before the main thread is initialized and before any other hooks are called.
DFhackCExport void dfhooks_preinit(std::filesystem::path dllpath)
{
basepath = dllpath.parent_path();
}

// called from the main thread before the simulation thread is started
// and the main event loop is initiated
DFhackCExport void dfhooks_init() {
Expand All @@ -17,7 +50,7 @@ DFhackCExport void dfhooks_init() {
}

// we need to init DF globals before we can check the commandline
if (!DFHack::Core::getInstance().InitMainThread() || !df::global::game) {
if (!DFHack::Core::getInstance().InitMainThread(std::filesystem::canonical(basepath)) || !df::global::game) {
// we don't set disabled to true here so symbol generation can work
return;
}
Expand Down
3 changes: 2 additions & 1 deletion library/PlugLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
#ifdef WIN32
#define NOMINMAX
#include <windows.h>
#include <libloaderapi.h>
#define global_search_handle() GetModuleHandle(nullptr)
#define get_function_address(plugin, function) GetProcAddress((HMODULE)plugin, function)
#define clear_error()
#define load_library(fn) LoadLibraryW(fn.c_str())
#define load_library(fn) LoadLibraryExW(fn.wstring().c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
#define close_library(handle) (!(FreeLibrary((HMODULE)handle)))
#else
#include <dlfcn.h>
Expand Down
4 changes: 3 additions & 1 deletion library/include/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ namespace DFHack
struct Private;
std::unique_ptr<Private> d;

bool InitMainThread();
bool InitMainThread(std::filesystem::path path);
bool InitSimulationThread();
int Update (void);
int Shutdown (void);
Expand Down Expand Up @@ -353,6 +353,8 @@ namespace DFHack

uint32_t unpaused_ms; // reset to 0 on map load

std::filesystem::path hack_path;

friend class CoreService;
friend class ServerConnection;
friend class CoreSuspender;
Expand Down
1 change: 1 addition & 0 deletions library/include/Hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ distribution.

union SDL_Event;

DFhackCExport void dfhooks_preinit(std::filesystem::path dllpath);
DFhackCExport void dfhooks_init();
DFhackCExport void dfhooks_shutdown();
DFhackCExport void dfhooks_update();
Expand Down
Loading
Loading