Skip to content

Commit d2de819

Browse files
authored
Merge pull request #636 from kang-sw/fix/629-hot-reload-servers-api
Fix: Ensure class servers methods are loaded after hot reload
2 parents ef563c3 + 30c0f23 commit d2de819

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

godot-core/src/init/mod.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8+
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
9+
810
use godot_ffi as sys;
911

1012
use sys::GodotFfi;
@@ -53,17 +55,38 @@ pub unsafe fn __gdext_load_library<E: ExtensionLibrary>(
5355
is_success.unwrap_or(0)
5456
}
5557

58+
static LEVEL_SERVERS_CORE_LOADED: AtomicBool = AtomicBool::new(false);
59+
5660
unsafe extern "C" fn ffi_initialize_layer<E: ExtensionLibrary>(
5761
_userdata: *mut std::ffi::c_void,
5862
init_level: sys::GDExtensionInitializationLevel,
5963
) {
6064
let level = InitLevel::from_sys(init_level);
6165
let ctx = || format!("failed to initialize GDExtension level `{:?}`", level);
6266

63-
// Swallow panics. TODO consider crashing if gdext init fails.
64-
let _ = crate::private::handle_panic(ctx, || {
67+
fn try_load<E: ExtensionLibrary>(level: InitLevel) {
68+
// Workaround for https://github.com/godot-rust/gdext/issues/629:
69+
// When using editor plugins, Godot may unload all levels but only reload from Scene upward.
70+
// Manually run initialization of lower levels.
71+
72+
// TODO: Remove this workaround once after the upstream issue is resolved.
73+
if level == InitLevel::Scene {
74+
if !LEVEL_SERVERS_CORE_LOADED.load(Relaxed) {
75+
try_load::<E>(InitLevel::Core);
76+
try_load::<E>(InitLevel::Servers);
77+
}
78+
} else if level == InitLevel::Core {
79+
// When it's normal initialization, the `Servers` level is normally initialized.
80+
LEVEL_SERVERS_CORE_LOADED.store(true, Relaxed);
81+
}
82+
6583
gdext_on_level_init(level);
6684
E::on_level_init(level);
85+
}
86+
87+
// Swallow panics. TODO consider crashing if gdext init fails.
88+
let _ = crate::private::handle_panic(ctx, || {
89+
try_load::<E>(level);
6790
});
6891
}
6992

@@ -76,6 +99,11 @@ unsafe extern "C" fn ffi_deinitialize_layer<E: ExtensionLibrary>(
7699

77100
// Swallow panics.
78101
let _ = crate::private::handle_panic(ctx, || {
102+
if level == InitLevel::Core {
103+
// Once the CORE api is unloaded, reset the flag to initial state.
104+
LEVEL_SERVERS_CORE_LOADED.store(false, Relaxed);
105+
}
106+
79107
E::on_level_deinit(level);
80108
gdext_on_level_deinit(level);
81109
});

0 commit comments

Comments
 (0)