Skip to content

Commit

Permalink
Format, refactoring to separate strucs from mod funcs, commands valid…
Browse files Browse the repository at this point in the history
…ation (#16)
  • Loading branch information
sbordeyne authored Aug 25, 2024
1 parent 502778c commit 388c0d0
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 157 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::mods::ModInfo;
use crate::structs::modinfo::ModInfo;
use crate::utils::{extract_functions, get_lua_files, minify_lua};
use mlua::prelude::LuaResult;
use mlua::{Lua, Table, Value};
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use crate::core::{
};
use mlua::prelude::*;
use mlua::Value;
use structs::modinfo::ModInfo;

use crate::mods::*;
#[cfg(not(target_os = "android"))]
use crate::updater::{get_latest_cli_version, self_update};

mod core;
mod mods;
mod structs;
mod tests;
mod updater;
mod utils;
Expand Down
160 changes: 5 additions & 155 deletions src/mods.rs
Original file line number Diff line number Diff line change
@@ -1,57 +1,12 @@
use std::collections::{HashMap, HashSet};

use crate::core::{get_love_dir, json_to_lua, lua_to_json};
use crate::core::get_love_dir;
use crate::structs::localmod::LocalMod;
use crate::structs::modinfo::ModInfo;
use crate::utils::validate_schema;
use crate::VERSION;
use mlua::prelude::{LuaError, LuaResult, LuaTable, LuaValue};
use mlua::{FromLua, IntoLua, Lua, Table};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone)]
pub struct ModInfo {
pub url: String,
pub id: String,
pub name: String,
pub description: Vec<String>,
pub version: String,
pub authors: Vec<String>,
}

impl IntoLua<'_> for ModInfo {
fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
let table = lua.create_table()?;
let download_mod = self.clone();
let download_func = lua.create_function(move |lua, ()| download_mod.download(lua))?;
table.set("url", self.url)?;
table.set("id", self.id)?;
table.set("name", self.name)?;
table.set("description", self.description)?;
table.set("version", self.version)?;
table.set("authors", self.authors)?;
table.set("download", download_func)?;
Ok(LuaValue::Table(table))
}
}

impl FromLua<'_> for ModInfo {
fn from_lua(value: LuaValue, _: &'_ Lua) -> LuaResult<Self> {
let table = value.as_table().expect("Expected table");
Ok(ModInfo {
url: table.get("url")?,
id: table.get("id")?,
name: table.get("name")?,
description: table.get("description")?,
version: table.get("version")?,
authors: table.get("authors")?,
})
}
}

impl ModInfo {
pub fn download(&self, lua: &Lua) -> LuaResult<()> {
download_mod(lua, self.clone())
}
}
use mlua::prelude::{LuaError, LuaResult, LuaTable};
use mlua::{Lua, Table};

pub fn download_mod(lua: &Lua, mod_info: ModInfo) -> LuaResult<()> {
let owner = mod_info.url.split("/").nth(3).unwrap();
Expand Down Expand Up @@ -259,111 +214,6 @@ pub fn get_local_mods(lua: &Lua) -> LuaResult<Vec<LocalMod>> {
Ok(local_mods)
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LocalMod {
pub id: String,
#[serde(skip)]
pub enabled: bool,
pub name: String,
pub version: String,
pub description: Vec<String>,
pub author: String,
pub load_before: Vec<String>,
pub load_after: Vec<String>,
pub min_balamod_version: Option<String>,
pub max_balamod_version: Option<String>,
pub balalib_version: Option<String>,
}

impl IntoLua<'_> for LocalMod {
fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
let local_mod = self.clone();
let table = lua.create_table()?;
let delete_mod = local_mod.clone();
let update_mod = local_mod.clone();
let save_config = local_mod.clone();
let load_config = local_mod.clone();
table.set(
"update",
lua.create_function(move |lua, mods: Vec<ModInfo>| update_mod.update(lua, mods))?,
)?;
table.set(
"delete",
lua.create_function(move |lua, ()| delete_mod.delete(lua))?,
)?;
table.set(
"save_config",
lua.create_function(move |lua, table: LuaValue| save_config.save_config(lua, table))?,
)?;
table.set(
"load_config",
lua.create_function(move |lua, ()| load_config.load_config(lua))?,
)?;
table.set("id", local_mod.id)?;
table.set("name", local_mod.name)?;
table.set("enabled", local_mod.enabled)?;
table.set("version", local_mod.version)?;
table.set("description", local_mod.description)?;
table.set("author", local_mod.author)?;
table.set("load_before", local_mod.load_before)?;
table.set("load_after", local_mod.load_after)?;

Ok(LuaValue::Table(table))
}
}

impl LocalMod {
pub fn delete(&self, lua: &Lua) -> LuaResult<()> {
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
std::fs::remove_dir_all(mod_dir)?;
Ok(())
}

pub fn update(&self, lua: &Lua, mods: Vec<ModInfo>) -> LuaResult<()> {
let mod_info = mods.iter().find(|mod_info| mod_info.id == self.id);
match mod_info {
Some(mod_info) => {
download_mod(lua, mod_info.clone())?;
println!("Updated mod: {}", self.id);
Ok(())
}
None => {
println!("Mod not found in the repo: {}", self.id);
Err(LuaError::RuntimeError(format!(
"Mod not found in the repo: {}",
self.id
)))
}
}
}

pub fn save_config(&self, lua: &Lua, table: LuaValue) -> LuaResult<()> {
let json = lua_to_json(table)?;
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
let config_file = format!("{}/config.json", mod_dir);
std::fs::write(config_file, json)?;
Ok(())
}

pub fn load_config<'lua>(&self, lua: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
let config_file = format!("{}/config.json", mod_dir);
if !std::path::Path::new(&config_file).exists() {
println!("No config file found for mod: {}", self.id);
return Ok(LuaValue::Nil);
}

let json = std::fs::read_to_string(config_file)?;
json_to_lua(lua, json)
}
}

