diff options
author | Daniel Schadt <kingdread@gmx.de> | 2021-11-06 22:25:23 +0100 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2021-11-06 22:25:23 +0100 |
commit | 834a2d4f8a7dbd0e9eb14573c4340eb41af04738 (patch) | |
tree | bebd06cc13104fb8e77dc313f2f2ee862eb94a32 /src/game.rs | |
download | modderbaas-834a2d4f8a7dbd0e9eb14573c4340eb41af04738.tar.gz modderbaas-834a2d4f8a7dbd0e9eb14573c4340eb41af04738.tar.bz2 modderbaas-834a2d4f8a7dbd0e9eb14573c4340eb41af04738.zip |
Initial commit
This is the inital commit of a somewhat working version.
Diffstat (limited to 'src/game.rs')
-rw-r--r-- | src/game.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..f323212 --- /dev/null +++ b/src/game.rs @@ -0,0 +1,67 @@ +use std::{ + fmt, + path::{Path, PathBuf}, +}; + +use super::{ + error::{Error, Result}, + minemod::{self, MineMod}, + scan, +}; + +/// Represents an on-disk Minetest game. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Game { + path: PathBuf, +} + +impl Game { + /// Open the given directory as a Minetest game. + /// + /// Note that the path may be relative, but only to the parent directory of the actual game. + /// This is because Minetest uses the game's directory name to identify the game + /// ([`Game::technical_name`]), so we need this information. + pub fn open<P: AsRef<Path>>(path: P) -> Result<Game> { + Game::open_path(path.as_ref()) + } + + fn open_path(path: &Path) -> Result<Game> { + if path.file_name().is_none() { + return Err(Error::InvalidGameDir(path.into())); + } + let conf = path.join("game.conf"); + if !conf.is_file() { + return Err(Error::InvalidGameDir(path.into())); + } + + Ok(Game { path: path.into() }) + } + + /// Returns the technical name of this game. + /// + /// This is the name that is used by minetest to identify the game. + pub fn technical_name(&self) -> String { + self.path + .file_name() + .expect("Somebody constructed an invalid `Game`") + .to_str() + .expect("Non-UTF8 directory encountered") + .into() + } + + /// Returns all mods that this game provides. + pub fn mods(&self) -> Result<Vec<MineMod>> { + let path = self.path.join("mods"); + let mut mods = vec![]; + for container in scan(&path, |p| minemod::open_mod_or_pack(p))? { + mods.extend(container.mods()?); + } + Ok(mods) + } +} + +impl fmt::Display for Game { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.technical_name()) + } +} |