mirror of
https://github.com/correl/mage.git
synced 2025-04-09 09:11:05 -09:00
* Game: fixed priority lost on rollback (example: game skips to next step instead current step after a rollback error);
* Game: added game logs on rollback error;
This commit is contained in:
parent
c8445c31a3
commit
1d60c2039b
4 changed files with 26 additions and 11 deletions
Mage/src/main/java/mage
|
@ -452,7 +452,7 @@ public interface Game extends MageItem, Serializable, Copyable<Game> {
|
||||||
|
|
||||||
int bookmarkState();
|
int bookmarkState();
|
||||||
|
|
||||||
void restoreState(int bookmark, String context);
|
GameState restoreState(int bookmark, String context);
|
||||||
|
|
||||||
void removeBookmark(int bookmark);
|
void removeBookmark(int bookmark);
|
||||||
|
|
||||||
|
|
|
@ -846,9 +846,10 @@ public abstract class GameImpl implements Game {
|
||||||
*
|
*
|
||||||
* @param bookmark
|
* @param bookmark
|
||||||
* @param context additional information for error message
|
* @param context additional information for error message
|
||||||
|
* @return current restored state (if all fine)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void restoreState(int bookmark, String context) {
|
public GameState restoreState(int bookmark, String context) {
|
||||||
if (!simulation && !this.hasEnded()) { // if player left or game is over no undo is possible - this could lead to wrong winner
|
if (!simulation && !this.hasEnded()) { // if player left or game is over no undo is possible - this could lead to wrong winner
|
||||||
if (bookmark != 0) {
|
if (bookmark != 0) {
|
||||||
if (!savedStates.contains(bookmark - 1)) {
|
if (!savedStates.contains(bookmark - 1)) {
|
||||||
|
@ -863,11 +864,12 @@ public abstract class GameImpl implements Game {
|
||||||
if (restore != null) {
|
if (restore != null) {
|
||||||
state.restore(restore);
|
state.restore(restore);
|
||||||
playerList.setCurrent(state.getPlayerByOrderId());
|
playerList.setCurrent(state.getPlayerByOrderId());
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1469,7 +1471,7 @@ public abstract class GameImpl implements Game {
|
||||||
public void playPriority(UUID activePlayerId, boolean resuming) {
|
public void playPriority(UUID activePlayerId, boolean resuming) {
|
||||||
int errorContinueCounter = 0;
|
int errorContinueCounter = 0;
|
||||||
infiniteLoopCounter = 0;
|
infiniteLoopCounter = 0;
|
||||||
int bookmark = 0;
|
int rollbackBookmark = 0;
|
||||||
clearAllBookmarks();
|
clearAllBookmarks();
|
||||||
try {
|
try {
|
||||||
applyEffects();
|
applyEffects();
|
||||||
|
@ -1484,8 +1486,8 @@ public abstract class GameImpl implements Game {
|
||||||
Player player;
|
Player player;
|
||||||
while (!isPaused() && !checkIfGameIsOver()) {
|
while (!isPaused() && !checkIfGameIsOver()) {
|
||||||
try {
|
try {
|
||||||
if (bookmark == 0) {
|
if (rollbackBookmark == 0) {
|
||||||
bookmark = bookmarkState();
|
rollbackBookmark = bookmarkState();
|
||||||
}
|
}
|
||||||
player = getPlayer(state.getPlayerList().get());
|
player = getPlayer(state.getPlayerList().get());
|
||||||
state.setPriorityPlayerId(player.getId());
|
state.setPriorityPlayerId(player.getId());
|
||||||
|
@ -1542,12 +1544,22 @@ public abstract class GameImpl implements Game {
|
||||||
logger.fatal(ex.getStackTrace());
|
logger.fatal(ex.getStackTrace());
|
||||||
}
|
}
|
||||||
this.fireErrorEvent("Game exception occurred: ", ex);
|
this.fireErrorEvent("Game exception occurred: ", ex);
|
||||||
restoreState(bookmark, "Game exception: " + ex.getMessage());
|
|
||||||
bookmark = 0;
|
// rollback game to prev state
|
||||||
|
GameState restoredState = restoreState(rollbackBookmark, "Game exception: " + ex.getMessage());
|
||||||
|
rollbackBookmark = 0;
|
||||||
|
|
||||||
if (errorContinueCounter > 15) {
|
if (errorContinueCounter > 15) {
|
||||||
throw new MageException("Iterated player priority after game exception too often, game ends! Last error:\n "
|
throw new MageException("Iterated player priority after game exception too often, game ends! Last error:\n "
|
||||||
+ ex.getMessage());
|
+ ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (restoredState != null) {
|
||||||
|
this.informPlayers(String.format("Auto-restored to %s due game error: %s", restoredState, ex.getMessage()));
|
||||||
|
} else {
|
||||||
|
logger.error("Can't auto-restore to prev state.");
|
||||||
|
}
|
||||||
|
|
||||||
Player activePlayer = this.getPlayer(getActivePlayerId());
|
Player activePlayer = this.getPlayer(getActivePlayerId());
|
||||||
if (activePlayer != null && !activePlayer.isTestsMode()) {
|
if (activePlayer != null && !activePlayer.isTestsMode()) {
|
||||||
errorContinueCounter++;
|
errorContinueCounter++;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import mage.filter.FilterCard;
|
||||||
import mage.filter.FilterMana;
|
import mage.filter.FilterMana;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.GameState;
|
||||||
import mage.game.Graveyard;
|
import mage.game.Graveyard;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
import mage.game.combat.CombatGroup;
|
import mage.game.combat.CombatGroup;
|
||||||
|
@ -541,11 +542,12 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
|
|
||||||
void resetStoredBookmark(Game game);
|
void resetStoredBookmark(Game game);
|
||||||
|
|
||||||
default void restoreState(int bookmark, String text, Game game) {
|
default GameState restoreState(int bookmark, String text, Game game) {
|
||||||
game.restoreState(bookmark, text);
|
GameState state = game.restoreState(bookmark, text);
|
||||||
if (getStoredBookmark() >= bookmark) {
|
if (getStoredBookmark() >= bookmark) {
|
||||||
resetStoredBookmark(game);
|
resetStoredBookmark(game);
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void revealCards(Ability source, Cards cards, Game game);
|
void revealCards(Ability source, Cards cards, Game game);
|
||||||
|
|
|
@ -294,13 +294,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
this.human = player.isHuman();
|
this.human = player.isHuman();
|
||||||
this.life = player.getLife();
|
this.life = player.getLife();
|
||||||
|
|
||||||
|
this.passed = player.isPassed();
|
||||||
|
|
||||||
// Don't restore more global states. If restored they are probably cause for unintended draws (https://github.com/magefree/mage/issues/1205).
|
// Don't restore more global states. If restored they are probably cause for unintended draws (https://github.com/magefree/mage/issues/1205).
|
||||||
// this.wins = player.hasWon();
|
// this.wins = player.hasWon();
|
||||||
// this.loses = player.hasLost();
|
// this.loses = player.hasLost();
|
||||||
// this.left = player.hasLeft();
|
// this.left = player.hasLeft();
|
||||||
// this.quit = player.hasQuit();
|
// this.quit = player.hasQuit();
|
||||||
// Makes no sense to restore
|
// Makes no sense to restore
|
||||||
// this.passed = player.isPassed();
|
|
||||||
// this.priorityTimeLeft = player.getPriorityTimeLeft();
|
// this.priorityTimeLeft = player.getPriorityTimeLeft();
|
||||||
// this.idleTimeout = player.hasIdleTimeout();
|
// this.idleTimeout = player.hasIdleTimeout();
|
||||||
// this.timerTimeout = player.hasTimerTimeout();
|
// this.timerTimeout = player.hasTimerTimeout();
|
||||||
|
|
Loading…
Add table
Reference in a new issue