Skip to content

Feature/moding framework refactor - #4927

Draft
cerwym wants to merge 31 commits into
dkfans:masterfrom
cerwym:feature/moding-framework-refactor
Draft

Feature/moding framework refactor#4927
cerwym wants to merge 31 commits into
dkfans:masterfrom
cerwym:feature/moding-framework-refactor

Conversation

@cerwym

@cerwym cerwym commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces a new, unified modding and platform abstraction layer, refactors configuration loading to use a single walker-based batch traversal, and updates build scripts to support these changes. The main changes are the delegation of all platform-specific file and directory operations to new platform manager classes, the replacement of per-file mod config loading with a more efficient batch process, and the addition of new source files and build rules for platform and modding support.

Platform Abstraction and File I/O Refactor:

  • All file and directory operations in bflib_fileio.c now delegate to the PlatformManager and its platform-specific implementations (PlatformWindows.cpp, PlatformLinux.cpp). This removes all direct OS-specific logic from the file and centralizes it in the new platform classes. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-6a4d0e428017c28b0c6eaa2c1d35583b79af8d13eeee3d5d1c77eeba22d65fc0L8-R10), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-6a4d0e428017c28b0c6eaa2c1d35583b79af8d13eeee3d5d1c77eeba22d65fc0L25-R99))
  • The Makefile and build scripts are updated to include new platform source files and to enforce include order for platform and modding code. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52R259-R262), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52L354-R359), [[3]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-0fe2808a49cbac879115dca8774642fe3df413773dd5f75310169713023fe636L183-R184), [[4]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-0fe2808a49cbac879115dca8774642fe3df413773dd5f75310169713023fe636R289), [[5]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52R602-R629))

Modding and Configuration Loading Overhaul:

  • The configuration loading system in config.c is refactored to use a walker-based, 6-tier batch traversal for mod overrides, replacing the previous per-file and per-mod-item logic. This allows loading multiple config files in a single pass through the mod tier stack, improving efficiency and consistency. ([src/config.cL2096-R2179](https://github.com/dkfans/keeperfx/pull/4927/files#diff-18680f57f5d32607a3b196afffe0d6ecb250af6c0a994b304b88fc91231250bfL2096-R2179))
  • A new load_config_batch() function and ConfigBatchItem struct are introduced in config.h to support batch loading of configuration files. ([src/config.hR256-R271](https://github.com/dkfans/keeperfx/pull/4927/files#diff-c24f78b3519d763901eb9f67b864f01d802d803df1b24faaf154019cf812bf95R256-R271))
  • Includes and dependencies are updated to use the new modding API and tier stack headers. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-18680f57f5d32607a3b196afffe0d6ecb250af6c0a994b304b88fc91231250bfR46), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-23513555a9d1310a35d7f4b1e4834bf786fa629680af5711dae0e8d4995693e1L31-R32))

Configuration and Sound System:

  • A new [system] section is added to sounds.cfg to allow configuration of the speech queue limit, introducing a new modifiable parameter. ([config/fxdata/sounds.cfgR31-R35](https://github.com/dkfans/keeperfx/pull/4927/files#diff-758b71a4dacdaa54c2a9a552fb9bd67463c86a5302b14eb84010c816b66eff7dR31-R35))

Most important changes:

Platform Abstraction and File I/O

  • All file and directory operations in bflib_fileio.c are now delegated to the new PlatformManager and platform-specific implementations, removing direct OS-specific logic from the file. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-6a4d0e428017c28b0c6eaa2c1d35583b79af8d13eeee3d5d1c77eeba22d65fc0L8-R10), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-6a4d0e428017c28b0c6eaa2c1d35583b79af8d13eeee3d5d1c77eeba22d65fc0L25-R99))
  • Build system changes: new platform and modding source files added to the Makefile and build rules, with enforced include order for platform and modding code. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52R259-R262), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52L354-R359), [[3]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-0fe2808a49cbac879115dca8774642fe3df413773dd5f75310169713023fe636L183-R184), [[4]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-0fe2808a49cbac879115dca8774642fe3df413773dd5f75310169713023fe636R289), [[5]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52R602-R629))

