server: fixed game freeze on leaving player before finish target selection (example: Nethergoyf, close #13567, related to #11285)

This commit is contained in:
Oleg Agafonov 2025-05-07 17:27:26 +04:00
parent 99ca1e6029
commit 62aa310a4f
2 changed files with 26 additions and 13 deletions

View file

@ -6,7 +6,6 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.CostsImpl; import mage.abilities.costs.CostsImpl;
import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount;
import mage.abilities.effects.common.continuous.SetBasePowerToughnessPlusOneSourceEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessPlusOneSourceEffect;
import mage.abilities.hint.HintUtils; import mage.abilities.hint.HintUtils;
@ -100,7 +99,11 @@ class NethergoyfTarget extends TargetCardInYourGraveyard {
types.size() + " of 4", types.size() + " of 4",
types.size() >= 4 ? Color.GREEN : Color.RED types.size() >= 4 ? Color.GREEN : Color.RED
); );
text += " [" + types.stream().map(CardType::toString).collect(Collectors.joining(", ")) + "])"; String info = types.stream().map(CardType::toString).collect(Collectors.joining(", "));
if (!info.isEmpty()) {
text += " [" + info + "]";
}
text += ")";
return text; return text;
} }

View file

@ -52,11 +52,17 @@ public class Targets extends ArrayList<Target> implements Copyable<Targets> {
} }
public boolean choose(Outcome outcome, UUID playerId, UUID sourceId, Ability source, Game game) { public boolean choose(Outcome outcome, UUID playerId, UUID sourceId, Ability source, Game game) {
if (this.size() > 0) { Player player = game.getPlayer(playerId);
if (!canChoose(playerId, source, game)) { if (player == null) {
return false; return false;
} }
while (!isChosen(game)) {
if (this.size() > 0 && !this.doneChoosing(game)) {
do {
if (!player.canRespond() || !canChoose(playerId, source, game)) {
return false;
}
Target target = this.getUnchosen(game).get(0); Target target = this.getUnchosen(game).get(0);
if (!target.choose(outcome, playerId, sourceId, source, game)) { if (!target.choose(outcome, playerId, sourceId, source, game)) {
return false; return false;
@ -67,13 +73,17 @@ public class Targets extends ArrayList<Target> implements Copyable<Targets> {
} }
public boolean chooseTargets(Outcome outcome, UUID playerId, Ability source, boolean noMana, Game game, boolean canCancel) { public boolean chooseTargets(Outcome outcome, UUID playerId, Ability source, boolean noMana, Game game, boolean canCancel) {
if (this.size() > 0) { Player player = game.getPlayer(playerId);
if (!canChoose(playerId, source, game)) { if (player == null) {
return false; return false;
} }
if (this.size() > 0 && !this.doneChoosing(game)) {
do {
if (!player.canRespond() || !canChoose(playerId, source, game)) {
return false;
}
//int state = game.bookmarkState();
while (!isChosen(game)) {
Target target = this.getUnchosen(game).get(0); Target target = this.getUnchosen(game).get(0);
UUID targetController = playerId; UUID targetController = playerId;