Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
075ae3b
Fixed paths not working for code signing
ktwrd Oct 31, 2025
f3f85cf
Use windows-2022 instead of windows-2025 (this is what i think broke it)
ktwrd Oct 31, 2025
fbd7cf8
fix: update deprecated actions
sour-dani Nov 2, 2025
329606b
chore: workflow name
sour-dani Nov 2, 2025
43913f4
Merge pull request #43 from Pre-Fortress-2/deprecated
ktwrd Nov 2, 2025
3fd6d85
Merge pull request #42 from ktwrd/housekeeping/fix-codesigning-1
ktwrd Nov 3, 2025
e164acd
fix: codesigning step accidentally skipped
sour-dani Nov 8, 2025
82e3d5b
Merge pull request #50 from Pre-Fortress-2/codesigning-workflow-fix
ktwrd Nov 8, 2025
71a7663
docs: new dir + server integration
sour-dani Nov 8, 2025
7be3e7b
docs: suggested revisions for readme + CONTRIBUTING
sour-dani Nov 8, 2025
7a3488b
Update to Rust 2024 and nightly-2025-11-09
ktwrd Nov 9, 2025
ae71171
cargo fmt
ktwrd Nov 9, 2025
4041386
Updated dependencies
ktwrd Nov 9, 2025
35b9bd7
Replaced static mut with lazy static in logger.rs
ktwrd Nov 9, 2025
17d4c94
Merge pull request #51 from ktwrd/housekeeping/toolchain-nightly-2025…
ktwrd Nov 9, 2025
4b7e0ae
docs: sentry
sour-dani Nov 10, 2025
d02ddd0
docs: code signing
sour-dani Nov 11, 2025
a1a363d
Merge pull request #52 from Pre-Fortress-2/docs
ktwrd Nov 11, 2025
e4270d9
feat: mod specific butler staging foler
sour-dani Nov 14, 2025
c286bbe
feat: clean up command also removes butler-staging
sour-dani Nov 14, 2025
6740fa6
Merge pull request #56 from Pre-Fortress-2/butler-cleanup
ktwrd Nov 14, 2025
98c8d77
Merge pull request #55 from Pre-Fortress-2/staging-dir
ktwrd Nov 14, 2025
31e27dc
docs: cargo fmt
sour-dani Nov 28, 2025
744f1cf
Merge pull request #59 from Pre-Fortress-2/docs
ktwrd Nov 29, 2025
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
10 changes: 5 additions & 5 deletions .github/workflows/compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- os: ubuntu-22.04
filename: 'beans-rs'
target: x86_64-unknown-linux-gnu
- os: windows-latest
- os: windows-2022
target: x86_64-pc-windows-msvc
filename: 'beans-rs.exe'
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -52,22 +52,22 @@ jobs:
libfltk1.3-dev \
libssl-dev

- uses: actions-rs/toolchain@v1
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-01-10
target: ${{ matrix.target }}
targets: ${{ matrix.target }}

- uses: actions-rs/cargo@v1
with:
command: build
args: --verbose --target ${{ matrix.target }}
- name: Code Signing (Windows)
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-2022' }}
uses: skymatic/code-sign-action@v1
with:
certificate: '${{ secrets.CODESIGN }}'
password: '${{ secrets.CODESIGN_PASSWORD }}'
folder: 'target/${{ matrix.target }}/debug/'
folder: 'target/${{ matrix.target }}/debug'
description: 'beans-rs'
certificatesha1: '${{ secrets.CODESIGN_HASH }}'
- name: Upload artifact
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# .github/workflows/release.yml
name: Release

on:
workflow_dispatch:
Expand All @@ -19,7 +20,7 @@ jobs:
filename: 'beans-rs'
target: x86_64-unknown-linux-gnu

- os: windows-latest
- os: windows-2022
target: x86_64-pc-windows-msvc
filename: 'beans-rs.exe'

Expand Down Expand Up @@ -53,23 +54,23 @@ jobs:
libfltk1.3-dev \
libssl-dev

- uses: actions-rs/toolchain@v1
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-01-10
target: ${{ matrix.target }}
targets: ${{ matrix.target }}

- uses: actions-rs/cargo@v1
with:
command: build
args: --release --target ${{ matrix.target }}

- name: Code Signing (Windows)
if: ${{ matrix.os == 'windows-latest' }}
if: ${{ matrix.os == 'windows-2022' }}
uses: skymatic/code-sign-action@v1
with:
certificate: '${{ secrets.CODESIGN }}'
password: '${{ secrets.CODESIGN_PASSWORD }}'
folder: 'target/${{ matrix.target }}/release/'
folder: 'target/${{ matrix.target }}/release'
description: 'beans-rs'
certificatesha1: '${{ secrets.CODESIGN_HASH }}'

Expand Down
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing

**When creating a PR, you must branch off the `develop` branch.** When merging back into this repo remember to select the `develop` as the branch to merge into. After the **7th of June 2024** any PRs that **do not** use `develop` as the base branch will be closed.

