Skip to content

Commit c152ce6

Browse files
authored
Merge pull request #5784 from DFHack/resteam
Update Steam launcher
2 parents 9c5469b + 7316621 commit c152ce6

11 files changed

Lines changed: 309 additions & 72 deletions

File tree

CMakeLists.txt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ cmake_policy(SET CMP0074 NEW)
77

88
# set up versioning.
99
set(DF_VERSION "53.11")
10-
set(DFHACK_RELEASE "r2")
11-
set(DFHACK_PRERELEASE FALSE)
10+
set(DFHACK_RELEASE "r3rc1")
11+
set(DFHACK_PRERELEASE TRUE)
1212

1313
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
1414
set(DFHACK_ABI_VERSION 2)
@@ -226,13 +226,10 @@ set(DFHACK_DATA_DESTINATION hack)
226226

227227
## where to install things (after the build is done, classic 'make install' or package structure)
228228
# the dfhack libraries will be installed here:
229-
if(UNIX)
230-
# put the lib into DF/hack
231-
set(DFHACK_LIBRARY_DESTINATION ${DFHACK_DATA_DESTINATION})
232-
else()
233-
# windows is crap, therefore we can't do nice things with it. leave the libs on a nasty pile...
234-
set(DFHACK_LIBRARY_DESTINATION .)
235-
endif()
229+
230+
# put the lib into DF/hack
231+
# windows will find it because dfhooks will `AddDllDirectory` the hack folder at runtime
232+
set(DFHACK_LIBRARY_DESTINATION ${DFHACK_DATA_DESTINATION})
236233

237234
# external tools will be installed here:
238235
set(DFHACK_BINARY_DESTINATION .)
@@ -267,7 +264,7 @@ if(UNIX)
267264
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -march=i686")
268265
endif()
269266
string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
270-
set(CMAKE_INSTALL_RPATH ${DFHACK_LIBRARY_DESTINATION})
267+
set(CMAKE_INSTALL_RPATH "$ORIGIN")
271268
elseif(MSVC)
272269
# for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion
273270
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm /MP")

docs/changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ Template for new versions:
6060
## New Features
6161

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

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

6668
## Documentation
6769

library/CMakeLists.txt

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ endif()
131131

132132
set(MAIN_SOURCES_WINDOWS
133133
${CONSOLE_SOURCES}
134-
Hooks.cpp
135134
)
136135

137136
if(WIN32)
@@ -318,8 +317,6 @@ endif()
318317

319318
# Compilation
320319

321-
add_definitions(-DBUILD_DFHACK_LIB)
322-
323320
if(UNIX)
324321
if(CONSOLE_NO_CATCH)
325322
add_definitions(-DCONSOLE_NO_CATCH)
@@ -373,6 +370,7 @@ if(EXISTS ${dfhack_SOURCE_DIR}/.git/index AND EXISTS ${dfhack_SOURCE_DIR}/.git/m
373370
endif()
374371

375372
add_library(dfhack SHARED ${PROJECT_SOURCES})
373+
target_compile_definitions(dfhack PRIVATE BUILD_DFHACK_LIB)
376374
target_include_directories(dfhack PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/proto)
377375

378376
get_target_property(xlsxio_INCLUDES xlsxio_read_STATIC INTERFACE_INCLUDE_DIRECTORIES)
@@ -381,6 +379,7 @@ add_dependencies(dfhack generate_proto_core)
381379
add_dependencies(dfhack generate_headers)
382380

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

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

393392
if(WIN32)
394-
set_target_properties(dfhack PROPERTIES OUTPUT_NAME "dfhooks_dfhack" )
395393
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
396394
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
397395
else()
398396
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" )
399397
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "-include Export.h" )
400-
add_library(dfhooks_dfhack SHARED Hooks.cpp)
401-
target_link_libraries(dfhooks_dfhack dfhack ${FMTLIB})
402398
endif()
403399

400+
add_library(dfhooks_dfhack SHARED Hooks.cpp)
401+
target_link_libraries(dfhooks_dfhack PUBLIC dfhack ${FMTLIB})
402+
404403
# effectively disables debug builds...
405404
set_target_properties(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
406405

@@ -450,11 +449,13 @@ if(UNIX)
450449
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
451450
DESTINATION .)
452451
endif()
453-
install(TARGETS dfhooks_dfhack
454-
LIBRARY DESTINATION .
455-
RUNTIME DESTINATION .)
456452
endif()
457453

454+
install(TARGETS dfhooks_dfhack
455+
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
456+
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})
457+
458+
458459
# install the main lib
459460
install(TARGETS dfhack
460461
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
@@ -464,6 +465,12 @@ install(TARGETS dfhack-run dfhack-client binpatch
464465
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
465466
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})
466467

