Skip to main content

ReplacementEffect

Struct ReplacementEffect 

Source
pub struct ReplacementEffect {
    pub base: Box<TriggerReplacementBase>,
    pub event: ReplacementType,
    pub layer: ReplacementLayer,
    pub ir: ReplacementEffectIr,
    pub active_zones: Vec<ZoneType>,
    pub suppressed: bool,
}
Expand description

A parsed replacement effect from an R$ line in a card script.

Reference: Java ReplacementEffect.java in forge/game/replacement/.

Fields§

§base: Box<TriggerReplacementBase>

Shared trait base (host card, sVars, text-changes, map params). Mirrors Java ReplacementEffect extends TriggerReplacementBase extends CardTraitBase. Currently default-initialized by the parser; card factory population is a follow-up parity task so that matches_valid_param picks up Invert* entries from map_params.

Boxed because CardState holds five inline Option<ReplacementEffect> fields (loyalty_rep, defense_rep, saga_rep, adventure_rep, omen_rep) and TriggerReplacementBase → CardTraitBase contains an Option<CardState>, which would otherwise form an infinite-sized type. Trigger does not need this because CardState only owns triggers via Vec (heap indirection already).

§event: ReplacementType

The event type this effect intercepts.

§layer: ReplacementLayer

The CR 616 layer this effect belongs to.

§ir: ReplacementEffectIr

Typed runtime view of lowered replacement semantics.

§active_zones: Vec<ZoneType>

Zones where this effect is active. Empty = active everywhere. Parsed from ActiveZones$ parameter. TODO(java-parity): collapse into base.valid_host_zones.

§suppressed: bool

Temporary suppression flag used by effects like commander replacement.

Implementations§

Source§

impl ReplacementEffect

Source

pub fn set_host_card(&mut self, host: &Card)

Attach the host card id on the embedded trait base. Mirrors Java’s inherited CardTraitBase.setHostCard(host) — called from the ReplacementEffect constructor (ReplacementEffect.java:107) so a freshly-constructed effect is always host-bound.

In Rust the parser builds an unbound effect first (parser doesn’t have a Card handle) and every insertion site (card_state::add_replacement_effect, keyword grants, factory helpers) routes through this method to bind the host. After this call, CardTrait machinery can stop threading explicit host: &Card args. TriggerReplacementBase::set_host_card also propagates the host into any cached overriding ability.

Source§

impl ReplacementEffect

Source

pub fn new( event: ReplacementType, layer: ReplacementLayer, params: Params, active_zones: Vec<ZoneType>, ) -> Self

Source

pub fn replace_with(&self) -> Option<&str>

Source

pub fn has_skip(&self) -> bool

Source

pub fn prevents(&self) -> bool

Source

pub fn matches_phase(&self, phase: PhaseType) -> bool

Source

pub fn active_in_zone(&self, zone: ZoneType) -> bool

Returns true if this effect is active while the source card is in zone.

An empty active_zones list means the effect is always active (mirrors Java zonesCheck() returning true when activeZones is empty).

Source

pub fn description(&self, host: &Card, game: &GameState) -> String

Human-readable description. Mirrors Java ReplacementEffect.getDescription().

  • Suppressed or missing Description$ → empty string.
  • Applies text-change effects carried on the trait (Glamerdye / Crystal Spray word-swaps).
  • Substitutes CARDNAME and NICKNAME with the host’s name.
  • Substitutes EFFECTSOURCE with the card that created this host via effect_source (token makers, emblems, etc.).
  • For DamageDone replacements whose overriding SpellAbility uses AB$ ReplaceDamage / AB$ ReplaceSplitDamage, appends "Shields remain: N" when the Amount$ / VarName$ SVar resolves to Number$<n>. Only fires when the SA is already cached on the base (matches Java’s getOverridingAbility() not ensureAbility()).

Multi-locale translation is UI-layer and intentionally skipped.

Source

pub fn has_run(&self) -> bool

