Skip to content

Commit

Permalink
1.0.0 (functions for ZAS, making sure turfs are optional, whatever el…
Browse files Browse the repository at this point in the history
…se may be needed) (#43)

* Some required bits for ZAS

* Ratio for share_ratio no longer hardcoded

* Documentation, consistency

* Cleanup, a bit of memory footprint improvement

* More microoptimizations, docs etc.

* And a formatting check.

* More proper prototypes

* Fixes enabled

* Embarassing typo

* Plasma fire wasn't loading right!

* Adjacencies must happen after turfs

* Pedantic clippy stuff
  • Loading branch information
Putnam3145 authored May 5, 2022
1 parent 076b1ef commit 4e1ed42
Show file tree
Hide file tree
Showing 16 changed files with 738 additions and 354 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ jobs:
run: |
sudo apt update
sudo apt install g++-multilib -y
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check auxmos build
run: cargo check --target=i686-unknown-linux-gnu --release --features "all_reaction_hooks katmos"
13 changes: 10 additions & 3 deletions Cargo.lock

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

11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
[package]
name = "auxmos"
version = "0.3.1"
version = "1.0.0"
authors = ["Putnam <putnam3145@gmail.com>"]
edition = "2018"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["auxcleanup_gas_deletion"]
default = ["auxcleanup_gas_deletion", "turf_processing"]
auxcleanup_gas_deletion = ["auxcleanup"]
equalization = []
zas_hooks = []
turf_processing = []
equalization = ["turf_processing"]
monstermos = ["equalization"]
putnamos = ["equalization"]
katmos = ["equalization"]
Expand Down Expand Up @@ -41,6 +43,7 @@ ahash = "0.7.6"
lazy_static = "1.4.0"
indexmap = { version = "1.8.0", features = ["rayon"] }
dashmap = { version = "5.2.0", features = ["rayon"] }
atomic_float = "0.1.0"

[dependencies.tinyvec]
version = "1.5.1"
Expand Down
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
Rust-based atmospherics for Space Station 13 using [auxtools](https://github.com/willox/auxtools).

Still quite early. Monstermos has an annoying anisotropy--it prefers to go left and right rather than up or down. Up and down are first in the adjacency bitfield (little endian wise), so this isn't *terribly* surprising, but it is annoying. Perhaps it's a problem with the algorithm--am I using a stack instead of a queue?

This code relies on some byond code on [this fork of Citadel](https://github.com/Putnam3145/Citadel-Station-13/tree/auxtools-atmos). Documentation on this is associated with the individual data structures that hold them, in this repository.

The compiled binary on Citadel is compiled for Citadel's CPU, which therefore means that it uses [AVX2 fused-multiply-accumulate](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2). Yes, really. If you have issues, compile it yourself, via `cargo rustc --target=i686-pc-windows-msvc --release --features "all_reaction_hooks" -- -C target-cpu=native`.

TODO:
I would quite a lot like monstermos to work.
The compiled binary on Citadel is compiled for Citadel's CPU, which therefore means that it uses [AVX2 fused-multiply-accumulate](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2). Yes, really. If you have issues, compile it yourself, via `cargo rustc --target=i686-pc-windows-msvc --release --features "all_reaction_hooks" -- -C target-cpu=native`. It has to be 32-bit, mind.
26 changes: 26 additions & 0 deletions docs/MIGRATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 0.2 to 0.3

If you're using generic fires, `fire_enthalpy_released` was replaced with a more general `enthalpy`. If you're not, you don't need to do anything in auxgm.

# 0.3 to 1.0

New functions were added:

1. `/datum/gas_mixture/proc/adjust_moles_temp(gas_type, amt, temperature)`
2. `/datum/gas_mixture/proc/adjust_multi()` (it's variadic, of the form `gas1, amt1, gas2, amt2, ...`)
3. `/datum/gas_mixture/proc/add(amt)`
4. `/datum/gas_mixture/proc/subtract(amt)`
5. `/datum/gas_mixture/proc/multiply(factor)`
6. `/datum/gas_mixture/proc/divide(factor)`
7. `/datum/gas_mixture/proc/__remove_by_flag(taker, flag, amount)` should be paired with a proper remove_by_flag, like remove and remove_ratio
8. `/datum/gas_mixture/proc/get_by_flag(flag)`

There's also new feature flags:

1. `turf_processing`: on by default. Enables the hooks for turf processing, heat processing etc. Required for katmos, of course.
2. `zas_hooks`: Adds a `/datum/gas_mixture/proc/share_ratio(sharer, ratio, share_size, one_way = FALSE)` hook.

Monstermos is now deprecated. Use katmos instead. It inherently has explosive decompression, sorry.

`fire_products = "plasma_fire"` should be replaced with `fire_products = 0` or, preferably, `fire_products = FIRE_PRODUCT_PLASMA` or similar, with `FIRE_PRODUCT_PLASMA` being `#define FIRE_PRODUCT_PLASMA 0`. String conversion like this is why fires weren't working on linux before; this breaking change is required for it not to be a total hack.

21 changes: 16 additions & 5 deletions src/callbacks.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use auxtools::*;
use auxtools::{init, shutdown, DMResult, Proc, Value};

type DeferredFunc = Box<dyn Fn() -> DMResult + Send + Sync>;

type CallbackChannel = (flume::Sender<DeferredFunc>, flume::Receiver<DeferredFunc>);

static mut CALLBACK_CHANNELS: Option<[CallbackChannel; 2]> = None;
static mut CALLBACK_CHANNELS: Option<[CallbackChannel; 3]> = None;

pub(crate) const TURFS: usize = 0;

pub(crate) const TEMPERATURE: usize = 1;

pub(crate) const ADJACENCIES: usize = 2;

#[init(partial)]
fn _start_aux_callbacks() -> Result<(), String> {
unsafe {
CALLBACK_CHANNELS = Some([flume::unbounded(), flume::unbounded()]);
CALLBACK_CHANNELS = Some([flume::unbounded(), flume::unbounded(), flume::unbounded()]);
}
Ok(())
}
Expand All @@ -30,20 +32,29 @@ fn with_aux_callback_receiver<T>(
f(unsafe { &CALLBACK_CHANNELS.as_ref().unwrap()[item].1 })
}

/// Returns a clone of the sender for the given callback channel.
/// # Panics
/// If callback channels have (somehow) not been initialized yet.
#[must_use]
pub fn aux_callbacks_sender(item: usize) -> flume::Sender<DeferredFunc> {
unsafe { CALLBACK_CHANNELS.as_ref().unwrap()[item].0.clone() }
}

/// Process all the callbacks for the given channel.
/// # Panics
/// If `auxtools_stack_trace` does not exist.
pub fn process_aux_callbacks(item: usize) {
let stack_trace = Proc::find("/proc/auxtools_stack_trace").unwrap();
with_aux_callback_receiver(
|receiver| {
for callback in receiver.try_iter() {
if let Err(e) = callback() {
let _ = stack_trace.call(&[&Value::from_string(e.message.as_str()).unwrap()]);
std::mem::drop(
stack_trace.call(&[&Value::from_string(e.message.as_str()).unwrap()]),
);
}
}
},
item,
)
);
}
45 changes: 45 additions & 0 deletions src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub use mixture::Mixture;

pub type GasIDX = usize;

/// A static container, with a bunch of helper functions for accessing global data. It's horrible, I know, but video games.
pub struct GasArena {}

/*
Expand Down Expand Up @@ -74,12 +75,20 @@ fn _shut_down_gases() {
}

impl GasArena {
/// Locks the gas arena and and runs the given closure with it locked.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
pub fn with_all_mixtures<T, F>(f: F) -> T
where
F: FnOnce(&[RwLock<Mixture>]) -> T,
{
f(GAS_MIXTURES.read().as_ref().unwrap())
}
/// Read locks the given gas mixture and runs the given closure on it.
/// # Errors
/// If no such gas mixture exists or the closure itself errors.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
pub fn with_gas_mixture<T, F>(id: usize, f: F) -> Result<T, Runtime>
where
F: FnOnce(&Mixture) -> Result<T, Runtime>,
Expand All @@ -92,6 +101,11 @@ impl GasArena {
.read();
f(&mix)
}
/// Write locks the given gas mixture and runs the given closure on it.
/// # Errors
/// If no such gas mixture exists or the closure itself errors.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
pub fn with_gas_mixture_mut<T, F>(id: usize, f: F) -> Result<T, Runtime>
where
F: FnOnce(&mut Mixture) -> Result<T, Runtime>,
Expand All @@ -104,6 +118,11 @@ impl GasArena {
.write();
f(&mut mix)
}
/// Read locks the given gas mixtures and runs the given closure on them.
/// # Errors
/// If no such gas mixture exists or the closure itself errors.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
pub fn with_gas_mixtures<T, F>(src: usize, arg: usize, f: F) -> Result<T, Runtime>
where
F: FnOnce(&Mixture, &Mixture) -> Result<T, Runtime>,
Expand All @@ -120,6 +139,11 @@ impl GasArena {
.read();
f(&src_gas, &arg_gas)
}
/// Locks the given gas mixtures and runs the given closure on them.
/// # Errors
/// If no such gas mixture exists or the closure itself errors.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
pub fn with_gas_mixtures_mut<T, F>(src: usize, arg: usize, f: F) -> Result<T, Runtime>
where
F: FnOnce(&mut Mixture, &mut Mixture) -> Result<T, Runtime>,
Expand Down Expand Up @@ -149,6 +173,11 @@ impl GasArena {
)
}
}
/// Runs the given closure on the gas mixture *locks* rather than an already-locked version.
/// # Errors
/// If no such gas mixture exists or the closure itself errors.
/// # Panics
/// if `GAS_MIXTURES` hasn't been initialized, somehow.
fn with_gas_mixtures_custom<T, F>(src: usize, arg: usize, f: F) -> Result<T, Runtime>
where
F: FnOnce(&RwLock<Mixture>, &RwLock<Mixture>) -> Result<T, Runtime>,
Expand All @@ -175,6 +204,10 @@ impl GasArena {
}
}
/// Fills in the first unused slot in the gas mixtures vector, or adds another one, then sets the argument Value to point to it.
/// # Errors
/// If `initial_volume` is incorrect or `_extools_pointer_gasmixture` doesn't exist, somehow.
/// # Panics
/// If `NEXT_GAS_IDS` is not initialized, somehow.
pub fn register_mix(mix: &Value) -> DMResult {
if NEXT_GAS_IDS.read().as_ref().unwrap().is_empty() {
let mut lock = GAS_MIXTURES.write();
Expand Down Expand Up @@ -227,6 +260,8 @@ impl GasArena {
Ok(Value::null())
}
/// Marks the Value's gas mixture as unused, allowing it to be reallocated to another.
/// # Panics
/// Panics if `NEXT_GAS_IDS` hasn't been initialized, somehow.
pub fn unregister_mix(mix: u32) {
if is_registered_mix(mix) {
use raw_types::values::{ValueData, ValueTag};
Expand Down Expand Up @@ -258,6 +293,8 @@ impl GasArena {
}

/// Gets the mix for the given value, and calls the provided closure with a reference to that mix as an argument.
/// # Errors
/// If a gasmixture ID is not a number or the callback returns an error.
pub fn with_mix<T, F>(mix: &Value, f: F) -> Result<T, Runtime>
where
F: FnMut(&Mixture) -> Result<T, Runtime>,
Expand All @@ -278,6 +315,8 @@ where
}

/// As `with_mix`, but mutable.
/// # Errors
/// If a gasmixture ID is not a number or the callback returns an error.
pub fn with_mix_mut<T, F>(mix: &Value, f: F) -> Result<T, Runtime>
where
F: FnMut(&mut Mixture) -> Result<T, Runtime>,
Expand All @@ -298,6 +337,8 @@ where
}

/// As `with_mix`, but with two mixes.
/// # Errors
/// If a gasmixture ID is not a number or the callback returns an error.
pub fn with_mixes<T, F>(src_mix: &Value, arg_mix: &Value, f: F) -> Result<T, Runtime>
where
F: FnMut(&Mixture, &Mixture) -> Result<T, Runtime>,
Expand Down Expand Up @@ -330,6 +371,8 @@ where
}

/// As `with_mix_mut`, but with two mixes.
/// # Errors
/// If a gasmixture ID is not a number or the callback returns an error.
pub fn with_mixes_mut<T, F>(src_mix: &Value, arg_mix: &Value, f: F) -> Result<T, Runtime>
where
F: FnMut(&mut Mixture, &mut Mixture) -> Result<T, Runtime>,
Expand Down Expand Up @@ -362,6 +405,8 @@ where
}

/// Allows different lock levels for each gas. Instead of relevant refs to the gases, returns the `RWLock` object.
/// # Errors
/// If a gasmixture ID is not a number or the callback returns an error.
pub fn with_mixes_custom<T, F>(src_mix: &Value, arg_mix: &Value, f: F) -> Result<T, Runtime>
where
F: FnMut(&RwLock<Mixture>, &RwLock<Mixture>) -> Result<T, Runtime>,
Expand Down
7 changes: 7 additions & 0 deletions src/gas/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ pub const MOLES_GAS_VISIBLE_STEP: f32 = 0.25;

/// REACTIONS

// Maximum amount of ReactionIdentifiers in the TinyVec that all_reactions returns.
// We can't guarantee the max number of reactions that will ever be registered,
// so this is here to prevent that from getting out of control.
// TinyVec is used mostly to prevent too much heap stuff from going on, since there can be a LOT of reactions going.
// ReactionIdentifier is 12 bytes, so this can be pretty generous.
pub(crate) const MAX_REACTION_TINYVEC_SIZE: usize = 32;

/// return values for reactions (bitflags)
pub const NO_REACTION: i32 = 0;
pub const REACTING: i32 = 1;
Expand Down
Loading

0 comments on commit 4e1ed42

Please sign in to comment.