Skip to content

Commit 284353a

Browse files
committed
Refactors and move lua stdlib
- Moved lua stdlib from the rust autorun-env package to be a standalone plugin. - To do this reliably, added plugin "ordering" field which can allow a plugin to specify the ordering it desires, lower number means higher priority / starts first. Higher number starts later. Plugins are sorted by this before being run. - Added Autorun.load() which is the equivalent of lua's loadstring() or gmod's CompileString, except it is also available on the menu. - Implement FromLua for Option<FromLua> - Simplify loadbuffer and pcall internals
1 parent 3c826aa commit 284353a

File tree

15 files changed

+146
-87
lines changed

15 files changed

+146
-87
lines changed

packages/autorun-core/src/plugins.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,13 @@ pub struct Plugin {
88
/// Directory for mutable data.
99
data_dir: Dir,
1010

11-
config: std::sync::OnceLock<Config>,
11+
config: Config,
1212
}
1313

1414
impl core::fmt::Display for Plugin {
1515
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16-
match self.get_config() {
17-
Ok(cfg) => write!(f, "{} v{} by {}", cfg.plugin.name, cfg.plugin.version, cfg.plugin.author),
18-
Err(_) => write!(f, "Invalid Plugin"),
19-
}
16+
let cfg = &self.config;
17+
write!(f, "{} v{} by {}", cfg.plugin.name, cfg.plugin.version, cfg.plugin.author)
2018
}
2119
}
2220

@@ -48,28 +46,28 @@ impl Plugin {
4846
self.src()?.open_dir("menu")
4947
}
5048

49+
pub fn shared(&self) -> std::io::Result<Dir> {
50+
self.src()?.open_dir("shared")
51+
}
52+
5153
pub fn try_clone(&self) -> std::io::Result<Self> {
5254
Ok(Self {
5355
dir: self.dir.try_clone()?,
5456
data_dir: self.data_dir.try_clone()?,
55-
config: std::sync::OnceLock::new(),
57+
config: self.config.clone(),
5658
})
5759
}
5860

5961
pub fn read_client_init(&self) -> std::io::Result<Vec<u8>> {
6062
self.client()?.read(Self::INIT_FILE)
6163
}
6264

63-
pub fn client_exists(&self) -> std::io::Result<bool> {
64-
self.client()?.try_exists(Self::INIT_FILE)
65-
}
66-
6765
pub fn read_menu_init(&self) -> std::io::Result<Vec<u8>> {
68-
self.menu()?.read("init.lua")
66+
self.menu()?.read(Self::INIT_FILE)
6967
}
7068

71-
pub fn menu_exists(&self) -> std::io::Result<bool> {
72-
self.menu()?.try_exists(Self::INIT_FILE)
69+
pub fn read_shared_init(&self) -> std::io::Result<Vec<u8>> {
70+
self.shared()?.read(Self::INIT_FILE)
7371
}
7472

7573
pub fn from_dir(dir: Dir) -> anyhow::Result<Self> {
@@ -85,34 +83,26 @@ impl Plugin {
8583
}
8684
};
8785

88-
Ok(Self {
89-
dir,
90-
data_dir,
91-
config: std::sync::OnceLock::new(),
92-
})
93-
}
94-
95-
pub fn get_config(&self) -> anyhow::Result<&Config> {
96-
if let Some(cfg) = self.config.get() {
97-
return Ok(cfg);
98-
}
99-
100-
let config_data = self.dir.read_to_string(Self::PLUGIN_CONFIG)?;
86+
let config_data = dir.read_to_string(Self::PLUGIN_CONFIG)?;
10187
let config: Config = toml::from_str(&config_data)?;
102-
self.config.set(config).expect("Shouldn't be set");
10388

104-
Ok(self.config.get().expect("Should be set"))
89+
Ok(Self { dir, data_dir, config })
90+
}
91+
92+
pub fn config(&self) -> &Config {
93+
&self.config
10594
}
10695
}
10796

10897
nestify::nest! {
109-
#[derive(Debug, Serialize, Deserialize)]*
98+
#[derive(Debug, Clone, Serialize, Deserialize)]*
11099
pub struct Config {
111100
pub plugin: pub struct ConfigPlugin {
112101
pub name: String,
113102
pub author: String,
114103
pub version: String,
115104
pub description: String,
105+
pub ordering: Option<u32>,
116106

117107
pub language: #[serde(rename_all = "lowercase")] #[non_exhaustive] pub enum ConfigPluginLanguage {
118108
Lua,

packages/autorun-env/api.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,28 @@
277277
"description": "The original function that was detoured"
278278
}
279279
]
280+
},
281+
{
282+
"name": "load",
283+
"description": "Compiles a Lua string into a callable function without executing it. Similar to Lua's loadstring/load function. Use this to dynamically compile code at runtime. NOTE: The environment inside defaults to the global environment, NOT Autorun's environment.",
284+
"realm": "shared",
285+
"parameters": [
286+
{
287+
"name": "code",
288+
"type": "string",
289+
"description": "The Lua code to compile"
290+
}
291+
],
292+
"returns": [
293+
{
294+
"type": "function?",
295+
"description": "The compiled function, or nil if compilation failed"
296+
},
297+
{
298+
"type": "string?",
299+
"description": "Error message if compilation failed"
300+
}
301+
]
280302
}
281303
]
282304
}

