Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare the v2.0 beta release #56

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "steamlocate"
version = "2.0.0-alpha.1"
version = "2.0.0-beta.0"
authors = ["William Venner <william@venner.io>"]
edition = "2018"
repository = "https://github.com/WilliamVenner/steamlocate-rs"
Expand All @@ -19,16 +19,13 @@ rustdoc-args = ["--cfg", "docsrs", "--cfg", "steamlocate_doctest"]
[features]
default = ["locate"]
locate = ["locate_backend"]
shortcuts_extras = ["crc"]

[dependencies]
crc = "3.0"
keyvalues-parser = "0.2"
keyvalues-serde = "0.2"
serde = { version = "1.0", features = ["derive"] }

# TODO: is this really worth making optional? It should be a really small dep
crc = { version = "3.0", optional = true }

# Custom cfg used to enable a dependency only needed for doctests
[target."cfg(steamlocate_doctest)".dependencies]
tempfile = "3.8.1"
Expand Down
162 changes: 66 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,127 +5,97 @@

# steamlocate

A crate which efficiently locates any Steam application on the filesystem, and/or the Steam installation itself.
A crate which efficiently locates any Steam application on the filesystem,
and/or the Steam installation itself.

This crate is best used when you do not want to depend on the Steamworks API for your program. In some cases the Steamworks API may be more appropriate to use, in which case I recommend the fantastic [steamworks](https://github.com/Thinkofname/steamworks-rs) crate. You don't need to be a Steamworks partner to get installation directory locations from the Steamworks API.
This crate is best used when you do not want to depend on the Steamworks API
for your program. In some cases the Steamworks API may be more appropriate to
use, in which case I recommend the fantastic
[steamworks](https://github.com/Thinkofname/steamworks-rs) crate. You don't
need to be a Steamworks partner to get installation directory locations from
the Steamworks API.

**This crate supports Windows, macOS and Linux.**
# Using steamlocate

## Using steamlocate
Simply add to your [Cargo.toml](https://doc.rust-lang.org/cargo/reference/manifest.html) file:
```toml
[dependencies]
steamlocate = "0.*"
```

To use [steamid-ng](#steamid-ng-support) with steamlocate, add this to your [Cargo.toml](https://doc.rust-lang.org/cargo/reference/manifest.html) file:
```toml
[dependencies]
steamid-ng = "1.*"
Simply add `steamlocate` using
[`cargo`](https://doc.rust-lang.org/cargo/getting-started/installation.html).

[dependencies.steamlocate]
version = "0.*"
features = ["steamid_ng"]
```console
$ cargo add steamlocate
```

## Caching
All functions in this crate cache their results, meaning you can call them as many times as you like and they will always return the same reference.
## Feature flags

If you need to get uncached results, simply instantiate a new [SteamDir](https://docs.rs/steamlocate/*/steamlocate/struct.SteamDir.html).
Default: `locate`

## steamid-ng Support
This crate supports [steamid-ng](https://docs.rs/steamid-ng) and can automatically convert [SteamApp::last_user](struct.SteamApp.html#structfield.last_user) to a [SteamID](https://docs.rs/steamid-ng/*/steamid_ng/struct.SteamID.html) for you.
| Feature flag | Description |
| :---: | :--- |
| `locate` | Enables automatically detecting the Steam installation on supported platforms (currently Windows, MacOS, and Linux). Unsupported platforms will return a runtime error. |

To enable this support, [use the `steamid_ng` Cargo.toml feature](#using-steamlocate).
# Examples

## Examples
## Locate the Steam installation and a specific game

#### Locate the installed Steam directory
```rust
extern crate steamlocate;
use steamlocate::SteamDir;
The `SteamDir` is going to be your entrypoint into _most_ parts of the API.
After you locate it you can access related information.

match SteamDir::locate() {
Some(steamdir) => println!("{:#?}", steamdir),
None => panic!("Couldn't locate Steam on this computer!")
}
```rust,ignore
let steam_dir = steamlocate::SteamDir::locate()?;
println!("Steam installation - {}", steam_dir.path().display());
// ^^ prints something like `Steam installation - C:\Program Files (x86)\Steam`

const GMOD_APP_ID: u32 = 4_000;
let (garrys_mod, _lib) = steam_dir
.find_app(GMOD_APP_ID)?
.expect("Of course we have G Mod");
assert_eq!(garrys_mod.name.as_ref().unwrap(), "Garry's Mod");
println!("{garrys_mod:#?}");
// ^^ prints something like vv
```
```rust
SteamDir (
path: PathBuf: "C:\\Program Files (x86)\\Steam"
)
```rust,ignore
App {
app_id: 4_000,
install_dir: "GarrysMod",
name: Some("Garry's Mod"),
universe: Some(Public),
// much much more data
}
```

#### Locate an installed Steam app by its app ID
This will locate Garry's Mod anywhere on the filesystem.
```rust
extern crate steamlocate;
use steamlocate::SteamDir;
## Get an overview of all libraries and apps on the system

let mut steamdir = SteamDir::locate().unwrap();
match steamdir.app(&4000) {
Some(app) => println!("{:#?}", app),
None => panic!("Couldn't locate Garry's Mod on this computer!")
}
```
```rust
SteamApp (
appid: u32: 4000,
path: PathBuf: "C:\\Program Files (x86)\\steamapps\\common\\GarrysMod",
vdf: <steamy_vdf::Table>,
name: Some(String: "Garry's Mod"),
last_user: Some(u64: 76561198040894045)
)
```
You can iterate over all of Steam's libraries from the steam dir. Then from each library you
can iterate over all of its apps.

#### Locate all Steam apps on this filesystem
```rust
extern crate steamlocate;
use steamlocate::{SteamDir, SteamApp};
use std::collections::HashMap;
```rust,ignore
let steam_dir = steamlocate::SteamDir::locate()?;

let mut steamdir = SteamDir::locate().unwrap();
let apps: &HashMap<u32, Option<SteamApp>> = steamdir.apps();
for library in steam_dir.libraries()? {
let library = library?;
println!("Library - {}", library.path().display());

println!("{:#?}", apps);
```
```rust
{
4000: SteamApp (
appid: u32: 4000,
path: PathBuf: "C:\\Program Files (x86)\\steamapps\\common\\GarrysMod",
vdf: <steamy_vdf::Table>,
name: Some(String: "Garry's Mod"),
last_user: Some(u64: 76561198040894045)
)
...
for app in library.apps() {
let app = app?;
println!(" App {} - {:?}", app.app_id, app.name);
}
}
```

#### Locate all Steam library folders
```rust
extern crate steamlocate;
use steamlocate::{SteamDir, LibraryFolders};
use std::{vec, path::PathBuf};

let mut steamdir: SteamDir = SteamDir::locate().unwrap();
let libraryfolders: &LibraryFolders = steamdir.libraryfolders();
let paths: &Vec<PathBuf> = &libraryfolders.paths;

println!("{:#?}", paths);
```
```rust
{
"C:\\Program Files (x86)\\Steam\\steamapps",
"D:\\Steam\\steamapps",
"E:\\Steam\\steamapps",
"F:\\Steam\\steamapps",
...
}
On my laptop this prints

```text
Library - /home/wintermute/.local/share/Steam
App 1628350 - Steam Linux Runtime 3.0 (sniper)
App 1493710 - Proton Experimental
App 4000 - Garry's Mod
Library - /home/wintermute/temp steam lib
App 391540 - Undertale
App 1714040 - Super Auto Pets
App 2348590 - Proton 8.0
```

## Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the MIT license,
shall be dual licensed as above, without any additional terms or conditions.
shall be licensed as above, without any additional terms or conditions.
2 changes: 1 addition & 1 deletion examples/shortcuts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn main() {
println!("Shortcuts:");
for maybe_shortcut in steamdir.shortcuts().unwrap() {
match maybe_shortcut {
Ok(shortcut) => println!(" - {} {}", shortcut.appid, shortcut.app_name),
Ok(shortcut) => println!(" - {} {}", shortcut.app_id, shortcut.app_name),
Err(err) => println!("Failed reading potential shortcut: {err}"),
}
}
Expand Down
17 changes: 12 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//! The [`SteamDir`] is going to be your entrypoint into _most_ parts of the API. After you locate
//! it you can access related information.
//!
//! ```rust
//! ```
//! # /*
//! let steam_dir = steamlocate::SteamDir::locate()?;
//! # */
Expand All @@ -34,7 +34,9 @@
//! // ^^ prints something like `Steam installation - C:\Program Files (x86)\Steam`
//!
//! const GMOD_APP_ID: u32 = 4_000;
//! let (garrys_mod, _lib) = steam_dir.find_app(GMOD_APP_ID)?.expect("Of course we have G Mod");
//! let (garrys_mod, _lib) = steam_dir
//! .find_app(GMOD_APP_ID)?
//! .expect("Of course we have G Mod");
//! assert_eq!(garrys_mod.name.as_ref().unwrap(), "Garry's Mod");
//! println!("{garrys_mod:#?}");
//! // ^^ prints something like vv
Expand Down Expand Up @@ -120,9 +122,14 @@ pub use crate::error::{Error, Result};
pub use crate::library::Library;
pub use crate::shortcut::Shortcut;

// Run doctests on the README too
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;

/// The entrypoint into most of the rest of the API
///
/// Use either [`SteamDir::locate()`] or [`SteamDir::from_steam_dir()`] to create a new instance.
/// Use either [`SteamDir::locate()`] or [`SteamDir::from_dir()`] to create a new instance.
/// From there you have access to:
///
/// - The Steam installation directory
Expand Down Expand Up @@ -219,7 +226,7 @@ impl SteamDir {
}

// TODO: rename to `from_dir()` and make consitent with similar constructors on other structs
pub fn from_steam_dir(path: &Path) -> Result<SteamDir> {
pub fn from_dir(path: &Path) -> Result<SteamDir> {
if !path.is_dir() {
return Err(Error::validation(ValidationError::missing_dir()));
}
Expand All @@ -236,6 +243,6 @@ impl SteamDir {
pub fn locate() -> Result<SteamDir> {
let path = locate::locate_steam_dir()?;

Self::from_steam_dir(&path)
Self::from_dir(&path)
}
}
Loading