1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
pub use ambient_api_core as api;
pub use api::{core, message::*};

use std::future::Future;
pub fn run_async(_world: &ecs::World, future: impl Future<Output = ()> + Send + 'static) {
    api::prelude::run_async(async {
        future.await;
        api::prelude::OkEmpty
    });
}

/// Execute a future to completion on a worker thread.
///
/// This permits spawning thread local futures
pub fn run_async_local<F>(_world: &ecs::World, create: impl 'static + Send + FnOnce() -> F)
where
    F: 'static + Future,
    F::Output: Send + 'static,
{
    api::prelude::run_async(async {
        let future = create();
        future.await;
        api::prelude::OkEmpty
    });
}

pub async fn sleep(seconds: f32) {
    api::prelude::sleep(seconds).await;
}

pub fn broadcast_local_message(_world: &mut ecs::World, message: impl ModuleMessage) {
    message.send_local_broadcast(true);
}

pub mod ecs {
    use super::api;
    pub use api::{
        ecs::{Component, SupportedValue as ComponentValue, UntypedComponent},
        prelude::{Entity, EntityId},
    };

    #[derive(Clone, Copy)]
    pub struct World;
    impl World {
        pub fn spawn(&self, entity: Entity) -> EntityId {
            api::entity::spawn(&entity)
        }
        pub fn despawn(&self, entity_id: EntityId) -> Option<Entity> {
            api::entity::despawn(entity_id)
        }
        pub fn exists(&self, entity_id: EntityId) -> bool {
            api::entity::exists(entity_id)
        }
        pub fn set<T: ComponentValue>(
            &self,
            entity_id: EntityId,
            component: Component<T>,
            value: T,
        ) -> Result<(), ECSError> {
            // TODO: set_component needs to return errors
            api::entity::set_component(entity_id, component, value);
            Ok(())
        }
        pub fn add_component<T: ComponentValue>(
            &self,
            entity_id: EntityId,
            component: Component<T>,
            value: T,
        ) -> Result<(), ECSError> {
            // TODO: add_component needs to return errors
            api::entity::add_component(entity_id, component, value);
            Ok(())
        }
        pub fn add_components(
            &self,
            entity_id: EntityId,
            components: Entity,
        ) -> Result<(), ECSError> {
            // TODO: add_components needs to return errors
            api::entity::add_components(entity_id, components);
            Ok(())
        }
        pub fn get<T: ComponentValue>(
            &self,
            entity_id: EntityId,
            component: Component<T>,
        ) -> Result<T, ECSError> {
            api::entity::get_component(entity_id, component)
                .ok_or_else(|| ECSError::EntityDoesntHaveComponent)
        }
        pub fn get_cloned<T: ComponentValue>(
            &self,
            entity_id: EntityId,
            component: Component<T>,
        ) -> Result<T, ECSError> {
            self.get(entity_id, component)
        }
        pub fn has_component<T: ComponentValue>(
            &self,
            entity_id: EntityId,
            component: Component<T>,
        ) -> bool {
            api::entity::has_component(entity_id, component)
        }
        pub fn resource<T: ComponentValue>(&self, component: Component<T>) -> T {
            api::entity::get_component(api::entity::resources(), component).unwrap()
        }
    }
    #[derive(Debug)]
    pub enum ECSError {
        EntityDoesntHaveComponent,
        NoSuchEntity,
    }

    pub struct ComponentDesc(Box<dyn UntypedComponent>);
    impl ComponentDesc {
        pub fn index(&self) -> u32 {
            self.0.index()
        }
    }
    impl<T: 'static> From<Component<T>> for ComponentDesc {
        fn from(value: Component<T>) -> Self {
            Self(Box::new(value))
        }
    }
}

pub mod window {
    use ambient_shared_types::CursorIcon;

    pub fn set_cursor(_world: &crate::ecs::World, cursor: CursorIcon) {
        #[cfg(feature = "client")]
        super::api::client::input::set_cursor(cursor);
        #[cfg(not(feature = "client"))]
        let _ = cursor;
    }
    pub async fn get_clipboard() -> Option<String> {
        #[cfg(feature = "client")]
        return super::api::client::clipboard::get().await;
        #[cfg(not(feature = "client"))]
        return None;
    }

    pub async fn set_clipboard(text: &str) -> anyhow::Result<()> {
        #[cfg(feature = "client")]
        super::api::client::clipboard::set(text);
        #[cfg(not(feature = "client"))]
        let _ = text;

        Ok(())
    }
}