Skip to content

Commit 63ca6b1

Browse files
committed
Implement ModLoader module with engine integration
Add ModLoader module that provides Virtools engine integration and hooking capabilities. This replaces the previous BMLPlus.dll functionality by separating engine concerns from mod compatibility. The ModLoader module includes: - HookBlock behavior for intercepting building block execution - CK Manager for engine lifecycle event handling - Dynamic BML Core API loading to avoid static linking - MinHook integration for engine function hooking - IMC event publishing for mod lifecycle coordination This change establishes the foundation for mod loading by providing the necessary engine integration layer while maintaining separation of concerns between the engine integration and the core mod management functionality.
1 parent 17eb0ec commit 63ca6b1

File tree

7 files changed

+888
-0
lines changed

7 files changed

+888
-0
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ configure_file(Version.h.in "${BML_INCLUDE_DIR}/BML/Version.h" @ONLY)
22

33
add_subdirectory(Utils)
44
add_subdirectory(Core)
5+
add_subdirectory(ModLoader)
56

67
set(BML_PUBLIC_HEADERS
78
${BML_INCLUDE_DIR}/BML/Version.h
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* @file HookBlock.cpp
3+
* @brief Building block hooking behavior for Virtools
4+
*
5+
* This behavior allows intercepting and extending building block execution
6+
* through callback registration. Used by ModLoader to provide mod callbacks
7+
* at specific points in the game's behavior graph execution.
8+
*/
9+
10+
#include "CKAll.h"
11+
12+
typedef int (*CKBehaviorCallback)(const CKBehaviorContext *behcontext, void *arg);
13+
14+
// Forward declarations
15+
CKObjectDeclaration *FillBehaviorHookBlockDecl();
16+
CKERROR CreateHookBlockProto(CKBehaviorPrototype **pproto);
17+
int HookBlock(const CKBehaviorContext &behcontext);
18+
19+
/**
20+
* @brief Creates the HookBlock object declaration
21+
*
22+
* Registers the HookBlock building block with the Virtools engine.
23+
* This block is used to intercept behavior graph execution.
24+
*/
25+
CKObjectDeclaration *FillBehaviorHookBlockDecl() {
26+
CKObjectDeclaration *od = CreateCKObjectDeclaration("HookBlock");
27+
od->SetDescription("Hook building blocks");
28+
od->SetCategory("Hook");
29+
od->SetType(CKDLL_BEHAVIORPROTOTYPE);
30+
od->SetGuid(CKGUID(0x19038c0, 0x663902da));
31+
od->SetAuthorGuid(CKGUID(0x3a086b4d, 0x2f4a4f01));
32+
od->SetAuthorName("Kakuty");
33+
od->SetVersion(0x00010000);
34+
od->SetCreationFunction(CreateHookBlockProto);
35+
od->SetCompatibleClassId(CKCID_BEOBJECT);
36+
return od;
37+
}
38+
39+
/**
40+
* @brief Creates the HookBlock behavior prototype
41+
*
42+
* Defines the behavior's parameters and settings:
43+
* - Local parameter 0: Callback function pointer
44+
* - Local parameter 1: User argument pointer
45+
* - Variable inputs/outputs for flexible hooking
46+
*/
47+
CKERROR CreateHookBlockProto(CKBehaviorPrototype **pproto) {
48+
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("HookBlock");
49+
if (!proto) return CKERR_OUTOFMEMORY;
50+
51+
proto->DeclareLocalParameter("Callback", CKPGUID_POINTER);
52+
proto->DeclareLocalParameter("Argument", CKPGUID_POINTER);
53+
54+
proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)(CKBEHAVIOR_VARIABLEINPUTS | CKBEHAVIOR_VARIABLEOUTPUTS));
55+
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
56+
proto->SetFunction(HookBlock);
57+
58+
*pproto = proto;
59+
return CK_OK;
60+
}
61+
62+
/**
63+
* @brief HookBlock behavior execution function
64+
*
65+
* Deactivates all inputs, invokes the registered callback (if any),
66+
* then activates all outputs. The callback can control the return value.
67+
*
68+
* @param behcontext The behavior context containing execution state
69+
* @return CKBR_OK on success, or callback-defined return value
70+
*/
71+
int HookBlock(const CKBehaviorContext &behcontext) {
72+
CKBehavior *beh = behcontext.Behavior;
73+
74+
// Deactivate all inputs
75+
int i, count = beh->GetInputCount();
76+
for (i = 0; i < count; ++i) {
77+
beh->ActivateInput(i, FALSE);
78+
}
79+
80+
// Invoke registered callback
81+
int ret = CKBR_OK;
82+
CKBehaviorCallback cb = nullptr;
83+
beh->GetLocalParameterValue(0, &cb);
84+
if (cb) {
85+
void *arg = nullptr;
86+
beh->GetLocalParameterValue(1, &arg);
87+
ret = cb(&behcontext, arg);
88+
}
89+
90+
// Activate all outputs
91+
count = beh->GetOutputCount();
92+
for (i = 0; i < count; ++i) {
93+
beh->ActivateOutput(i);
94+
}
95+
96+
return ret;
97+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @file HookBlock.h
3+
* @brief Header for HookBlock behavior
4+
*/
5+
6+
#ifndef BML_MODLOADER_HOOKBLOCK_H
7+
#define BML_MODLOADER_HOOKBLOCK_H
8+
9+
#include "CKAll.h"
10+
11+
namespace ModLoader {
12+
13+
/// Callback function type for HookBlock
14+
typedef int (*CKBehaviorCallback)(const CKBehaviorContext *behcontext, void *arg);
15+
16+
/// Register HookBlock behavior with the engine
17+
CKObjectDeclaration *FillBehaviorHookBlockDecl();
18+
19+
/// Create HookBlock prototype
20+
CKERROR CreateHookBlockProto(CKBehaviorPrototype **pproto);
21+
22+
/// HookBlock execution function
23+
int HookBlock(const CKBehaviorContext &behcontext);
24+
25+
} // namespace ModLoader
26+
27+
#endif // BML_MODLOADER_HOOKBLOCK_H

src/ModLoader/CMakeLists.txt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# ModLoader - Game Engine Integration Layer
2+
# Provides CK2 Manager, core hooks, and Virtools plugin entry points
3+
4+
set(MODLOADER_SOURCES
5+
Entry.cpp
6+
ModManager.cpp
7+
Behaviors/HookBlock.cpp
8+
)
9+
10+
set(MODLOADER_HEADERS
11+
ModManager.h
12+
Behaviors/HookBlock.h
13+
)
14+
15+
add_library(ModLoader SHARED
16+
${MODLOADER_SOURCES}
17+
${MODLOADER_HEADERS}
18+
)
19+
20+
target_include_directories(ModLoader
21+
PUBLIC
22+
$<BUILD_INTERFACE:${BML_INCLUDE_DIR}>
23+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
24+
PRIVATE
25+
${CMAKE_CURRENT_SOURCE_DIR}
26+
)
27+
28+
target_link_libraries(ModLoader
29+
PUBLIC
30+
CK2 VxMath
31+
PRIVATE
32+
minhook
33+
)
34+
35+
target_compile_definitions(ModLoader PRIVATE
36+
MODLOADER_EXPORTS
37+
)
38+
39+
set_target_properties(ModLoader PROPERTIES
40+
OUTPUT_NAME "ModLoader"
41+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
42+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
43+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
44+
)
45+
46+
# Install targets
47+
install(TARGETS ModLoader
48+
EXPORT ModLoaderTargets
49+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
50+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
51+
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
52+
)

0 commit comments

Comments
 (0)