mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
game, refactor: improved player related code, fixed miss reset fields between games like commanderIds (#11081, #11628)
This commit is contained in:
parent
a090a2a9d0
commit
6ac2f44cc1
7 changed files with 92 additions and 71 deletions
|
|
@ -44,7 +44,7 @@ public class TableController {
|
||||||
private static final Logger logger = Logger.getLogger(TableController.class);
|
private static final Logger logger = Logger.getLogger(TableController.class);
|
||||||
|
|
||||||
private final ManagerFactory managerFactory;
|
private final ManagerFactory managerFactory;
|
||||||
private final UUID userId;
|
private final UUID userId; // table owner/creator (null in tourney's table)
|
||||||
private final UUID chatId;
|
private final UUID chatId;
|
||||||
private final String controllerName;
|
private final String controllerName;
|
||||||
private final Table table;
|
private final Table table;
|
||||||
|
|
@ -604,17 +604,17 @@ public class TableController {
|
||||||
if (table.getState() == TableState.STARTING) {
|
if (table.getState() == TableState.STARTING) {
|
||||||
try {
|
try {
|
||||||
if (table.isTournamentSubTable()) {
|
if (table.isTournamentSubTable()) {
|
||||||
logger.info("Tourn. match started id:" + match.getId() + " tournId: " + table.getTournament().getId());
|
logger.info("Tourney MATCH started id:" + match.getId() + " tournId: " + table.getTournament().getId());
|
||||||
} else {
|
} else {
|
||||||
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
logger.info("MATCH started [" + match.getName() + "] " + match.getId() + " (" + user.getName() + ')');
|
logger.info("Single MATCH started [" + match.getName() + "] " + match.getId() + " (" + user.getName() + ')');
|
||||||
logger.debug("- " + match.getOptions().getGameType() + " - " + match.getOptions().getDeckType());
|
logger.debug("- " + match.getOptions().getGameType() + " - " + match.getOptions().getDeckType());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
match.startMatch();
|
match.startMatch();
|
||||||
startGame(null);
|
startGame(null);
|
||||||
} catch (GameException ex) {
|
} catch (GameException e) {
|
||||||
logger.fatal("Error starting match ", ex);
|
logger.fatal("Error starting match: " + e, e);
|
||||||
match.endGame();
|
match.endGame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,14 @@ public class GameController implements GameCallback {
|
||||||
|
|
||||||
public void cleanUp() {
|
public void cleanUp() {
|
||||||
cancelTimeout();
|
cancelTimeout();
|
||||||
for (GameSessionPlayer gameSessionPlayer : getGameSessions()) {
|
|
||||||
gameSessionPlayer.cleanUp();
|
|
||||||
}
|
|
||||||
managerFactory.chatManager().destroyChatSession(chatId);
|
|
||||||
for (PriorityTimer priorityTimer : timers.values()) {
|
for (PriorityTimer priorityTimer : timers.values()) {
|
||||||
priorityTimer.cancel();
|
priorityTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getGameSessions().forEach(GameSessionPlayer::cleanUp);
|
||||||
|
getGameSessionWatchers().forEach(GameSessionWatcher::cleanUp);
|
||||||
|
|
||||||
|
managerFactory.chatManager().destroyChatSession(chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
|
|
|
||||||
|
|
@ -2962,12 +2962,6 @@ public class TestPlayer implements Player {
|
||||||
computerPlayer.init(game);
|
computerPlayer.init(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Game game, boolean testMode) {
|
|
||||||
initialTurns = 0;
|
|
||||||
computerPlayer.init(game, testMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
computerPlayer.reset();
|
computerPlayer.reset();
|
||||||
|
|
|
||||||
|
|
@ -525,11 +525,6 @@ public class PlayerStub implements Player {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Game game, boolean testMode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void useDeck(Deck deck, Game game) {
|
public void useDeck(Deck deck, Game game) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,11 +150,6 @@ public class MatchPlayer implements Serializable {
|
||||||
// this.player = null;
|
// this.player = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanUp() {
|
|
||||||
// Free resources that are not needed after match end
|
|
||||||
this.player = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -370,10 +370,11 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
|
|
||||||
void setAllowBadMoves(boolean allowBadMoves);
|
void setAllowBadMoves(boolean allowBadMoves);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset values before new game, e.g. for next game
|
||||||
|
*/
|
||||||
void init(Game game);
|
void init(Game game);
|
||||||
|
|
||||||
void init(Game game, boolean testMode);
|
|
||||||
|
|
||||||
void useDeck(Deck deck, Game game);
|
void useDeck(Deck deck, Game game);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,21 @@ import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server: basic player implementation, shared for human and AI
|
||||||
|
* <p>
|
||||||
|
* WARNING, if you add new fields then sync it with constructor, restore, reset and init methods
|
||||||
|
*/
|
||||||
public abstract class PlayerImpl implements Player, Serializable {
|
public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
|
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* During some steps we can't play anything
|
||||||
|
*/
|
||||||
|
final static Map<PhaseStep, Step.StepPart> SILENT_PHASES_STEPS = ImmutableMap.<PhaseStep, Step.StepPart>builder().
|
||||||
|
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to cancel waiting requests send to the player
|
* Used to cancel waiting requests send to the player
|
||||||
*/
|
*/
|
||||||
|
|
@ -82,15 +93,18 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
protected final UUID playerId;
|
protected final UUID playerId;
|
||||||
protected String name;
|
protected String name;
|
||||||
protected boolean human;
|
protected boolean human;
|
||||||
|
|
||||||
protected int life;
|
protected int life;
|
||||||
protected boolean wins;
|
protected boolean wins;
|
||||||
protected boolean draws;
|
protected boolean draws;
|
||||||
protected boolean loses;
|
protected boolean loses;
|
||||||
|
|
||||||
protected Library library;
|
protected Library library;
|
||||||
protected Cards sideboard;
|
protected Cards sideboard;
|
||||||
protected Cards hand;
|
protected Cards hand;
|
||||||
protected Graveyard graveyard;
|
protected Graveyard graveyard;
|
||||||
protected Set<UUID> commandersIds = new HashSet<>(0);
|
protected Set<UUID> commandersIds = new HashSet<>(0);
|
||||||
|
|
||||||
protected Abilities<Ability> abilities;
|
protected Abilities<Ability> abilities;
|
||||||
protected Counters counters;
|
protected Counters counters;
|
||||||
protected int landsPlayed;
|
protected int landsPlayed;
|
||||||
|
|
@ -98,6 +112,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
protected int maxHandSize = 7;
|
protected int maxHandSize = 7;
|
||||||
protected int maxAttackedBy = Integer.MAX_VALUE;
|
protected int maxAttackedBy = Integer.MAX_VALUE;
|
||||||
protected ManaPool manaPool;
|
protected ManaPool manaPool;
|
||||||
|
|
||||||
// priority control
|
// priority control
|
||||||
protected boolean passed; // player passed priority
|
protected boolean passed; // player passed priority
|
||||||
protected boolean passedTurn; // F4
|
protected boolean passedTurn; // F4
|
||||||
|
|
@ -142,7 +157,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
protected boolean drawsOnOpponentsTurn = false;
|
protected boolean drawsOnOpponentsTurn = false;
|
||||||
|
|
||||||
protected FilterPermanent sacrificeCostFilter;
|
protected FilterPermanent sacrificeCostFilter;
|
||||||
|
|
||||||
protected final List<AlternativeSourceCosts> alternativeSourceCosts = new ArrayList<>();
|
protected final List<AlternativeSourceCosts> alternativeSourceCosts = new ArrayList<>();
|
||||||
|
|
||||||
protected boolean isGameUnderControl = true;
|
protected boolean isGameUnderControl = true;
|
||||||
|
|
@ -151,9 +165,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
protected Set<UUID> playersUnderYourControl = new HashSet<>();
|
protected Set<UUID> playersUnderYourControl = new HashSet<>();
|
||||||
|
|
||||||
protected Set<UUID> usersAllowedToSeeHandCards = new HashSet<>();
|
protected Set<UUID> usersAllowedToSeeHandCards = new HashSet<>();
|
||||||
|
|
||||||
protected List<UUID> attachments = new ArrayList<>();
|
protected List<UUID> attachments = new ArrayList<>();
|
||||||
|
|
||||||
protected boolean topCardRevealed = false;
|
protected boolean topCardRevealed = false;
|
||||||
|
|
||||||
// 800.4i When a player leaves the game, any continuous effects with durations that last until that player's next turn
|
// 800.4i When a player leaves the game, any continuous effects with durations that last until that player's next turn
|
||||||
|
|
@ -184,12 +196,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
||||||
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* During some steps we can't play anything
|
|
||||||
*/
|
|
||||||
protected final Map<PhaseStep, Step.StepPart> silentPhaseSteps = ImmutableMap.<PhaseStep, Step.StepPart>builder().
|
|
||||||
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build();
|
|
||||||
|
|
||||||
protected PlayerImpl(String name, RangeOfInfluence range) {
|
protected PlayerImpl(String name, RangeOfInfluence range) {
|
||||||
this(UUID.randomUUID());
|
this(UUID.randomUUID());
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
@ -205,7 +211,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PlayerImpl(UUID id) {
|
protected PlayerImpl(UUID id) {
|
||||||
this.playerId = id;
|
this.playerId = id; // TODO: miss another fields init?
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PlayerImpl(final PlayerImpl player) {
|
protected PlayerImpl(final PlayerImpl player) {
|
||||||
|
|
@ -291,6 +297,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
this.designations = CardUtil.deepCopyObject(player.designations);
|
this.designations = CardUtil.deepCopyObject(player.designations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore on rollback
|
||||||
|
*
|
||||||
|
* @param player
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void restore(Player player) {
|
public void restore(Player player) {
|
||||||
this.name = player.getName();
|
this.name = player.getName();
|
||||||
|
|
@ -398,43 +409,35 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
for (Card card : deck.getSideboard()) {
|
for (Card card : deck.getSideboard()) {
|
||||||
sideboard.add(card);
|
sideboard.add(card);
|
||||||
}
|
}
|
||||||
//TODO ARTI initialize extra decks here!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cast e.g. from Karn Liberated to restart the current game
|
|
||||||
*
|
|
||||||
* @param game
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Game game) {
|
public void init(Game game) {
|
||||||
init(game, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Game game, boolean testMode) {
|
|
||||||
this.abort = false;
|
this.abort = false;
|
||||||
if (!testMode) {
|
|
||||||
this.hand.clear();
|
// keep old
|
||||||
this.graveyard.clear();
|
//this.playerId;
|
||||||
}
|
//this.name;
|
||||||
this.library.reset();
|
//this.human;
|
||||||
this.abilities.clear();
|
|
||||||
this.counters.clear();
|
this.life = game.getStartingLife();
|
||||||
this.wins = false;
|
this.wins = false;
|
||||||
this.draws = false;
|
this.draws = false;
|
||||||
this.loses = false;
|
this.loses = false;
|
||||||
this.left = false;
|
|
||||||
// reset is necessary because in tournament player will be used for each round
|
|
||||||
this.quit = false;
|
|
||||||
this.timerTimeout = false;
|
|
||||||
this.idleTimeout = false;
|
|
||||||
|
|
||||||
this.turns = 0;
|
this.library.reset();
|
||||||
this.isGameUnderControl = true;
|
this.sideboard.clear();
|
||||||
this.turnController = this.getId();
|
this.hand.clear();
|
||||||
this.turnControllers.clear();
|
this.graveyard.clear();
|
||||||
this.playersUnderYourControl.clear();
|
this.commandersIds.clear();
|
||||||
|
|
||||||
|
this.abilities.clear();
|
||||||
|
this.counters.clear();
|
||||||
|
this.landsPlayed = 0;
|
||||||
|
this.landsPerTurn = 1;
|
||||||
|
this.maxHandSize = 7;
|
||||||
|
this.maxAttackedBy = Integer.MAX_VALUE;
|
||||||
|
this.getManaPool().init(); // needed to remove mana that not empties on step change from previous game if left
|
||||||
|
|
||||||
this.passed = false;
|
this.passed = false;
|
||||||
this.passedTurn = false;
|
this.passedTurn = false;
|
||||||
|
|
@ -448,19 +451,51 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
this.passedAllTurns = false;
|
this.passedAllTurns = false;
|
||||||
this.justActivatedType = null;
|
this.justActivatedType = null;
|
||||||
|
|
||||||
|
this.turns = 0;
|
||||||
|
this.storedBookmark = -1;
|
||||||
|
this.priorityTimeLeft = Integer.MAX_VALUE;
|
||||||
|
this.bufferTimeLeft = 0;
|
||||||
|
|
||||||
|
// reset is necessary because in tournament player will be used for each round
|
||||||
|
this.left = false;
|
||||||
|
this.quit = false;
|
||||||
|
this.timerTimeout = false;
|
||||||
|
this.idleTimeout = false;
|
||||||
|
|
||||||
|
//this.range; // must keep
|
||||||
|
this.inRange.clear();
|
||||||
|
|
||||||
|
//this.isTestMode // must keep
|
||||||
this.canGainLife = true;
|
this.canGainLife = true;
|
||||||
this.canLoseLife = true;
|
this.canLoseLife = true;
|
||||||
|
this.payLifeCostLevel = PayLifeCostLevel.allAbilities;
|
||||||
|
this.loseByZeroOrLessLife = true;
|
||||||
|
this.canPlayCardsFromGraveyard = true;
|
||||||
|
this.drawsOnOpponentsTurn = false;
|
||||||
|
|
||||||
|
this.sacrificeCostFilter = null;
|
||||||
|
this.alternativeSourceCosts.clear();
|
||||||
|
|
||||||
|
this.isGameUnderControl = true;
|
||||||
|
this.turnController = null;
|
||||||
|
this.turnControllers.clear();
|
||||||
|
this.playersUnderYourControl.clear();
|
||||||
|
|
||||||
|
//this.usersAllowedToSeeHandCards; // must keep
|
||||||
|
this.attachments.clear();
|
||||||
this.topCardRevealed = false;
|
this.topCardRevealed = false;
|
||||||
this.payManaMode = false;
|
|
||||||
this.setLife(game.getStartingLife(), game, null);
|
|
||||||
this.setReachedNextTurnAfterLeaving(false);
|
|
||||||
|
|
||||||
|
this.reachedNextTurnAfterLeaving = false;
|
||||||
this.clearCastSourceIdManaCosts();
|
this.clearCastSourceIdManaCosts();
|
||||||
|
this.payManaMode = false;
|
||||||
|
|
||||||
this.getManaPool().init(); // needed to remove mana that not empties on step change from previous game if left
|
// must keep
|
||||||
this.phyrexianColors = null;
|
//this.userData;
|
||||||
|
//this.matchPlayer;
|
||||||
|
|
||||||
this.designations.clear();
|
this.designations.clear();
|
||||||
|
this.phyrexianColors = null;
|
||||||
|
this.availableTriggeredManaList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -4246,7 +4281,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
if (game.getStep() == null) { // happens at the start of the game
|
if (game.getStep() == null) { // happens at the start of the game
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (Entry<PhaseStep, Step.StepPart> phaseStep : silentPhaseSteps.entrySet()) {
|
for (Entry<PhaseStep, Step.StepPart> phaseStep : SILENT_PHASES_STEPS.entrySet()) {
|
||||||
if (game.getPhase() != null
|
if (game.getPhase() != null
|
||||||
&& game.getPhase().getStep() != null
|
&& game.getPhase().getStep() != null
|
||||||
&& phaseStep.getKey() == game.getPhase().getStep().getType()) {
|
&& phaseStep.getKey() == game.getPhase().getStep().getType()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue