diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index 5c2ec948877..a10572b810a 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -141,6 +141,12 @@ public class CallbackClientImpl implements CallbackClient { panel.hideGame(); } } + else if (callback.getMethod().equals("gameError")) { + GamePanel panel = frame.getGame(callback.getObjectId()); + if (panel != null) { + panel.modalMessage((String) callback.getData()); + } + } else if (callback.getMethod().equals("gameAsk")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = frame.getGame(callback.getObjectId()); diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 30b94868b8e..dcbd414069e 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -117,6 +117,9 @@ public class GameController implements GameCallback { case REVEAL: revealCards(event.getMessage(), event.getCards()); break; + case ERROR: + error(event.getMessage()); + break; } } catch (MageException ex) { logger.fatal("Table event listener error ", ex); @@ -416,6 +419,12 @@ public class GameController implements GameCallback { } } + private void error(String message) { + for (final Entry entry: gameSessions.entrySet()) { + entry.getValue().gameError(message); + } + } + private GameView getGameView() { return new GameView(game.getState(), game); } diff --git a/Mage.Server/src/main/java/mage/server/game/GameWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameWatcher.java index 872f73dbbd2..6f8ceb38d67 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameWatcher.java @@ -95,6 +95,15 @@ public class GameWatcher { } } + public void gameError(final String message) { + if (!killed) { + Session session = SessionManager.getInstance().getSession(sessionId); + if (session != null) { + session.fireCallback(new ClientCallback("gameError", gameId, message)); + } + } + } + protected void handleRemoteException(RemoteException ex) { logger.fatal("GameWatcher error", ex); GameManager.getInstance().kill(gameId, sessionId); diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 3814ac404fc..ed35457bc4d 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -131,7 +131,8 @@ public interface Game extends MageItem, Serializable { public void fireInformEvent(String message); public void fireUpdatePlayersEvent(); public void informPlayers(String message); - + public void fireErrorEvent(String message); + //game event methods public void fireEvent(GameEvent event); public boolean replaceEvent(GameEvent event); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 7e4322b1301..ee3fb259b12 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -519,6 +519,9 @@ public abstract class GameImpl> implements Game, Serializa state.getPlayerList().getNext(); } } + } catch (Exception ex) { + logger.fatal("Game exception ", ex); + this.fireErrorEvent("Game exception occurred: " + ex.getMessage() + " - " + ex.getStackTrace()[0]); } finally { resetLKI(); } @@ -833,6 +836,11 @@ public abstract class GameImpl> implements Game, Serializa tableEventSource.fireTableEvent(EventType.UPDATE, null, this); } + @Override + public void fireErrorEvent(String message) { + tableEventSource.fireTableEvent(EventType.ERROR, message, this); + } + @Override public Players getPlayers() { return state.getPlayers(); diff --git a/Mage/src/mage/game/events/TableEvent.java b/Mage/src/mage/game/events/TableEvent.java index aea35cadeb8..c0b75938421 100644 --- a/Mage/src/mage/game/events/TableEvent.java +++ b/Mage/src/mage/game/events/TableEvent.java @@ -45,7 +45,8 @@ import mage.game.tournament.TournamentPairing; public class TableEvent extends EventObject implements ExternalEvent, Serializable { public enum EventType { - UPDATE, INFO, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END} + UPDATE, INFO, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR + } private Game game; private Draft draft; diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 1a036ce1e0d..940bcf93d86 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -58,9 +58,14 @@ public class SpellStack extends Stack { //resolve top StackObject public void resolve(Game game) { - StackObject top = this.peek(); - top.resolve(game); - this.remove(top); + StackObject top = null; + try { + top = this.peek(); + top.resolve(game); + } finally { + if (top != null) + this.remove(top); + } } public void checkTriggers(GameEvent event, Game game) {