Prevent P/T flickering for good

This commit is contained in:
drdev
2014-10-13 05:06:25 +00:00
parent f8a54eed14
commit a8457ea75b
3 changed files with 47 additions and 3 deletions

View File

@@ -48,6 +48,7 @@ import forge.game.zone.PlayerZoneBattlefield;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.trackable.TrackableObject;
import forge.util.Aggregates;
import forge.util.CollectionSuppliers;
import forge.util.Expressions;
@@ -659,6 +660,7 @@ public class GameAction {
final boolean refreeze = game.getStack().isFrozen();
game.getStack().setFrozen(true);
TrackableObject.freeze(); //prevent views flickering during while updating for state-based effects
// do this multiple times, sometimes creatures/permanents will survive
// when they shouldn't
@@ -750,14 +752,16 @@ public class GameAction {
}
} // for q=0;q<9
TrackableObject.unfreeze();
if (runEvents) {
game.fireEvent(new GameEventCardStatsChanged(allAffectedCards));
}
checkGameOverCondition();
if (game.getAge() != GameStage.Play)
if (game.getAge() != GameStage.Play) {
return Collections.emptySet();
}
game.getTriggerHandler().resetActiveTriggers();
if (!refreeze) {
game.getStack().unfreezeStack();

View File

@@ -1,5 +1,6 @@
package forge.trackable;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
@@ -7,6 +8,32 @@ import forge.game.IIdentifiable;
//base class for objects that can be tracked and synced between game server and GUI
public abstract class TrackableObject implements IIdentifiable {
private static int freezeCounter = 0;
public static void freeze() {
freezeCounter++;
}
public static void unfreeze() {
if (freezeCounter == 0 || --freezeCounter > 0 || delayedPropChanges.isEmpty()) {
return;
}
//after being unfrozen, ensure all changes delayed during freeze are now applied
for (DelayedPropChange change : delayedPropChanges) {
change.object.set(change.prop, change.value);
}
delayedPropChanges.clear();
}
private static class DelayedPropChange {
private final TrackableObject object;
private final TrackableProperty prop;
private final Object value;
private DelayedPropChange(TrackableObject object0, TrackableProperty prop0, Object value0) {
object = object0;
prop = prop0;
value = value0;
}
}
private static final ArrayList<DelayedPropChange> delayedPropChanges = new ArrayList<DelayedPropChange>();
private final int id;
private final EnumMap<TrackableProperty, Object> props;
private final EnumSet<TrackableProperty> changedProps;
@@ -36,6 +63,10 @@ public abstract class TrackableObject implements IIdentifiable {
}
protected <T> void set(TrackableProperty key, T value) {
if (freezeCounter > 0 && key.respectFreeze()) { //if trackable objects currently frozen, queue up delayed prop change
delayedPropChanges.add(new DelayedPropChange(this, key, value));
return;
}
if (value == null || value.equals(key.getDefaultValue())) {
if (props.remove(key) != null) {
changedProps.add(key);

View File

@@ -52,7 +52,7 @@ public enum TrackableProperty {
Haunting(TrackableTypes.CardViewType),
MustBlockCards(TrackableTypes.CardViewCollectionType),
PairedWith(TrackableTypes.CardViewType),
CurrentState(TrackableTypes.CardStateViewType),
CurrentState(TrackableTypes.CardStateViewType, false), //can't respect freeze, otherwise card constructor can crash
AlternateState(TrackableTypes.CardStateViewType),
//Card State
@@ -140,9 +140,18 @@ public enum TrackableProperty {
Phase(TrackableTypes.EnumType(PhaseType.class));
private final TrackableType<?> type;
private final boolean respectFreeze;
private TrackableProperty(TrackableType<?> type0) {
this(type0, true);
}
private TrackableProperty(TrackableType<?> type0, boolean respectFreeze0) {
type = type0;
respectFreeze = respectFreeze0;
}
public boolean respectFreeze() {
return respectFreeze;
}
@SuppressWarnings("unchecked")