Always false. Java’s ReplacementEffect.hasRun is a per-effect flag used mainly during otherChoices resolution (Java gap #2 here). Our per-event chain uses ReplacementHandler.has_run instead, and a new handler is constructed by apply_replacements per event — so stale run-marks never leak across events. Revisit when otherChoices lands (a nested choice flow is the only path that needs the per-effect flag).

Source

pub fn requirements_check(&self, game: &GameState, source: &Card) -> bool

Check requirements for this replacement effect against the current game state.

Source

pub fn copy(&self) -> Self

Clone this replacement effect. Since ReplacementEffect derives Clone, this delegates to self.clone().

Mirrors Java ReplacementEffect.copy().

Source

pub fn ensure_ability( &self, game: &GameState, host_card: CardId, activating_player: PlayerId, ) -> Option<SpellAbility>

Mirrors Java ReplacementEffect.ensureAbility():

  1. If an overriding SpellAbility is already cached on the base, return a clone of it.
  2. Otherwise, if ReplaceWith$ is set, look up the named SVar on the host card, parse it via AbilityFactory.getAbility() (the Rust equivalent is build_spell_ability), and return the built ability.

This variant does NOT cache the built ability (const receiver). Use ensure_ability_mut to lazily cache on the base, matching Java’s setOverridingAbility(sa) call inside ensureAbility.

Source

pub fn ensure_ability_mut( &mut self, game: &GameState, host_card: CardId, activating_player: PlayerId, ) -> Option<&mut SpellAbility>

Mirrors Java ReplacementEffect.ensureAbility() including the cache write (Java calls setOverridingAbility(sa) on first build). Returns a mutable reference to the cached ability so callers can mutate trigger payloads before resolution.

Source

pub fn can_replace_etb(&self, source: &Card, affected: &Card) -> bool

Filter for ETB replacement events. Mirrors Java ReplacementEffect.canReplaceETB(runParams) (L321-345).

Returns false (skip) when the effect targets things OTHER than itself (ValidCard$ is not Card.Self-prefixed) AND the affected card IS the host card — i.e. the effect would be replacing its own ETB. Otherwise returns true.

Not yet ported: Java’s second guard reads AbilityKey.LastStateBattlefield to also skip when the host wasn’t on the battlefield before this Moved event. Rust doesn’t snapshot the previous battlefield state for replacement resolution, so that branch is omitted. Effects whose host just entered may still slip through in narrow nested ETB scenarios.

Source

pub fn set_replacing_objects( &self, event: &ReplacementEvent, sa: &mut SpellAbility, )

Mirrors Java ReplacementEffect.setReplacingObjects(runParams, sa). Java’s base method is an empty default overridden by each concrete subclass (ReplaceMoved, ReplaceDamage, ReplaceAddCounter, …). Rust has no subclasses; the match on self.event fills the same role by dispatching per event type inline.

The sub-ability walk is a Rust-ism — Java’s resolver inherits the triggering/replacing maps from the parent SA automatically, while the Rust SpellAbility resolver reads directly from each node. Writing to every node keeps Defined$ ReplacedCard-style lookups working inside SubAbility$ chains (Rust stores these under sa.trigger_objects; Java keeps replacingObjects separate).

Scope note: today this only runs on event paths that actually build a SpellAbility and resolve it through the SA resolver — currently just replace_moved::execute. Other handlers mutate events inline via execute_replace_effect_chain and bypass this hook. Migrate those paths first before adding their cases here.

Source

pub fn mode_check(&self, event: &ReplacementType) -> bool

Check if this effect’s event type matches the given event.

For AddCounter, also matches Moved events when the effect handles counter-on-move (i.e. has a CounterMap interaction).

Mirrors Java ReplacementEffect.modeCheck().

Trait Implementations§

Source§

impl CardTrait for ReplacementEffect

Source§

fn base(&self) -> &CardTraitBase

Borrow the underlying CardTraitBase. Implementors own a CardTraitBase (directly or transitively) and return a reference.
Source§

fn resolve_source_player(&self, src_card: &Card) -> PlayerId

Resolves the player whose perspective is used for Valid$ expressions. Default matches Java’s base behavior (source card’s controller). Trigger overrides — mirrors this instanceof Trigger in Java CardTraitBase.matchesValid(Object, String[], Card) at line 214.
Source§

fn matches_valid( &self, target: &MatchValidTarget<'_>, valids: &[&str], src_card: Option<&Card>, ) -> bool

Mirrors matchesValid(Object, String[], Card).
Source§

fn matches_compiled_valid( &self, target: &MatchValidTarget<'_>, selector: &CompiledSelector, src_card: Option<&Card>, ) -> bool

Source§

fn matches_valid_param( &self, param: &str, target: &MatchValidTarget<'_>, src_card: Option<&Card>, ) -> bool

Source§

fn matches_valid_card(&self, expr: &str, card: &Card, source: &Card) -> bool

Ergonomic comma-separated-expression wrapper over matches_valid for card targets. Mirrors Java’s matchesValid(Object, String[], Card) call pattern where valids is often a single comma-separated string (e.g. "Creature.YouCtrl,Artifact").
Source§

fn matches_compiled_valid_card( &self, selector: &CompiledSelector, card: &Card, source: &Card, ) -> bool

Source§

fn matches_valid_player( &self, expr: &str, player: PlayerId, source: &Card, ) -> bool

Ergonomic comma-separated-expression wrapper over matches_valid for player targets.
Source§

fn matches_compiled_valid_player( &self, selector: &CompiledSelector, player: PlayerId, source: &Card, ) -> bool

Source§

impl CardTraitIrOwner for ReplacementEffect

Source§

impl Clone for ReplacementEffect

Source§

fn clone(&self) -> ReplacementEffect

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 ReplacementEffect

Source§

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

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

impl<'de> Deserialize<'de> for ReplacementEffect

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 Serialize for ReplacementEffect

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

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> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
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<F, W, T, D> Deserialize<With<T, W>, D> for F
where W: DeserializeWith<F, T, D>, D: Fallible + ?Sized, F: ?Sized,

Source§

fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>

Deserializes using the given deserializer
Source§

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

Source§

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

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Gets the layout of the type.
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The type for metadata in pointers and references to Self.
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V