#[derive(PartialEq)]
enum VisitFlag {
Temporary,
Expand Down
34 changes: 34 additions & 0 deletions src/schema/manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,34 @@
"authorName": {
"type": "string",
"pattern": "[A-Za-z0-9]+( <.+@[a-z0-9]+\\.[a-z\\.]{3,}>)?"
},
"command": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z_]+$",
"minLength": 4,
"maxLength": 15
},
"lua_path": {
"type": "string",
"pattern": "^[a-z0-9_]+(\\.[a-z0-9_]+)*$"
},
"short_description": {
"$ref": "#/$defs/text"
},
"usage": {
"$ref": "#/$defs/text"
}
},
"required": [
"name",
"lua_path",
"short_description",
"usage"
],
"additionalProperties": false
}
},
"type": "object",
Expand Down Expand Up @@ -87,6 +115,12 @@
}
},
"additionalProperties": false
},
"commands": {
"type": "array",
"items": {
"$ref": "#/$defs/command"
}
}
},
"additionalProperties": false
Expand Down
132 changes: 132 additions & 0 deletions src/structs/localmod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::core::{get_love_dir, json_to_lua, lua_to_json};
use crate::download_mod;
use crate::structs::modinfo::ModInfo;
use mlua::prelude::{LuaError, LuaResult, LuaValue};
use mlua::{IntoLua, Lua};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ModCommand {
pub name: String,
pub lua_path: String,
pub short_description: String,
pub usage: String,
}

impl IntoLua<'_> for ModCommand {
fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
let table = lua.create_table()?;
table.set("name", self.name)?;
table.set("lua_path", self.lua_path)?;
table.set("short_description", self.short_description)?;
table.set("usage", self.usage)?;
Ok(LuaValue::Table(table))
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LocalMod {
pub id: String,
#[serde(skip)]
pub enabled: bool,
pub name: String,
pub version: String,
pub description: Vec<String>,
pub author: String,
pub load_before: Vec<String>,
pub load_after: Vec<String>,
pub min_balamod_version: Option<String>,
pub max_balamod_version: Option<String>,
pub balalib_version: Option<String>,
pub commands: Vec<ModCommand>,
}

impl IntoLua<'_> for LocalMod {
fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
let local_mod = self.clone();
let table = lua.create_table()?;
let delete_mod = local_mod.clone();
let update_mod = local_mod.clone();
let save_config = local_mod.clone();
let load_config = local_mod.clone();
table.set(
"update",
lua.create_function(move |lua, mods: Vec<ModInfo>| update_mod.update(lua, mods))?,
)?;
table.set(
"delete",
lua.create_function(move |lua, ()| delete_mod.delete(lua))?,
)?;
table.set(
"save_config",
lua.create_function(move |lua, table: LuaValue| save_config.save_config(lua, table))?,
)?;
table.set(
"load_config",
lua.create_function(move |lua, ()| load_config.load_config(lua))?,
)?;
table.set("id", local_mod.id)?;
table.set("name", local_mod.name)?;
table.set("enabled", local_mod.enabled)?;
table.set("version", local_mod.version)?;
table.set("description", local_mod.description)?;
table.set("author", local_mod.author)?;
table.set("load_before", local_mod.load_before)?;
table.set("load_after", local_mod.load_after)?;
table.set("commands", local_mod.commands)?;

Ok(LuaValue::Table(table))
}
}

impl LocalMod {
pub fn delete(&self, lua: &Lua) -> LuaResult<()> {
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
std::fs::remove_dir_all(mod_dir)?;
Ok(())
}

pub fn update(&self, lua: &Lua, mods: Vec<ModInfo>) -> LuaResult<()> {
let mod_info = mods.iter().find(|mod_info| mod_info.id == self.id);
match mod_info {
Some(mod_info) => {
download_mod(lua, mod_info.clone())?;
println!("Updated mod: {}", self.id);
Ok(())
}
None => {
println!("Mod not found in the repo: {}", self.id);
Err(LuaError::RuntimeError(format!(
"Mod not found in the repo: {}",
self.id
)))
}
}
}

pub fn save_config(&self, lua: &Lua, table: LuaValue) -> LuaResult<()> {
let json = lua_to_json(table)?;
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
let config_file = format!("{}/config.json", mod_dir);
std::fs::write(config_file, json)?;
Ok(())
}

pub fn load_config<'lua>(&self, lua: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
let mod_dir = format!("{}/{}", mods_dir, self.id);
let config_file = format!("{}/config.json", mod_dir);
if !std::path::Path::new(&config_file).exists() {
println!("No config file found for mod: {}", self.id);
return Ok(LuaValue::Nil);
}

let json = std::fs::read_to_string(config_file)?;
json_to_lua(lua, json)
}
}
2 changes: 2 additions & 0 deletions src/structs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod localmod;
pub mod modinfo;
Loading

0 comments on commit 388c0d0

Please sign in to comment.