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
impl HookConfig
Sourcepub fn load_from_path(path: &Path) -> Result<Self, HookConfigError>
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.
Sourcepub fn write_to_path(&self, path: &Path) -> Result<(), HookConfigError>
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.
Sourcepub fn load_from_mods_dir(
mods_dir: &Path,
) -> Result<(Self, Vec<(String, HookConfigError)>), HookConfigError>
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.
Sourcepub fn find_matching_rule(
&self,
requested_path: &str,
) -> Option<&RedirectionRule>
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).
Sourcepub fn resolve(
&self,
requested_path: &str,
file_exists: impl FnOnce(&Path) -> bool,
) -> ResolvedAction
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
impl Clone for HookConfig
Source§fn clone(&self) -> HookConfig
fn clone(&self) -> HookConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for HookConfig
impl Debug for HookConfig
Source§impl Default for HookConfig
impl Default for HookConfig
Source§fn default() -> HookConfig
fn default() -> HookConfig
Source§impl<'de> Deserialize<'de> for HookConfig
impl<'de> Deserialize<'de> for HookConfig
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for HookConfig
impl PartialEq for HookConfig
Source§fn eq(&self, other: &HookConfig) -> bool
fn eq(&self, other: &HookConfig) -> bool
self and other values to be equal, and is used by ==.