Modding and Configuration Loading

  • Refactored configuration loading in config.c to use a walker-based, 6-tier batch traversal for mod overrides, allowing efficient and consistent loading of multiple config files in a single pass. ([src/config.cL2096-R2179](https://github.com/dkfans/keeperfx/pull/4927/files#diff-18680f57f5d32607a3b196afffe0d6ecb250af6c0a994b304b88fc91231250bfL2096-R2179))
  • Introduced load_config_batch() and ConfigBatchItem in config.h for batch configuration loading. ([src/config.hR256-R271](https://github.com/dkfans/keeperfx/pull/4927/files#diff-c24f78b3519d763901eb9f67b864f01d802d803df1b24faaf154019cf812bf95R256-R271))
  • Updated includes to use new modding API and tier stack headers. ([[1]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-18680f57f5d32607a3b196afffe0d6ecb250af6c0a994b304b88fc91231250bfR46), [[2]](https://github.com/dkfans/keeperfx/pull/4927/files#diff-23513555a9d1310a35d7f4b1e4834bf786fa629680af5711dae0e8d4995693e1L31-R32))

Configuration and Sound System

  • Added [system] section and SPEECH_QUEUE_LIMIT parameter to sounds.cfg for configurable speech queue limits. ([config/fxdata/sounds.cfgR31-R35](https://github.com/dkfans/keeperfx/pull/4927/files#diff-758b71a4dacdaa54c2a9a552fb9bd67463c86a5302b14eb84010c816b66eff7dR31-R35))

cerwym added 27 commits June 15, 2026 09:25
Copilot AI review requested due to automatic review settings June 16, 2026 10:14
@cerwym
cerwym marked this pull request as draft June 16, 2026 10:18
@cerwym cerwym self-assigned this Jun 16, 2026
@cerwym
cerwym marked this pull request as ready for review June 16, 2026 10:18
@cerwym
cerwym requested a review from Loobinex June 16, 2026 10:18
@cerwym
cerwym marked this pull request as draft June 16, 2026 10:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a unified modding “tier stack” + walker API and a new platform abstraction layer, then refactors multiple subsystems (config loading, Lua, sprites, textures, landview, sounds) to use these mechanisms instead of ad-hoc per-mod/per-file logic.

Changes:

  • Added kfx/modding tier-stack + walker APIs (C + C++) and migrated several resource loaders to use walker traversal (including a new batch config loader).
  • Added IPlatform + PlatformManager and moved Windows/Linux entry points, file I/O, and file enumeration behind platform implementations.
  • Extended sound configuration with a new [system] section (SPEECH_QUEUE_LIMIT) and wired SoundManager into the load-event lifecycle.

Reviewed changes

Copilot reviewed 44 out of 44 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/windows.cpp Removed legacy Windows-specific entrypoint + file-find implementation (moved to PlatformWindows/PlatformManager).
src/linux.cpp Removed legacy Linux entrypoint + file-find implementation (moved to PlatformLinux/PlatformManager).
src/sound_manager.h SoundManager now implements IModSubsystem and participates in load events.
src/sound_manager.cpp Registers with mod lifecycle; adds load-event handling; updates sound path resolution to include mod sound dirs.
src/platform/PlatformWindows.h Declares Windows IPlatform implementation interface.
src/platform/PlatformWindows.cpp Implements Windows platform services + WinMain that registers the platform singleton.
src/platform/PlatformLinux.h Declares Linux IPlatform implementation interface.
src/platform/PlatformLinux.cpp Implements Linux platform services + main() that registers the platform singleton.
src/platform/IWindowSystem.h Adds stub window-system abstraction interface.
src/platform/IPlatform.h Adds the core platform abstraction interface used by C wrappers.
src/platform/IAudioPlatform.h Adds stub audio-platform abstraction interface.
src/platform/PlatformManager.h Adds platform singleton accessor + C-callable file I/O wrapper declarations.
src/platform/PlatformManager.cpp Implements platform singleton + C-callable wrappers for OS/file APIs.
src/main.cpp Hooks Startup load event dispatch into init path.
src/main_game.c Replaces direct sound snapshot restore with kfx_trigger_load_event(Level).
src/lvl_script_lib.c Uses unified mod API helper to reload creature configs.
src/lua_base.c Refactors Lua script loading to use mod walker traversal instead of per-mod probing.
src/kfx/modding/tier_stack.h Adds tier-stack lifecycle + subsystem registry + event dispatch API.
src/kfx/modding/tier_stack.cpp Implements tier-stack rebuild and event dispatch (including mod existence probing integration).
src/kfx/modding/ModWalker.hpp Declares the C++ tier-stack walker used by both C API and C++ subsystems.
src/kfx/modding/ModWalker.cpp Implements tier traversal for accumulate/find-first/batch patterns.
src/kfx/modding/mod_location.h Defines tier/lifetime/event/resource-type model and KfxTierStack layout.
src/kfx/modding/mod_api.h Adds C API for creating walkers, visiting tiers, batch visits, and load observers.
src/kfx/modding/mod_api.cpp Implements the C API wrappers and load observer TLS stack.
src/kfx/modding/IModSubsystem.hpp Adds C++ subsystem base class to register for load events.
src/kfx/modding/IModSubsystem.cpp Implements registration trampoline for C++ subsystems.
src/gui_soundmsgs.h Exposes g_speech_queue_limit as a configurable runtime variable.
src/gui_soundmsgs.cpp Switches to configurable queue limit; routes certain scripted sounds through SoundManager resolution.
src/game_saves.c Triggers KfxLoadEvent_SaveLoad after restoring save state.
src/frontmenu_select.c Frontend now uses game_request_campaign_change() wrapper.
src/front_network.c Network frontend now uses game_request_campaign_change() wrapper.
src/front_landview.c Landview assets are located via tier-stack walker (campaign tier).
src/engine_textures.c Texture resolution refactored to walker-based find-first across tiers.
src/dungeon_stats.c Uses load_config_batch() and adds load progress notifications per creature.
src/custom_sprites.c Sprite loading refactored to walker-based directory + per-map zip traversal.
src/config.h Introduces ConfigBatchItem and load_config_batch() declaration.
src/config.c Implements load_config_batch() using a single walker traversal for mod overrides; load_config() refactored.
src/config_strings.c Refactors GUI/campaign string overrides to walker-based traversal.
src/config_sounds.h Declares g_speech_queue_limit and documents new config behavior.
src/config_sounds.c Adds parsing for new [system] section and resets speech queue limit during baseline reset.
src/config_mods.h Adds sound exist-state flag; removes public recheck_all_mod_exist() decl.
src/config_mods.c Probes mods/<name>/sound/ as a new existence-checked resource dir.
src/config_keeperfx.c Refactors KeeperFX config overrides to walker-based traversal; removes early mod probing call.
src/config_crtrmodel.c Refactors creature model config loading to walker-based traversal across tiers.
src/config_campaigns.h Adds game_request_campaign_change() wrapper declaration.
src/config_campaigns.c Replaces direct sound reload logic with kfx_trigger_load_event(Campaign); adds wrapper implementation.
src/bflib_fileio.c Converts file I/O to thin delegates into the platform abstraction.
Makefile Adds new modding/platform objects and enforces pre/post include checks for platform sources.
linux.mk Swaps legacy linux.cpp for new platform sources; adds -Isrc include path.
config/fxdata/sounds.cfg Adds [system] section with SPEECH_QUEUE_LIMIT.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/config.c
Comment on lines +2146 to +2150
if (s_config_walker == NULL)
s_config_walker = kfx_mod_create_walker(s_config_locs,
sizeof(s_config_locs) / sizeof(s_config_locs[0]));

if (mods_conf.after_campaign_cnt > 0)
{
load_config_for_mod_list(file_data, flags, mods_conf.after_campaign_item, mods_conf.after_campaign_cnt);
KfxModBatchEntry entries[count];
Comment thread src/config.c
Comment on lines +2174 to 2180
TbBool load_config(const struct ConfigFileData* file_data, unsigned short flags)
{
const ConfigBatchItem item = { file_data, flags };
load_config_batch(&item, 1);
/* Probe base file to determine success — same semantics as before. */
return LbFileLengthRnc(prepare_file_path(FGrp_FxData, file_data->filename)) > 0;
}
Comment thread src/main.cpp
Comment on lines 921 to +925
// Load configs which may have per-campaign part, and even be modified within a level
recheck_all_mod_exist();
init_custom_sprites(SPRITE_LAST_LEVEL);
load_stats_files();
check_and_auto_fix_stats();
// Notify all registered subsystems that the game has started.
Comment on lines +65 to +71
/**
* Register a subsystem reload callback with the event dispatch system.
*
* Registrations persist for the lifetime of the process. The callback is
* invoked by kfx_trigger_load_event() whenever the event matches the
* subsystem's declared lifetimes.
*
Comment on lines +42 to +57
void kfx_mod_visit_all(KfxModHandle handle,
const KfxTierStack *stack,
const char *base_fname,
ModOnFoundFn cb, void *userdata)
{
static_cast<ModWalker *>(handle)->visitAll(stack, base_fname, cb, userdata);
}

TbBool kfx_mod_find_first(KfxModHandle handle,
const KfxTierStack *stack,
const char *base_fname,
char *out_path, size_t out_size)
{
return static_cast<ModWalker *>(handle)->findFirst(stack, base_fname, out_path, out_size)
? 1 : 0;
}
Comment on lines +53 to +66
extern "C" TbFileFind* LbFileFindFirst(const char* filespec, TbFileEntry* fentry)
{
return PlatformManager::Get()->FileFindFirst(filespec, fentry);
}

extern "C" int LbFileFindNext(TbFileFind* ffind, TbFileEntry* fentry)
{
return PlatformManager::Get()->FileFindNext(ffind, fentry);
}

extern "C" void LbFileFindEnd(TbFileFind* ffind)
{
PlatformManager::Get()->FileFindEnd(ffind);
}
Comment on lines +70 to +88
extern "C" TbBool PlatformManager_FileExists(const char* path)
{
return PlatformManager::Get()->FileExists(path);
}

extern "C" int PlatformManager_MakeDirectory(const char* path)
{
return PlatformManager::Get()->MakeDirectory(path);
}

extern "C" int PlatformManager_GetCurrentDirectory(char* buf, unsigned long buflen)
{
return PlatformManager::Get()->GetCurrentDirectory(buf, buflen);
}

extern "C" TbFileHandle PlatformManager_FileOpen(const char* fname, unsigned char accmode)
{
return PlatformManager::Get()->FileOpen(fname, accmode);
}
Comment on lines +90 to +103
extern "C" int PlatformManager_FileClose(TbFileHandle handle)
{
return PlatformManager::Get()->FileClose(handle);
}

extern "C" int PlatformManager_FileRead(TbFileHandle handle, void* buf, unsigned long len)
{
return PlatformManager::Get()->FileRead(handle, buf, len);
}

extern "C" long PlatformManager_FileWrite(TbFileHandle handle, const void* buf, unsigned long len)
{
return PlatformManager::Get()->FileWrite(handle, buf, len);
}
Comment on lines +105 to +123
extern "C" int PlatformManager_FileSeek(TbFileHandle handle, long offset, unsigned char origin)
{
return PlatformManager::Get()->FileSeek(handle, offset, origin);
}

extern "C" int PlatformManager_FilePosition(TbFileHandle handle)
{
return PlatformManager::Get()->FilePosition(handle);
}

extern "C" TbBool PlatformManager_FileEof(TbFileHandle handle)
{
return PlatformManager::Get()->FileEof(handle);
}

extern "C" short PlatformManager_FileFlush(TbFileHandle handle)
{
return PlatformManager::Get()->FileFlush(handle);
}
Comment on lines +125 to +133
extern "C" long PlatformManager_FileLength(const char* fname)
{
return PlatformManager::Get()->FileLength(fname);
}

extern "C" int PlatformManager_FileDelete(const char* fname)
{
return PlatformManager::Get()->FileDelete(fname);
}
@cerwym
cerwym marked this pull request as ready for review June 16, 2026 10:22
@cerwym
cerwym marked this pull request as draft June 16, 2026 10:34
@cerwym
cerwym marked this pull request as ready for review June 16, 2026 10:34
@cerwym
cerwym marked this pull request as draft June 16, 2026 10:48
@cerwym
cerwym marked this pull request as ready for review June 16, 2026 10:48
@cerwym
cerwym marked this pull request as draft June 16, 2026 14:38
@benlp91
benlp91 marked this pull request as ready for review June 24, 2026 20:37
@benlp91
benlp91 marked this pull request as draft June 24, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants