Skip to main content

rblx_godot/instance/
data_model.rs

1use r2g_mlua::prelude::*;
2
3use crate::core::FastFlags;
4use crate::core::{get_state, inheritance_cast_to, FastFlag, InheritanceBase, InheritanceTable, InheritanceTableBuilder, Irc, 
5    ParallelDispatch::Synchronized, RwLock, RwLockReadGuard, RwLockWriteGuard};
6use crate::core::lua_macros::{lua_getter, lua_invalid_argument};
7use crate::userdata::{ManagedRBXScriptSignal, RBXScriptSignal};
8
9use super::{IInstanceComponent, DynInstance, IInstance, IObject, IServiceProvider, InstanceComponent, ManagedInstance, ServiceProviderComponent, WeakManagedInstance};
10
11#[derive(Debug)]
12pub struct DataModelComponent {
13    bind_close: ManagedRBXScriptSignal,
14    workspace: (), //todo!
15
16    pub graphics_quality_change_request: ManagedRBXScriptSignal,
17    pub loaded: ManagedRBXScriptSignal,
18    is_loaded: bool
19
20}
21
22#[derive(Debug)]
23pub struct DataModel {
24    instance: RwLock<InstanceComponent>,
25    service_provider: RwLock<ServiceProviderComponent>,
26    data_model: RwLock<DataModelComponent>
27}
28
29pub trait IDataModel {
30    fn get_data_model_component(&self) -> RwLockReadGuard<'_,DataModelComponent>;
31    fn get_data_model_component_mut(&self) -> RwLockWriteGuard<'_,DataModelComponent>;
32}
33
34impl InheritanceBase for DataModel {
35    fn inheritance_table(&self) -> InheritanceTable {
36        InheritanceTableBuilder::new()
37            .insert_type::<DataModel, dyn IObject>(|x| x, |x| x)
38            .insert_type::<DataModel, DynInstance>(|x| x, |x| x)
39            .insert_type::<DataModel, dyn IServiceProvider>(|x| x, |x| x)
40            .insert_type::<DataModel, dyn IDataModel>(|x| x, |x| x)
41            .output()
42    }
43}
44
45impl IObject for DataModel {
46    fn lua_get(&self, lua: &Lua, name: String) -> LuaResult<LuaValue> {
47        self.data_model.read().unwrap().lua_get(self, lua, &name)
48            .or_else(|| self.service_provider.read().unwrap().lua_get(self, lua, &name))
49            .unwrap_or_else(|| self.instance.read().unwrap().lua_get(lua, &name))
50    }
51
52    fn get_class_name(&self) -> &'static str { "DataModel" }
53
54    fn get_property_changed_signal(&self, property: String) -> ManagedRBXScriptSignal {
55        self.get_instance_component().get_property_changed_signal(property).unwrap()
56    }
57
58    fn is_a(&self, class_name: &String) -> bool {
59        match class_name.as_str() {
60            "DataModel" => true,
61            "ServiceProvider" => true,
62            "Instance" => true,
63            "Object" => true,
64            _ => false
65        }
66    }
67
68    fn get_changed_signal(&self) -> ManagedRBXScriptSignal {
69        self.get_instance_component().changed.clone()
70    }
71}
72
73impl IInstance for DataModel {
74    fn get_instance_component(&self) -> RwLockReadGuard<InstanceComponent> {
75        self.instance.read().unwrap()
76    }
77
78    fn get_instance_component_mut(&self) -> RwLockWriteGuard<InstanceComponent> {
79        self.instance.write().unwrap()
80    }
81
82    fn lua_set(&self, lua: &Lua, name: String, val: LuaValue) -> LuaResult<()> {
83        self.data_model.write().unwrap().lua_set(self, lua, &name, &val)
84            .or_else(|| self.service_provider.write().unwrap().lua_set(self, lua, &name, &val))
85            .unwrap_or_else(|| self.instance.write().unwrap().lua_set(lua, &name, val))
86    }
87
88    fn clone_instance(&self, _: &Lua) -> LuaResult<ManagedInstance> {
89        Err(LuaError::RuntimeError("DataModel cannot be cloned".into()))
90    }
91}
92
93impl IServiceProvider for DataModel {
94    fn get_service_provider_component(&self) -> RwLockReadGuard<ServiceProviderComponent> {
95        self.service_provider.read().unwrap()
96    }
97
98    fn get_service_provider_component_mut(&self) -> RwLockWriteGuard<ServiceProviderComponent> {
99        self.service_provider.write().unwrap()
100    }
101
102    fn get_service(&self, service_name: String) -> LuaResult<ManagedInstance> {
103        self.find_service(service_name)
104            .and_then(|x|
105                x.ok_or_else(|| LuaError::RuntimeError("Service not found".into()))
106            )
107    }
108
109    fn find_service(&self, service_name: String) -> LuaResult<Option<ManagedInstance>> {
110        DynInstance::find_first_child_of_class(self, service_name)
111    }
112}
113
114impl DataModel {
115    pub fn new(flags: &FastFlags) -> ManagedInstance {
116        let game: Irc<DynInstance> = Irc::new_cyclic(|x|
117            DataModel {
118                instance: RwLock::new_with_flag_auto(InstanceComponent::new(x.cast_to_instance(), "DataModel")),
119                service_provider: RwLock::new_with_flag_auto(ServiceProviderComponent::new(x.cast_to_instance(), "DataModel")),
120                data_model: RwLock::new_with_flag_auto(DataModelComponent::new(x.cast_to_instance(), "DataModel"))
121        }).cast_from_sized().unwrap();
122        game.set_name(flags.get_string(FastFlag::GameName)).unwrap();
123        game.lock_parent();
124        game
125    }
126}
127
128impl IInstanceComponent for DataModelComponent {
129    fn lua_get(self: &mut RwLockReadGuard<'_, Self>, _ptr: &DynInstance, lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>> {
130        match key.as_str() {
131            "CreatorId" => Some(lua_getter!(lua, get_state(lua).flags().get_int(FastFlag::CreatorId))),
132            "CreatorType" => todo!(),
133            "GameId" => Some(lua_getter!(lua, get_state(lua).flags().get_int(FastFlag::GameId))),
134            "JobId" => Some(lua_getter!(lua, get_state(lua).flags().get_string(FastFlag::JobId))),
135            "PlaceId" => Some(lua_getter!(lua, get_state(lua).flags().get_int(FastFlag::PlaceId))),
136            "PlaceVersion" => Some(lua_getter!(lua, get_state(lua).flags().get_int(FastFlag::PlaceVersion))),
137            "PrivateServerId" => Some(lua_getter!(lua, get_state(lua).flags().get_string(FastFlag::PrivateServerId))),
138            "PrivateServerOwnerId" => Some(lua_getter!(lua, get_state(lua).flags().get_int(FastFlag::PrivateServerOwnerId))),
139            "Workspace" => todo!(),
140            "BindToClose" => lua_getter!(function_opt, lua, |lua, (this, func): (ManagedInstance, LuaFunction)| {
141                inheritance_cast_to!(&*this, dyn IDataModel)
142                    .map_err(|_|
143                        lua_invalid_argument!("DataModel::BindToClose",1,self cast Instance to DataModel)
144                    )
145                    .and_then(|x|
146                        x.bind_to_close(lua, func)
147                    )
148            }),
149            "IsLoaded" => Some(Ok(LuaValue::Boolean(true))),
150            "GraphicsQualityChangeRequest" => Some(lua_getter!(clone, lua, self.graphics_quality_change_request)),
151            "Loaded" => Some(lua_getter!(clone, lua, self.loaded)),
152            _ => None
153        }
154    }
155
156    fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, _ptr: &DynInstance, _lua: &Lua, key: &String, _value: &LuaValue) -> Option<LuaResult<()>> {
157        match key.as_str() {
158            "CreatorId" |
159            "CreatorType" |
160            "GameId" |
161            "JobId" |
162            "PlaceId" |
163            "PlaceVersion" |
164            "PrivateServerId" |
165            "PrivateServerOwnerId" |
166            "Workspace "=> Some(Err(LuaError::RuntimeError("Cannot set read only property.".into()))),
167            _ => None
168        }
169    }
170
171    fn clone(self: &RwLockReadGuard<'_, Self>, _: &Lua, _: &WeakManagedInstance) -> LuaResult<Self> {
172        Err(LuaError::RuntimeError("Cannot clone DataModelComponent".into()))
173    }
174
175    fn new(_ptr: WeakManagedInstance, _class_name: &'static str) -> Self {
176        Self {
177            bind_close: RBXScriptSignal::new(),
178            workspace: (),
179            graphics_quality_change_request: RBXScriptSignal::new(),
180            loaded: RBXScriptSignal::new(),
181            is_loaded: false
182        }
183    }
184}
185
186impl IDataModel for DataModel {
187    fn get_data_model_component(&self) -> RwLockReadGuard<'_,DataModelComponent> {
188        self.data_model.read().unwrap()
189    }
190
191    fn get_data_model_component_mut(&self) -> RwLockWriteGuard<'_,DataModelComponent> {
192        self.data_model.write().unwrap()
193    }
194}
195impl dyn IDataModel {
196    pub fn bind_to_close(&self, lua: &Lua, func: LuaFunction) -> LuaResult<()> {
197        let read = self.get_data_model_component();
198        read.bind_close.write().once(lua, func, Synchronized)?;
199        Ok(())
200    }
201    pub fn is_loaded(&self) -> bool { 
202        self.get_data_model_component().is_loaded
203    }
204    pub fn fire_loaded(&self, lua: &Lua) -> LuaResult<()> {
205        let mut write = self.get_data_model_component_mut();
206        write.is_loaded = true;
207        write.loaded.write().fire(lua, ())
208    }
209}