1#![allow(dead_code)]
2
3extern crate warpack_stock_data as w3data;
4extern crate ceres_mpq as mpq;
5
6use std::error::Error;
7use std::fs;
8use std::path::PathBuf;
9use std::rc::Rc;
10
11use rlua::prelude::*;
12
13use crate::error::ContextError;
14use crate::evloop::wait_on_evloop;
15
16pub(crate) mod lua;
17pub(crate) mod error;
18pub(crate) mod compiler;
19pub(crate) mod evloop;
20
21#[derive(Copy, Clone)]
22pub enum WarpackRunMode {
23 Build,
24 RunMap,
25 LiveReload,
26}
27
28pub fn lua_error_root_cause(error: &LuaError) -> anyhow::Error {
29 match error {
30 LuaError::CallbackError { traceback, cause } => {
31 anyhow::anyhow!("{}\n{}", lua_error_root_cause(cause), traceback)
32 }
33 LuaError::ExternalError(external) => {
34 if let Some(error) = <dyn Error>::downcast_ref::<LuaError>(external.as_ref()) {
35 lua_error_root_cause(error)
36 } else {
37 anyhow::anyhow!("{}", external)
38 }
39 }
40 other => anyhow::anyhow!("{}", other),
41 }
42}
43
44pub fn handle_lua_result(result: anyhow::Result<()>) {
45 if let Err(err) = result {
46 match err.downcast::<LuaError>() {
47 Ok(err) => {
48 println!("{}", lua_error_root_cause(&err));
49 }
50 Err(err) => println!("{}", err),
51 }
52 }
53}
54
55pub fn execute_script<F>(
56 run_mode: WarpackRunMode,
57 script_args: Vec<&str>,
58 action: F,
59) -> Result<(), anyhow::Error>
60where
61 F: FnOnce(LuaContext) -> Result<(), anyhow::Error>,
62{
63 const DEFAULT_BUILD_SCRIPT: &str = include_str!("resource/buildscript_default.lua");
64
65 let lua = Rc::new(Lua::new());
66
67 let result: Result<(), anyhow::Error> = lua.context(|ctx| {
68 lua::setup_ceres_environ(
69 ctx,
70 run_mode,
71 script_args.into_iter().map(|s| s.into()).collect(),
72 );
73
74 action(ctx)?;
75
76 Ok(())
77 });
78
79 if result.is_err() {
80 handle_lua_result(result);
81 std::process::exit(1);
82 }
83
84 wait_on_evloop(Rc::clone(&lua));
85
86 Ok(())
87}
88
89pub fn run_build_script(
90 run_mode: WarpackRunMode,
91 project_dir: PathBuf,
92 script_args: Vec<&str>,
93) -> Result<(), anyhow::Error> {
94 const DEFAULT_BUILD_SCRIPT: &str = include_str!("resource/buildscript_default.lua");
95
96 let build_script_path = project_dir.join("build.lua");
97
98 let build_script = if build_script_path.is_file() {
99 Some(
100 fs::read_to_string(&build_script_path)
101 .map_err(|cause| ContextError::new("Could not read custom build script", cause))?,
102 )
103 } else {
104 None
105 };
106
107 execute_script(run_mode, script_args, |ctx| {
108 if let Some(build_script) = build_script {
109 ctx.load(&build_script)
110 .set_name("custom build script")
111 .unwrap()
112 .exec()?;
113 }
114
115 ctx.load(DEFAULT_BUILD_SCRIPT)
116 .set_name("buildscript_default.lua")
117 .unwrap()
118 .exec()?;
119
120 Ok(())
121 })
122}