11use std:: any:: TypeId ;
2+ use std:: cell:: RefCell ;
23use std:: fmt:: Debug ;
4+ use std:: path:: PathBuf ;
5+ use std:: rc:: Rc ;
36use std:: sync:: mpsc;
7+ use std:: { fs, io} ;
48
59use egui:: { Align2 , Color32 , Context , FontId , Key , Rounding , Sense , TextEdit , Vec2 , Window } ;
610use flexi_logger:: { Cleanup , Criterion , FileSpec , LogSpecification , Logger , Naming , WriteMode } ;
711use heck:: ToSnakeCase ;
812use rhai:: plugin:: CallableFunction ;
9- use rhai:: { Dynamic , Engine , FnAccess , FnNamespace , Module , RegisterNativeFunction , Scope } ;
13+ use rhai:: * ;
1014
1115use crate :: { elex, handlers} ;
1216
@@ -18,6 +22,7 @@ pub struct ScriptHost {
1822 is_active : bool ,
1923 engine : Engine ,
2024 scope : Scope < ' static > ,
25+ mods : Vec < Mod > ,
2126}
2227
2328impl Default for ScriptHost {
@@ -40,6 +45,7 @@ impl Default for ScriptHost {
4045 is_active : false ,
4146 engine,
4247 scope : Scope :: new ( ) ,
48+ mods : vec ! [ ] ,
4349 }
4450 }
4551}
@@ -64,6 +70,14 @@ impl ScriptHost {
6470 }
6571 }
6672
73+ fn process_frame ( & mut self ) {
74+ for mod_ in & mut self . mods {
75+ let _res: Result < ( ) , _ > = self
76+ . engine
77+ . call_fn ( & mut mod_. scope , & mod_. ast , "on_frame" , vec ! [ mod_. state. clone( ) ] ) ;
78+ }
79+ }
80+
6781 pub fn toggle ( & mut self ) {
6882 self . is_active = !self . is_active ;
6983 }
@@ -103,11 +117,54 @@ impl ScriptHost {
103117 ) ;
104118 module
105119 }
120+
121+ fn verify_version ( ) -> bool {
122+ const SUPPORTED_VERSION_TS : u32 = 1647620648 ;
123+ let found_version = elex:: check_version ( ) ;
124+
125+ if found_version == SUPPORTED_VERSION_TS {
126+ log:: info!( "C.R.O.N.Y successfully initialized!" ) ;
127+ true
128+ } else {
129+ log:: error!( "Unsupported game version ({found_version}), exiting!" ) ;
130+ false
131+ }
132+ }
133+
134+ fn load_mods ( & mut self ) -> Result < ( ) , io:: Error > {
135+ let dir = std:: env:: current_exe ( ) ?
136+ . parent ( )
137+ . expect ( "no exe parent" )
138+ . join ( "plugins" )
139+ . join ( "crony" ) ;
140+ for entry in fs:: read_dir ( dir) ? {
141+ let entry = entry?;
142+ if entry. file_type ( ) ?. is_dir ( ) {
143+ let main = entry. path ( ) . join ( "main.rhai" ) ;
144+ if main. exists ( ) {
145+ match self . init_mod ( main. clone ( ) ) {
146+ Ok ( ( ) ) => log:: info!( "Successfully loaded {}" , main. display( ) ) ,
147+ Err ( err) => log:: info!( "Failed to initilize {}: {}" , main. display( ) , err) ,
148+ }
149+ }
150+ }
151+ }
152+
153+ Ok ( ( ) )
154+ }
155+
156+ fn init_mod ( & mut self , path : PathBuf ) -> Result < ( ) , Box < EvalAltResult > > {
157+ let ast = self . engine . compile_file ( path) ?;
158+ let mut scope = Scope :: new ( ) ;
159+ let state = self . engine . call_fn ( & mut scope, & ast, "initial_state" , ( ) ) ?;
160+ self . mods . push ( Mod :: new ( ast, scope, state) ) ;
161+ Ok ( ( ) )
162+ }
106163}
107164
108165impl egui_hook:: App for ScriptHost {
109166 fn render ( & mut self , ctx : & Context ) {
110- const DEFAULT_SIZE : Vec2 = Vec2 :: new ( 600. , 320. ) ;
167+ self . process_frame ( ) ;
111168
112169 let was_active = self . is_active ( ) ;
113170 if ctx. input ( ) . key_pressed ( Key :: Home ) {
@@ -117,6 +174,8 @@ impl egui_hook::App for ScriptHost {
117174 return ;
118175 }
119176
177+ const DEFAULT_SIZE : Vec2 = Vec2 :: new ( 600. , 320. ) ;
178+
120179 Window :: new ( "CRONY GUI" )
121180 . default_size ( DEFAULT_SIZE )
122181 . show ( ctx, |ui| {
@@ -165,15 +224,29 @@ impl egui_hook::App for ScriptHost {
165224 . start ( )
166225 . ok ( ) ;
167226
168- const SUPPORTED_VERSION_TS : u32 = 1647620648 ;
169- let found_version = elex :: check_version ( ) ;
227+ Self :: verify_version ( )
228+ }
170229
171- if found_version == SUPPORTED_VERSION_TS {
172- log:: info!( "C.R.O.N.Y successfully initialized!" ) ;
173- true
174- } else {
175- log:: error!( "Unsupported game version ({found_version}), exiting!" ) ;
176- false
230+ fn setup ( & mut self , _ctx : & Context ) {
231+ if let Err ( err) = self . load_mods ( ) {
232+ log:: warn!( "Failed to load mods: {err}" )
233+ }
234+ }
235+ }
236+
237+ #[ derive( Debug ) ]
238+ struct Mod {
239+ ast : AST ,
240+ scope : Scope < ' static > ,
241+ state : Rc < RefCell < Dynamic > > ,
242+ }
243+
244+ impl Mod {
245+ fn new ( ast : AST , scope : Scope < ' static > , state : Dynamic ) -> Self {
246+ Self {
247+ ast,
248+ scope,
249+ state : Rc :: new ( RefCell :: new ( state) ) ,
177250 }
178251 }
179252}
0 commit comments