1mod transform;
2
3pub trait Plugin: Send + Sync {
4 fn new() -> Self
5 where
6 Self: Sized;
7
8 fn update(&mut self);
9
10 fn handle_server_data(&mut self, _data: Vec<u8>) {}
11
12 fn set_update_frequency(&mut self) -> Option<f32> {
13 None
14 }
15}
16
17#[macro_export]
18macro_rules! register_plugin {
19 ($plugin_type:ty) => {
20 #[export_name = "init-plugin"]
21 pub extern "C" fn __init_plugin() {
22 fmc_client_api::register_plugin(|| {
23 Box::new(<$plugin_type as fmc_client_api::Plugin>::new())
24 });
25 }
26 };
27}
28
29static mut PLUGIN: Option<Box<dyn Plugin>> = None;
30
31#[doc(hidden)]
32pub fn register_plugin(build_plugin: fn() -> Box<dyn Plugin>) {
33 unsafe { PLUGIN = Some((build_plugin)()) }
34}
35
36fn plugin() -> &'static mut dyn Plugin {
37 unsafe { PLUGIN.as_deref_mut().unwrap() }
38}
39
40mod wit {
41 use std::hash::{Hash, Hasher};
42
43 wit_bindgen::generate!({
44 skip: ["init-plugin"],
45 path: "./src/api.wit",
46 with: {
47 "fmc:api/math": crate::math,
48 "fmc:api/transform": crate::transform
49 },
50 });
51
52 impl Hash for Key {
53 fn hash<H: Hasher>(&self, state: &mut H) {
54 let discriminant = std::mem::discriminant(self);
55 core::hash::Hash::hash(&discriminant, state);
56 }
57 }
58}
59
60pub use wit::{
61 delta_time, get_block, get_block_aabb, get_block_friction, get_block_name,
62 get_camera_transform, get_model_aabb, get_models, get_player_transform, keyboard_input, log,
63 set_camera_transform, set_player_transform, Friction, Key, KeyboardKey, SurfaceFriction,
64};
65
66pub mod math {
67 pub use glam::*;
68}
69
70pub mod prelude {
71 pub use crate::math::{DQuat, IVec3, Quat, Vec3};
72 pub use crate::transform::Transform;
73}
74
75wit::export!(Component with_types_in wit);
76
77struct Component;
78
79impl wit::Guest for Component {
80 fn set_update_frequency() -> Option<f32> {
81 plugin().set_update_frequency()
82 }
83
84 fn update() {
85 plugin().update()
86 }
87
88 fn handle_server_data(data: Vec<u8>) {
89 plugin().handle_server_data(data)
90 }
91}