**Before submitting a PR** make sure to format your code using the `cargo fmt` command. Code that is not properly formatted will need to do so before being merged.

When adding a new feature (that a user will interact with), create a new file in `src/workflows/` with the name of the feature (for example, `launch.rs`). Inside of `launch.rs` you would have a struct with the name of `LaunchWorkflow`. It would look something like this;
```rust
use crate::{RunnerContext, BeansError};

#[derive(Debug, Clone)]
pub struct LaunchWorkflow {
pub context: RunnerContext
}
impl LaunchWorkflow {
pub async fn wizard(ctx: &mut RunnerContext) -> Result<(), BeansError>
{
todo!("Logic for handling the LaunchWorkflow")
}
}
```
You would also be adding a subcommand for this ins `main.rs`. In `Launcher::run()` you would add the following ***before*** `.args` is called on `cmd`, and after the last `.subcommand()` that is used. What you would add would look like the following;
```rust
.subcommand(Command::new("launch")
.about("Launch the currently installed game")
.arg(Launcher::create_location_arg()))
```

All sub-commands must have the `--location` argument added so the end-user can specify if they have a custom location for their `sourcemods` folder.

Next you'd add a match case so `Launcher::subcommand_processor(&mut self)`, which would look like the following;
```rust
Some(("launch", install_matches)) => {
self.task_launch(install_matches).await;
}
```

Then, you'd add a new function to `Launcher`, which would actually call `LaunchWorkflow`. It would look something like the following (if there is only the `--location` argument);
```rust
pub async fn task_launch(&mut self, matches: &ArgMatches) {
self.to_location = Launcher::find_arg_sourcemods_location(&matches); // must be done when the `--launcher` argument is provided on the subcommand!
if let Err(e) = LaunchWorkflow::wizard(&mut ctx).await {
panic!("Failed to run LaunchWorkflow {:#?}", e);
} else {
logic_done(); // must be called when any flow of logic has completed.
}
}
```