packages/autorun-env/src/env.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ impl EnvHandle {
122122
lua.push(state, as_env_lua_function!(crate::functions::detour_get_original));
123123
lua.set_table(state, -3);
124124

125+
lua.push(state, c"load");
126+
lua.push(state, as_env_lua_function!(crate::functions::load));
127+
lua.set_table(state, -3);
128+
125129
lua.push(state, c"VERSION");
126130
lua.push(state, env!("CARGO_PKG_VERSION").to_string());
127131
lua.set_table(state, -3);
@@ -158,15 +162,7 @@ impl EnvHandle {
158162

159163
// Can unwrap since we are sure there is something on the stack
160164
let handle = RawHandle::from_stack(lua, state).unwrap();
161-
162-
// Create lua standard library
163-
let this = Self(handle);
164-
this.execute(lua, state, c"@stdlib", include_bytes!("./lua/builtins.lua"))?;
165-
this.execute(lua, state, c"@stdlib", include_bytes!("./lua/include.lua"))?;
166-
this.execute(lua, state, c"@stdlib", include_bytes!("./lua/require.lua"))?;
167-
this.execute(lua, state, c"@stdlib", include_bytes!("./lua/event.lua"))?;
168-
169-
Ok(this)
165+
Ok(Self(handle))
170166
}
171167

172168
fn push_autorun_table(&self, lua: &LuaApi, state: *mut LuaState) {

packages/autorun-env/src/functions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ pub use append::*;
1818

1919
mod detour;
2020
pub use detour::*;
21+
22+
mod load;
23+
pub use load::*;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use autorun_lua::{LuaApi, RawLuaReturn};
2+
use autorun_types::LuaState;
3+
4+
pub fn load(lua: &LuaApi, state: *mut LuaState, _env: crate::EnvHandle) -> anyhow::Result<RawLuaReturn> {
5+
let source = lua.check_string(state, 1);
6+
let chunk_name = lua.to::<Option<&[u8]>>(state, 2).unwrap_or(b"loadstring");
7+
let chunk_name = std::ffi::CString::new(chunk_name)?;
8+
9+
if let Err(why) = lua.load_buffer_x(state, source.as_bytes(), &chunk_name, c"t") {
10+
lua.push_nil(state);
11+
lua.push(state, &why);
12+
return Ok(RawLuaReturn(2));
13+
}
14+
15+
Ok(RawLuaReturn(1))
16+
}

packages/autorun-env/src/lua/include.lua

Lines changed: 0 additions & 17 deletions
This file was deleted.

packages/autorun-lua/src/lua.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -403,16 +403,10 @@ impl LuaApi {
403403
LUA_OK | LUA_YIELD => Ok(()),
404404

405405
_ => {
406-
let err_msg = self.to_lstring(state, -1, std::ptr::null_mut());
406+
let err = self.check_string(state, -1);
407407
self.pop(state, 1);
408408

409-
let err_str = if !err_msg.is_null() {
410-
unsafe { std::ffi::CStr::from_ptr(err_msg) }.to_string_lossy()
411-
} else {
412-
std::borrow::Cow::Borrowed("Unknown error")
413-
};
414-
415-
Err(err_str)
409+
Err(err)
416410
}
417411
}
418412
}
@@ -428,16 +422,10 @@ impl LuaApi {
428422
LUA_OK | LUA_YIELD => Ok(()),
429423

430424
_ => {
431-
let err_msg = self.to_lstring(state, -1, std::ptr::null_mut());
425+
let err = self.check_string(state, -1);
432426
self.pop(state, 1);
433427

434-
let err_str = if !err_msg.is_null() {
435-
unsafe { std::ffi::CStr::from_ptr(err_msg) }.to_string_lossy()
436-
} else {
437-
std::borrow::Cow::Borrowed("Unknown error")
438-
};
439-
440-
Err(err_str)
428+
Err(err)
441429
}
442430
}
443431
}
@@ -480,6 +468,15 @@ impl<T: IntoLua> LuaReturn for T {
480468
}
481469
}
482470

471+
#[repr(transparent)]
472+
pub struct RawLuaReturn(pub i32);
473+
474+
impl LuaReturn for RawLuaReturn {
475+
fn into_lua_return(self, _lua: &LuaApi, _state: *mut LuaState) -> i32 {
476+
self.0
477+
}
478+
}
479+
483480
// Macro to implement LuaReturn for tuples
484481
macro_rules! impl_lua_return_tuple {
485482
($($T:ident),+) => {

packages/autorun-lua/src/value.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ impl FromLua for Option<LuaFunction> {
104104
}
105105
}
106106

107+
impl<T: FromLua> FromLua for Option<T> {
108+
fn from_lua(lua: &LuaApi, state: *mut LuaState, stack_idx: i32) -> Self {
109+
if lua.type_id(state, stack_idx) == crate::LuaTypeId::Nil {
110+
None
111+
} else {
112+
Some(T::from_lua(lua, state, stack_idx))
113+
}
114+
}
115+
}
116+
107117
impl IntoLua for &std::borrow::Cow<'_, str> {
108118
fn into_lua(self, lua: &LuaApi, state: *mut LuaState) {
109119
lua.push_lstring(state, self.as_ptr() as _, self.len());

plugins/std/plugin.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[plugin]
2+
name = "std"
3+
author = "vurv"
4+
version = "0.1.0"
5+
description = "Standard library for Autorun-ng"
6+
language = "lua"
7+
ordering = 0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,5 @@ tostring = _G.tostring
107107
type = _G.type
108108
xpcall = _G.xpcall
109109
_VERSION = _G._VERSION
110+
getfenv = _G.getfenv
111+
setfenv = _G.setfenv

0 commit comments

Comments
 (0)