Skip to main content

HookConfig

Struct HookConfig 

Source
pub struct HookConfig {
    pub rules: Vec<RedirectionRule>,
}
Expand description

The full set of redirection rules the proxy DLL should apply for a single game session, already merged across every enabled mod. See HookConfig::load_from_mods_dir.

Fields§

§rules: Vec<RedirectionRule>

Implementations§

Source§

impl HookConfig

Source

pub fn load_from_path(path: &Path) -> Result<Self, HookConfigError>

Loads a HookConfig from a single JSON file on disk (a plain merged/resolved rule set, for a single mod’s authored mod.json, use ModConfig::load_from_path instead).

§Errors

Returns an error if the file cannot be read or does not contain valid JSON matching the expected shape.

Source

pub fn write_to_path(&self, path: &Path) -> Result<(), HookConfigError>

Serializes and writes this HookConfig to a JSON file on disk, creating parent directories as needed.

§Errors

Returns an error if parent directories can’t be created, the file can’t be written, or serialization fails.

Source

pub fn load_from_mods_dir( mods_dir: &Path, ) -> Result<(Self, Vec<(String, HookConfigError)>), HookConfigError>

Loads and merges every enabled mod’s rules from a mods directory laid out as described on crate::mods_state::DEFAULT_MODS_DIR_NAME.

Each mod’s rules are filtered and interpolated through ModConfig::resolved_rules before merging, by the time a rule reaches this function’s result, any enable_if gating and ${param_id} interpolation have already been resolved against that mod’s own configuration. Mods are then merged by simple concatenation of their (already-resolved) rule lists, in crate::mods_state::ModsPreset::priority_order order (of crate::mods_state::ModsState::active), the same order the launcher’s mod list displays, since for the active configuration display order and merge priority are the same list (unlike a saved, not-currently-applied preset in crate::mods_state::ModsState::presets, which freezes its own order separately until it’s applied, see crate::mods_state::ModsState::apply_preset). Since rule resolver scans that concatenated list in order: patch-only matches accumulate across mods, whereas a usable redirect starts a new stage at the redirected path and scans the entire list from the beginning. Thus the first successful conflicting redirect wins at its current stage, but later mods can still patch the same path or continue a chain at a redirected path. A mod’s rules stay contiguous and in their authored order.

A mod in the active priority order whose mod.json is missing, fails to parse, or fails ModConfig::validate is skipped entirely (none of its rules are applied) rather than failing the whole load, one broken or since-removed mod shouldn’t take every other enabled mod down with it. Validation failing here matches what the launcher’s own mod list shows as a broken/red entry, so a mod that a person can see is broken never has some of its rules quietly applied anyway. Skipped mods are returned alongside the merged config so the caller can log them; this crate takes no logging dependency of its own.

§Errors

Returns an error if mods.json can’t be read (including if it’s missing, unlike load_mods_state, this function requires it to exist) or doesn’t parse.

Source

pub fn find_matching_rule( &self, requested_path: &str, ) -> Option<&RedirectionRule>

Finds the first rule whose glob matches requested_path.

requested_path should be relative to the game’s root directory (callers are responsible for stripping the game root and normalizing separators before calling this).

Source

pub fn resolve( &self, requested_path: &str, file_exists: impl FnOnce(&Path) -> bool, ) -> ResolvedAction

Full resolution: given a requested path (relative to the game root) and a way to check whether a candidate replacement file exists, decides what the hook should do.

For a wildcard rule, the path below the rule’s fixed (non-wildcard) prefix is preserved when joining onto target, not just the file’s basename. This matters for directory-tree rules such as mods_source/**: a request for mods_source/textures/snow/ice.dds resolves under target as .../textures/snow/ice.dds, keeping the same relative layout, rather than flattening every match into a single directory. For a flat, single-component pattern like data/levels/*.dat this still reduces to just the file’s basename, since there’s no subdirectory portion to keep.

For a literal (non-wildcard) rule, target is used directly with nothing joined onto it, see RedirectionRule::is_literal_glob.

If target is omitted (None), this behaves exactly as if a configured replacement simply didn’t exist on disk: file_exists is never called, and the outcome is FallbackToOriginal or HardErrorMissingFile per the rule’s mode.

file_exists is injected rather than calling std::fs directly so this stays testable without touching a real filesystem, and so the proxy DLL can plug in whatever existence check makes sense for its context (e.g. going through the real NtQueryAttributesFile trampoline instead of std::fs, to avoid recursing into itself).

Trait Implementations§

Source§

impl Clone for HookConfig

Source§

fn clone(&self) -> HookConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for HookConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for HookConfig

Source§

fn default() -> HookConfig

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for HookConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for HookConfig

Source§

fn eq(&self, other: &HookConfig) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for HookConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for HookConfig

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,