**Do not make any PRs to remove the embedded executables in favor of downloading.** Some users would like to use this application offline, or they may have unreliable internet.
50 changes: 25 additions & 25 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "beans-rs"
version = "1.7.3"
edition = "2021"
edition = "2024"
authors = [
"Kate Ward <[email protected]>",
"ToastXC <[email protected]>"
Expand All @@ -13,46 +13,46 @@ license = "GPL-3.0"
[dependencies]
async-recursion = "1.1.1"
async-stream = "0.3.6"
const_format = "0.2.34"
const_format = "0.2.35"
futures = "0.3.31"
futures-util = "0.3.31"
indicatif = "0.17.11"
rand = "0.9.1"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
sysinfo = "0.35.1"
indicatif = "0.18.2"
rand = "0.9.2"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
sysinfo = "0.37.2"
tar = "0.4.44"
tokio-util = { version= "0.7.14", features = ["io"] }
tokio-util = { version= "0.7.17", features = ["io"] }
zstd = "0.13.3"
thiserror = "2.0.12"
include-flate = "0.3.0"
simple-home-dir = "0.5.0"
clap = { version = "4.5.32", features = ["cargo"] }
bitflags = "2.9.0"
log = "0.4.26"
thiserror = "2.0.17"
include-flate = "0.3.1"
simple-home-dir = "0.5.2"
clap = { version = "4.5.51", features = ["cargo"] }
bitflags = "2.10.0"
log = "0.4.28"
lazy_static = "1.5.0"
thread-id = "5.0.0"
colored = "3.0.0"
sentry-log = "0.38.0"
chrono = "0.4.40"
sentry-log = "0.45.0"
chrono = "0.4.42"

fltk = { version = "1.5.4" }
fltk-theme = "0.7.5"
fltk = { version = "1.5.21" }
fltk-theme = "0.7.9"
dark-light = "2.0.0"
image = { version = "0.25.5", features = ["png"] }
image = { version = "0.25.8", features = ["png"] }

[build-dependencies]
fl2rust = "0.7.0"
fl2rust = "0.7.1"

[target.'cfg(target_os = "windows")'.dependencies]
winconsole = { version = "0.11.1", features = ["window"] }
winreg = "0.55.0"
widestring = "1.1.0"
windows = { version = "0.60.0", features = ["Win32_System_IO", "Win32_Storage_FileSystem"] }
widestring = "1.2.1"
windows = { version = "0.62.2", features = ["Win32_System_IO", "Win32_Storage_FileSystem"] }
dunce = "1.0.5"

[dependencies.sentry]
version = "0.38.0"
version = "0.45.0"
default-features = false
features = [
"backtrace",
Expand All @@ -67,14 +67,14 @@ features = [


[dependencies.tokio]
version = "1.44.0"
version = "1.48.0"
features = [
"macros",
"rt-multi-thread"
]

[dependencies.reqwest]
version = "0.12.14"
version = "0.12.24"
features = [
"multipart",
"stream",
Expand Down
91 changes: 22 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,29 @@
# beans-rs

A Sourcemod Installer written with Rust, using the Kachemak versioning system (based off TF2C). Intended for general-purpose use, and for server owners.

This is a complete rewrite of the original [beans](https://github.com/int-72h/ofinstaller-beans) installer, but with rust, and extended support.

`beans-rs` is licensed under `GPLv3-only`, so please respect it!

**Note** Releases for Linux v1.5.0 and later are built with Ubuntu 20.04

## Developing
Requirements
- Rust Toolchain (nightly, only for building)
### Requirements:
- **Read the [CONTRIBUTING](CONTRIBUTING.md) rules!**
- Rust Toolchain (Nightly required for building)
- Recommended to use [rustup](https://rustup.rs/) to install.
- x86-64/AMD64 Processor ([see notes](#notes-binaries))
- OpenSSL v3 (also required on deployments)
- fltk ([please read "FLTK Linux Dependencies"](#fltk-linux-dependencies))
- (Optional) `fluid` for creating `.fl` files.
- **Following requirements are only required for testing**
- Steam Installed
- x86-64/AMD64 Processor ([See notes](#notes))
- OpenSSL v3 (Required on deployments)
- fltk ([Please read "FLTK Linux Dependencies"](#fltk-linux-dependencies))
- (Optional) `fluid` for creating `.fl` files.
- Steam Installed (Only required for testing)
- Source SDK Base 2013 Multiplayer ([install](steam://instal/243750))

## Contributing
When creating a PR, please please please branch off the `develop` branch. Any PRs that are created after the 7th of June 2024 that **do not** use `develop` as the base branch will be closed.

When adding a new feature (that a user will interact with), create a new file in `src/workflows/` with the name of the feature (for example, `launch.rs`). Inside of `launch.rs` you would have a struct with the name of `LaunchWorkflow`. It would look something like this;
```rust
use crate::{RunnerContext, BeansError};

#[derive(Debug, Clone)]
pub struct LaunchWorkflow {
pub context: RunnerContext
}
impl LaunchWorkflow {
pub async fn wizard(ctx: &mut RunnerContext) -> Result<(), BeansError>
{
todo!("Logic for handling the LaunchWorkflow")
}
}
```
You would also be adding a subcommand for this ins `main.rs`. In `Launcher::run()` you would add the following ***before*** `.args` is called on `cmd`, and after the last `.subcommand()` that is used. What you would add would look like the following;
```rust
.subcommand(Command::new("launch")
.about("Launch the currently installed game")
.arg(Launcher::create_location_arg()))
```

All sub-commands must have the `--location` argument added so the end-user can specify if they have a custom location for their `sourcemods` folder.

Next you'd add a match case so `Launcher::subcommand_processor(&mut self)`, which would look like the following;
```rust
Some(("launch", install_matches)) => {
self.task_launch(install_matches).await;
}
```

Then, you'd add a new function to `Launcher`, which would actually call `LaunchWorkflow`. It would look something like the following (if there is only the `--location` argument);
```rust
pub async fn task_launch(&mut self, matches: &ArgMatches) {
self.to_location = Launcher::find_arg_sourcemods_location(&matches); // must be done when the `--launcher` argument is provided on the subcommand!
if let Err(e) = LaunchWorkflow::wizard(&mut ctx).await {
panic!("Failed to run LaunchWorkflow {:#?}", e);
} else {
logic_done(); // must be called when any flow of logic has completed.
}
}
```

## Notes
### Binaries
All the bundled/embedded binaries are for x86-64/AMD64 systems. We only support that architecture because that's what Open Fortress supports.

Please do not make any PRs to remove the embedded executables in favor of downloading. Some users would like to use this application offline, or they may have unreliable internet.

Linux Systems not using glibc have not been tested.

### FLTK Linux Dependencies
## FLTK Linux Dependencies
When building `beans-rs`, some dependencies are required to build it since we need the build dependencies for fltk.

If your distribution is not listed (or the instructions are broken), please look at [`README.unix.txt` in the fltk repo.](https://github.com/fltk/fltk/blob/master/README.Unix.txt).
If your distribution is not listed (or the instructions are broken), please look at [`README.unix.txt` in the fltk repo](https://github.com/fltk/fltk/blob/master/README.Unix.txt).

#### Debian-based
### Debian-based
This includes and Linux Distribution that is based off Debian or Ubuntu. Like;
- [Ubuntu](https://ubuntu.com/),
- [Debian](https://www.debian.org/),
Expand Down Expand Up @@ -110,9 +55,17 @@ sudo apt-get install -y \
libxinerama-dev;
```

#### Fedora
### Fedora
```bash
sudo yum groupinstall -y "Development Tools"
sudo yum groupinstall -y "X Software Development"
sudo yum groupinstall -y "C Development Tools and Libraries"
```
```

## Notes
All the bundled/embedded binaries are for x86-64/AMD64 systems. We only support that architecture because that's what Open Fortress supports.

Linux Systems not using glibc have not been tested.

Releases for v1.5.0 and later are built with Ubuntu 20.04.

Loading
Loading