72 lines
1.9 KiB
Rust
72 lines
1.9 KiB
Rust
use std::{fs::{DirEntry, self}, io::ErrorKind};
|
|
|
|
use anyhow::anyhow;
|
|
use log::{debug, warn, info};
|
|
use mlua::{Lua, Table};
|
|
|
|
use crate::QC_VERSION;
|
|
|
|
fn load_plugin<'lua>(entry: &DirEntry, lua: &'lua Lua) -> anyhow::Result<(String, Table<'lua>)> {
|
|
let ty = entry.file_type()?;
|
|
let mut path = entry.path();
|
|
if ty.is_dir() {
|
|
path.push("main.lua");
|
|
}
|
|
let chunk = lua.load(path);
|
|
debug!("evaluating plugin");
|
|
let table: Table = chunk.eval()?;
|
|
|
|
let id = table.get("id")
|
|
.map_err(|e| anyhow!("could not get plugin id: {e}"))?;
|
|
|
|
if let Ok(qc_ver) = table.get::<_, String>("server_version") {
|
|
debug!("checking plugin version");
|
|
let req = semver::VersionReq::parse(&qc_ver)?;
|
|
if !req.matches(&semver::Version::parse(QC_VERSION).unwrap()) {
|
|
return Err(anyhow!("incompatible with quectocraft version {QC_VERSION}: expected {req}"));
|
|
}
|
|
} else {
|
|
warn!("plugin '{id}' is missing a version reqirement");
|
|
}
|
|
|
|
Ok((id, table))
|
|
}
|
|
|
|
pub fn load_plugins(lua: &Lua) -> mlua::Result<Table> {
|
|
let plugins = lua.create_table()?;
|
|
debug!("loading plugins");
|
|
let entries = match fs::read_dir("./plugins") {
|
|
Ok(n) => n,
|
|
Err(e) if e.kind() == ErrorKind::NotFound => {
|
|
warn!("plugins directory does not exist, creating");
|
|
if let Err(e) = fs::create_dir("./plugins") {
|
|
warn!("failed to create plugins directory: {e}");
|
|
}
|
|
return Ok(plugins)
|
|
},
|
|
Err(e) => {
|
|
warn!("failed to load plugins: {e}");
|
|
return Ok(plugins)
|
|
}
|
|
};
|
|
for entry in entries {
|
|
let entry = match entry {
|
|
Ok(e) => e,
|
|
Err(e) => {
|
|
warn!("error reading entry: {e}");
|
|
continue
|
|
}
|
|
};
|
|
let path = entry.path();
|
|
let spath = path.to_str().unwrap_or("<non-unicode path>");
|
|
debug!("loading plugin at {spath}");
|
|
match load_plugin(&entry, lua) {
|
|
Ok((id, table)) => {
|
|
info!("loaded plugin {}", id);
|
|
plugins.set(id, table)?;
|
|
}
|
|
Err(e) => warn!("error loading plugin at {spath}: {e}"),
|
|
}
|
|
}
|
|
Ok(plugins)
|
|
}
|