fix ContinuousEffect that access affectedObjectsSet before it is initialized (#12080)

This commit is contained in:
Susucre 2024-04-13 16:50:06 +02:00 committed by GitHub
parent cce7f79d89
commit 017286ed94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 351 additions and 150 deletions

View file

@ -37,7 +37,9 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
// If your ability/effect supports multi use cases (one time use, static, target pointers) then affectedObjectsSet can be useful:
// * affectedObjectsSet - true on static objects and false on dynamic objects (see rules from 611.2c)
// Full implement example: GainAbilityTargetEffect
protected boolean affectedObjectsSet = false;
//
// is null before being initialized. Any access attempt computes it.
private Boolean affectedObjectsSet = null;
protected List<MageObjectReference> affectedObjectList = new ArrayList<>();
protected boolean temporary = false;
@ -62,7 +64,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
private int effectStartingStepNum = 0; // Some continuous are waiting for the next step of a kind.
// Avoid miscancelling if the start step is of that kind.
public ContinuousEffectImpl(Duration duration, Outcome outcome) {
protected ContinuousEffectImpl(Duration duration, Outcome outcome) {
super(outcome);
this.duration = duration;
this.order = 0;
@ -71,7 +73,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
this.dependendToTypes = EnumSet.noneOf(DependencyType.class);
}
public ContinuousEffectImpl(Duration duration, Layer layer, SubLayer sublayer, Outcome outcome) {
protected ContinuousEffectImpl(Duration duration, Layer layer, SubLayer sublayer, Outcome outcome) {
this(duration, outcome);
this.layer = layer;
this.sublayer = sublayer;
@ -166,6 +168,16 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
@Override
public void init(Ability source, Game game, UUID activePlayerId) {
getTargetPointer().init(game, source);
if (this.affectedObjectsSet == null) {
initAffectedObjectsSet(source);
}
setStartingControllerAndTurnNum(game, source.getControllerId(), activePlayerId);
}
/**
* Computes affectedObjectsSet boolean from the source object.
*/
private void initAffectedObjectsSet(Ability source) {
// 20210112 - 611.2c
// 611.2c If a continuous effect generated by the resolution of a spell or ability modifies the
// characteristics or changes the controller of any objects, the set of objects it affects is
@ -177,6 +189,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
// effect began.If a single continuous effect has parts that modify the characteristics or
// changes the controller of any objects and other parts that dont, the set of objects
// each part applies to is determined independently.
this.affectedObjectsSet = false;
if (AbilityType.STATIC != source.getAbilityType()) {
if (layer != null) {
switch (layer) {
@ -199,7 +212,35 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
this.affectedObjectsSet = true;
}
}
setStartingControllerAndTurnNum(game, source.getControllerId(), activePlayerId);
}
/**
* This is a workaround when trying to access affectObjectsSet during init, before
* ContinuousEffectImpl::init is called.
* <p>
* TODO: should be investigated how to modify all continuous effects to call super.init()
* before doing their own changes. At which point there is no longer need for this
* workaround.
*/
protected boolean getAffectedObjectsSetAtInit(Ability source) {
if (this.affectedObjectsSet == null) {
initAffectedObjectsSet(source);
}
return this.affectedObjectsSet;
}
/**
* Use this getter in other places than overriden calls, most likely the apply method.
*/
protected boolean getAffectedObjectsSet() {
if (this.affectedObjectsSet == null) {
return false;
}
return this.affectedObjectsSet;
}
protected void setAffectedObjectsSet(boolean affectedObjectsSet) {
this.affectedObjectsSet = affectedObjectsSet;
}
@Override