468+
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dfhooks_dfhack.ini
469+
CONTENT "${DFHACK_DATA_DESTINATION}/$<TARGET_FILE_NAME:dfhooks_dfhack>")
470+
471+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dfhooks_dfhack.ini
472+
DESTINATION .)
473+
467474
endif(BUILD_LIBRARY)
468475

469476
# install the offset file

library/Core.cpp

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,22 @@ bool Core::loadScriptFile(color_ostream &out, std::filesystem::path fname, bool
859859
INFO(script,out) << "Running script: " << fname << std::endl;
860860
std::cerr << "Running script: " << fname << std::endl;
861861
}
862-
std::ifstream script{ fname.c_str() };
862+
863+
auto pathlist = {getHackPath(), getHackPath().parent_path(), std::filesystem::current_path()};
864+
865+
std::filesystem::path path;
866+
867+
for (auto& p : pathlist)
868+
{
869+
auto candidate = fname.is_relative() ? p / fname : fname;
870+
if (std::filesystem::exists(candidate))
871+
{
872+
path = candidate;
873+
break;
874+
}
875+
}
876+
877+
std::ifstream script{ path };
863878
if ( !script )
864879
{
865880
if(!silent)
@@ -1054,16 +1069,17 @@ void Core::fatal (std::string output, const char * title)
10541069

10551070
std::filesystem::path Core::getHackPath()
10561071
{
1057-
return Filesystem::get_initial_cwd() / "hack";
1072+
return hack_path;
10581073
}
10591074

10601075
df::viewscreen * Core::getTopViewscreen() {
10611076
return getInstance().top_viewscreen;
10621077
}
10631078

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

10681084
Filesystem::init();
10691085

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

10951112
std::cerr << "Binding to SDL.\n";
10961113
if (!DFSDL::init(con)) {
@@ -1232,9 +1249,9 @@ bool Core::InitSimulationThread()
12321249
{
12331250
// the update hook is only called from the simulation thread, so capture this thread id
12341251
df_simulation_thread = std::this_thread::get_id();
1235-
if(started)
1252+
if (started)
12361253
return true;
1237-
if(errorstate)
1254+
if (errorstate)
12381255
return false;
12391256

12401257
// Lock the CoreSuspendMutex until the thread exits or call Core::Shutdown
@@ -1276,20 +1293,20 @@ bool Core::InitSimulationThread()
12761293
std::cout << "Console disabled.\n";
12771294
}
12781295
}
1279-
else if(con.init(false))
1296+
else if (con.init(false))
12801297
std::cerr << "Console is running.\n";
12811298
else
12821299
std::cerr << "Console has failed to initialize!\n";
1283-
/*
1284-
// dump offsets to a file
1285-
std::ofstream dump("offsets.log");
1286-
if(!dump.fail())
1287-
{
1288-
//dump << vinfo->PrintOffsets();
1289-
dump.close();
1290-
}
1291-
*/
1292-
// initialize data defs
1300+
/*
1301+
// dump offsets to a file
1302+
std::ofstream dump("offsets.log");
1303+
if(!dump.fail())
1304+
{
1305+
//dump << vinfo->PrintOffsets();
1306+
dump.close();
1307+
}
1308+
*/
1309+
// initialize data defs
12931310
virtual_identity::Init(this);
12941311

12951312
// create config directory if it doesn't already exist
@@ -1306,7 +1323,8 @@ bool Core::InitSimulationThread()
13061323
else
13071324
{
13081325
// ensure all config file directories exist before we start copying files
1309-
for (auto &entry : default_config_files) {
1326+
for (auto& entry : default_config_files)
1327+
{
13101328
// skip over files
13111329
if (!entry.second)
13121330
continue;
@@ -1316,19 +1334,22 @@ bool Core::InitSimulationThread()
13161334
}
13171335

13181336
// copy files from the default tree that don't already exist in the config tree
1319-
for (auto &entry : default_config_files) {
1337+
for (auto& entry : default_config_files)
1338+
{
13201339
// skip over directories
13211340
if (entry.second)
13221341
continue;
13231342
std::filesystem::path filename = entry.first;
1324-
if (!config_files.contains(filename)) {
1343+
if (!config_files.contains(filename))
1344+
{
13251345
std::filesystem::path src_file = getConfigDefaultsPath() / filename;
13261346
if (!Filesystem::isfile(src_file))
13271347
continue;
13281348
std::filesystem::path dest_file = getConfigPath() / filename;
13291349
std::ifstream src(src_file, std::ios::binary);
13301350
std::ofstream dest(dest_file, std::ios::binary);
1331-
if (!src.good() || !dest.good()) {
1351+
if (!src.good() || !dest.good())
1352+
{
13321353
con.printerr("Copy failed: '{}'\n", filename);
13331354
continue;
13341355
}
@@ -1339,6 +1360,17 @@ bool Core::InitSimulationThread()
13391360
}
13401361
}
13411362

1363+
// set lua default path if not already set
1364+
if (std::getenv("DFHACK_LUA_PATH") == nullptr)
1365+
{
1366+
std::filesystem::path lua_path = getHackPath() / "lua" / "?.lua";
1367+
#ifdef WIN32
1368+
_putenv_s("DFHACK_LUA_PATH", lua_path.string().c_str());
1369+
#else
1370+
setenv("DFHACK_LUA_PATH", lua_path.string().c_str(), 1);
1371+
#endif
1372+
}
1373+
13421374
loadScriptPaths(con);
13431375

13441376
// initialize common lua context

library/Hooks.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,43 @@
33

44
#include "df/gamest.h"
55

6+
#ifdef _WIN32
7+
# define WIN32_LEAN_AND_MEAN
8+
# include <Windows.h>
9+
# include <libloaderapi.h>
10+
#else
11+
# include <dlfcn.h>
12+
#endif
13+
614
static bool disabled = false;
715

816
DFhackCExport const int32_t dfhooks_priority = 100;
917

18+
static std::filesystem::path getModulePath()
19+
{
20+
#ifdef _WIN32
21+
HMODULE module = nullptr;
22+
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)getModulePath, &module);
23+
if (!module) return std::filesystem::path(); // should never happen, but just in case, return an empty path instead of crashing
24+
25+
wchar_t path[MAX_PATH];
26+
GetModuleFileNameW(module, path, MAX_PATH);
27+
return std::filesystem::path(path);
28+
#else
29+
Dl_info info;
30+
dladdr((const void*)getModulePath, &info);
31+
return std::filesystem::path(info.dli_fname);
32+
#endif
33+
}
34+
35+
static std::filesystem::path basepath{getModulePath()};
36+
37+
// called by the chainloader before the main thread is initialized and before any other hooks are called.
38+
DFhackCExport void dfhooks_preinit(std::filesystem::path dllpath)
39+
{
40+
basepath = dllpath.parent_path();
41+
}
42+
1043
// called from the main thread before the simulation thread is started
1144
// and the main event loop is initiated
1245
DFhackCExport void dfhooks_init() {
@@ -17,7 +50,7 @@ DFhackCExport void dfhooks_init() {
1750
}
1851

1952
// we need to init DF globals before we can check the commandline
20-
if (!DFHack::Core::getInstance().InitMainThread() || !df::global::game) {
53+
if (!DFHack::Core::getInstance().InitMainThread(std::filesystem::canonical(basepath)) || !df::global::game) {
2154
// we don't set disabled to true here so symbol generation can work
2255
return;
2356
}

library/PlugLoad.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
#ifdef WIN32
1616
#define NOMINMAX
1717
#include <windows.h>
18+
#include <libloaderapi.h>
1819
#define global_search_handle() GetModuleHandle(nullptr)
1920
#define get_function_address(plugin, function) GetProcAddress((HMODULE)plugin, function)
2021
#define clear_error()
21-
#define load_library(fn) LoadLibraryW(fn.c_str())
22+
#define load_library(fn) LoadLibraryExW(fn.wstring().c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
2223
#define close_library(handle) (!(FreeLibrary((HMODULE)handle)))
2324
#else
2425
#include <dlfcn.h>

library/include/Core.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ namespace DFHack
268268
struct Private;
269269
std::unique_ptr<Private> d;
270270

271-
bool InitMainThread();
271+
bool InitMainThread(std::filesystem::path path);
272272
bool InitSimulationThread();
273273
int Update (void);
274274
int Shutdown (void);
@@ -353,6 +353,8 @@ namespace DFHack
353353

354354
uint32_t unpaused_ms; // reset to 0 on map load
355355

356+
std::filesystem::path hack_path;
357+
356358
friend class CoreService;
357359
friend class ServerConnection;
358360
friend class CoreSuspender;

library/include/Hooks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ distribution.
2626

2727
union SDL_Event;
2828

29+
DFhackCExport void dfhooks_preinit(std::filesystem::path dllpath);
2930
DFhackCExport void dfhooks_init();
3031
DFhackCExport void dfhooks_shutdown();
3132
DFhackCExport void dfhooks_update();

0 commit comments

Comments
 (0)