Merge branch 'shahrazad' into 'master'

Shahrazad

See merge request core-developers/forge!3709
This commit is contained in:
Michael Kamensky
2021-02-02 16:00:32 +00:00
16 changed files with 462 additions and 6 deletions

View File

@@ -109,6 +109,7 @@ public class Game {
private final Match match;
private GameStage age = GameStage.BeforeMulligan;
private GameOutcome outcome;
private Game maingame = null;
private final GameView view;
private final Tracker tracker = new Tracker();
@@ -219,7 +220,11 @@ public class Game {
changeZoneLKIInfo.clear();
}
public Game(Iterable<RegisteredPlayer> players0, GameRules rules0, Match match0) { /* no more zones to map here */
public Game(Iterable<RegisteredPlayer> players0, GameRules rules0, Match match0) {
this(players0, rules0, match0, -1);
}
public Game(Iterable<RegisteredPlayer> players0, GameRules rules0, Match match0, int startingLife) { /* no more zones to map here */
rules = rules0;
match = match0;
this.id = nextId();
@@ -243,7 +248,11 @@ public class Game {
allPlayers.add(pl);
ingamePlayers.add(pl);
pl.setStartingLife(psc.getStartingLife());
if (startingLife != -1) {
pl.setStartingLife(startingLife);
} else {
pl.setStartingLife(psc.getStartingLife());
}
pl.setMaxHandSize(psc.getStartingHand());
pl.setStartingHandSize(psc.getStartingHand());
@@ -430,6 +439,14 @@ public class Game {
return outcome;
}
public final Game getMaingame() {
return maingame;
}
public void setMaingame(final Game maingame0) {
maingame = maingame0;
}
public ReplacementHandler getReplacementHandler() {
return replacementHandler;
}
@@ -452,12 +469,16 @@ public class Game {
result.setTurnsPlayed(getPhaseHandler().getTurn());
outcome = result;
match.addGamePlayed(this);
if (maingame == null) {
match.addGamePlayed(this);
}
view.updateGameOver(this);
// The log shall listen to events and generate text internally
fireEvent(new GameEventGameOutcome(result, match.getOutcomes()));
if (maingame == null) {
fireEvent(new GameEventGameOutcome(result, match.getOutcomes()));
}
}
public Zone getZoneOf(final Card card) {
@@ -492,6 +513,14 @@ public class Game {
return cards;
}
public CardCollectionView getCardsInOwnedBy(final Iterable<ZoneType> zones, Player p) {
CardCollection cards = new CardCollection();
for (final ZoneType z : zones) {
cards.addAll(getCardsIncludePhasingIn(z));
}
return CardLists.filter(cards, CardPredicates.isOwner(p));
}
public boolean isCardExiled(final Card c) {
return getCardsIn(ZoneType.Exile).contains(c);
}

View File

@@ -516,6 +516,18 @@ public class GameAction {
c = changeZone(zoneFrom, zoneTo, c, position, cause, params);
// Move card in maingame if take card from subgame
// 720.4a
if (zoneFrom != null && zoneFrom.is(ZoneType.Sideboard) && game.getMaingame() != null) {
Card maingameCard = c.getOwner().getMappingMaingameCard(c);
if (maingameCard != null) {
if (maingameCard.getZone().is(ZoneType.Stack)) {
game.getMaingame().getStack().remove(maingameCard);
}
game.getMaingame().getAction().moveTo(ZoneType.Subgame, maingameCard, null);
}
}
if (zoneFrom == null) {
c.setCastFrom(null);
c.setCastSA(null);

View File

@@ -153,6 +153,7 @@ public enum ApiType {
SkipTurn (SkipTurnEffect.class),
StoreSVar (StoreSVarEffect.class),
StoreMap (StoreMapEffect.class),
Subgame (SubgameEffect.class),
Surveil (SurveilEffect.class),
SwitchBlock (SwitchBlockEffect.class),
Tap (TapEffect.class),

View File

@@ -0,0 +1,254 @@
package forge.game.ability.effects;
import java.util.*;
import com.google.common.collect.Lists;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.GameOutcome;
import forge.game.ability.ApiType;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.event.GameEventSubgameStart;
import forge.game.event.GameEventSubgameEnd;
import forge.game.player.Player;
import forge.game.player.PlayerController;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.util.CardTranslation;
import forge.util.Lang;
import forge.util.Localizer;
import forge.util.collect.FCollectionView;
public class SubgameEffect extends SpellAbilityEffect {
private final Game createSubGame(Game maingame, int startingLife) {
List<RegisteredPlayer> players = Lists.newArrayList();
// Add remaining players to subgame
for (Player p : maingame.getPlayers()) {
players.add(p.getRegisteredPlayer());
}
return new Game(players, maingame.getRules(), maingame.getMatch(), startingLife);
}
private final void setCardsInZone(Player player, final ZoneType zoneType, final CardCollectionView oldCards, boolean addMapping) {
PlayerZone zone = player.getZone(zoneType);
List<Card> newCards = Lists.newArrayList();
for (final Card card : oldCards) {
if (card.isToken() || card.isCopiedSpell()) continue;
Card newCard = Card.fromPaperCard(card.getPaperCard(), player);
newCards.add(newCard);
if (addMapping) {
// Build mapping between maingame cards and subgame cards,
// so when subgame pick a card from maingame (like Wish effects),
// The maingame card will also be moved.
// (Will be move to Subgame zone, which will be added back to libary after subgame ends.)
player.addMaingameCardMapping(newCard, card);
}
}
zone.setCards(newCards);
}
private final void initVariantsZonesSubgame(final Game subgame, final Player maingamePlayer, final Player player) {
PlayerZone com = player.getZone(ZoneType.Command);
RegisteredPlayer registeredPlayer = player.getRegisteredPlayer();
// Vanguard
if (registeredPlayer.getVanguardAvatars() != null) {
for(PaperCard avatar:registeredPlayer.getVanguardAvatars()) {
com.add(Card.fromPaperCard(avatar, player));
}
}
// Commander
List<Card> commanders = Lists.newArrayList();
final CardCollectionView commandCards = maingamePlayer.getCardsIn(ZoneType.Command);
for (final Card card : commandCards) {
if (card.isCommander()) {
Card cmd = Card.fromPaperCard(card.getPaperCard(), player);
if (cmd.hasKeyword("If CARDNAME is your commander, choose a color before the game begins.")) {
List<String> colorChoices = new ArrayList<>(MagicColor.Constant.ONLY_COLORS);
String prompt = Localizer.getInstance().getMessage("lblChooseAColorFor", cmd.getName());
List<String> chosenColors;
SpellAbility cmdColorsa = new SpellAbility.EmptySa(ApiType.ChooseColor, cmd, player);
chosenColors = player.getController().chooseColors(prompt,cmdColorsa, 1, 1, colorChoices);
cmd.setChosenColors(chosenColors);
subgame.getAction().nofityOfValue(cmdColorsa, cmd, Localizer.getInstance().getMessage("lblPlayerPickedChosen", player.getName(), Lang.joinHomogenous(chosenColors)), player);
}
cmd.setCommander(true);
com.add(cmd);
commanders.add(cmd);
com.add(Player.createCommanderEffect(subgame, cmd));
}
}
if (!commanders.isEmpty()) {
player.setCommanders(commanders);
}
// Conspiracies
// 720.2 doesn't mention Conspiracy cards so I guess they don't move
}
private void prepareAllZonesSubgame(final Game maingame, final Game subgame) {
final FCollectionView<Player> players = subgame.getPlayers();
final FCollectionView<Player> maingamePlayers = maingame.getPlayers();
final List<ZoneType> outsideZones = Arrays.asList(ZoneType.Hand, ZoneType.Battlefield,
ZoneType.Graveyard, ZoneType.Exile, ZoneType.Stack, ZoneType.Sideboard, ZoneType.Ante);
for (int i = 0; i < players.size(); i++) {
final Player player = players.get(i);
final Player maingamePlayer = maingamePlayers.get(i);
// Library
setCardsInZone(player, ZoneType.Library, maingamePlayer.getCardsIn(ZoneType.Library), false);
// Sideboard
// 720.4
final CardCollectionView outsideCards = maingame.getCardsInOwnedBy(outsideZones, maingamePlayer);
if (!outsideCards.isEmpty()) {
setCardsInZone(player, ZoneType.Sideboard, outsideCards, true);
// Assign Companion
PlayerController person = player.getController();
Card companion = player.assignCompanion(subgame, person);
// Create an effect that lets you cast your companion from your sideboard
if (companion != null) {
PlayerZone commandZone = player.getZone(ZoneType.Command);
companion = subgame.getAction().moveTo(ZoneType.Command, companion, null);
commandZone.add(Player.createCompanionEffect(subgame, companion));
player.updateZoneForView(commandZone);
}
}
// Schemes
setCardsInZone(player, ZoneType.SchemeDeck, maingamePlayer.getCardsIn(ZoneType.SchemeDeck), false);
// Planes
setCardsInZone(player, ZoneType.PlanarDeck, maingamePlayer.getCardsIn(ZoneType.PlanarDeck), false);
// Vanguard and Commanders
initVariantsZonesSubgame(subgame, maingamePlayer, player);
player.shuffle(null);
player.getZone(ZoneType.SchemeDeck).shuffle();
player.getZone(ZoneType.PlanarDeck).shuffle();
}
}
@Override
public void resolve(SpellAbility sa) {
final Card hostCard = sa.getHostCard();
final Game maingame = hostCard.getGame();
int startingLife = -1;
if (sa.hasParam("StartingLife")) {
startingLife = Integer.parseInt(sa.getParam("StartingLife"));
}
Game subgame = createSubGame(maingame, startingLife);
subgame.setMaingame(maingame);
String startMessage = Localizer.getInstance().getMessage("lblSubgameStart",
CardTranslation.getTranslatedName(hostCard.getName()));
maingame.fireEvent(new GameEventSubgameStart(subgame, startMessage));
prepareAllZonesSubgame(maingame, subgame);
subgame.getAction().startGame(null, null);
subgame.clearCaches();
// Find out winners and losers
final GameOutcome outcome = subgame.getOutcome();
List<Player> winPlayers = Lists.newArrayList();
List<Player> notWinPlayers = Lists.newArrayList();
StringBuilder sbWinners = new StringBuilder();
StringBuilder sbLosers = new StringBuilder();
for (Player p : maingame.getPlayers()) {
if (outcome.isWinner(p.getRegisteredPlayer())) {
if (!winPlayers.isEmpty()) {
sbWinners.append(", ");
}
sbWinners.append(p.getName());
winPlayers.add(p);
} else {
if (!notWinPlayers.isEmpty()) {
sbLosers.append(", ");
}
sbLosers.append(p.getName());
notWinPlayers.add(p);
}
}
if (sa.hasParam("RememberPlayers")) {
final String param = sa.getParam("RememberPlayers");
if (param.equals("Win")) {
for (Player p : winPlayers) {
hostCard.addRemembered(p);
}
} else if (param.equals("NotWin")) {
for (Player p : notWinPlayers) {
hostCard.addRemembered(p);
}
}
}
String endMessage = outcome.isDraw() ? Localizer.getInstance().getMessage("lblSubgameEndDraw") :
Localizer.getInstance().getMessage("lblSubgameEnd", sbWinners.toString(), sbLosers.toString());
maingame.fireEvent(new GameEventSubgameEnd(maingame, endMessage));
// Setup maingame library
final FCollectionView<Player> subgamePlayers = subgame.getRegisteredPlayers();
final FCollectionView<Player> players = maingame.getPlayers();
for (int i = 0; i < players.size(); i++) {
final Player subgamePlayer = subgamePlayers.get(i);
final Player player = players.get(i);
// All cards moved to Subgame Zone will be put into library when subgame ends.
// 720.5
final CardCollectionView movedCards = player.getCardsIn(ZoneType.Subgame);
PlayerZone library = player.getZone(ZoneType.Library);
for (final Card card : movedCards) {
library.add(card);
}
player.getZone(ZoneType.Subgame).removeAllCards(true);
// Move commander if it is no longer in subgame's commander zone
// 720.5c
List<Card> subgameCommanders = Lists.newArrayList();
List<Card> movedCommanders = Lists.newArrayList();
for (final Card card : subgamePlayer.getCardsIn(ZoneType.Command)) {
if (card.isCommander()) {
subgameCommanders.add(card);
}
}
for (final Card card : player.getCardsIn(ZoneType.Command)) {
if (card.isCommander()) {
boolean isInSubgameCommand = false;
for (final Card subCard : subgameCommanders) {
if (card.getName().equals(subCard.getName())) {
isInSubgameCommand = true;
}
}
if (!isInSubgameCommand) {
movedCommanders.add(card);
}
}
}
for (final Card card : movedCommanders) {
maingame.getAction().moveTo(ZoneType.Library, card, null);
}
player.shuffle(sa);
player.getZone(ZoneType.SchemeDeck).shuffle();
player.getZone(ZoneType.PlanarDeck).shuffle();
}
}
}

View File

@@ -0,0 +1,18 @@
package forge.game.event;
import forge.game.Game;
public class GameEventSubgameEnd extends GameEvent {
public final Game maingame;
public final String message;
public GameEventSubgameEnd(Game game, String message0) {
maingame = game;
message = message0;
}
@Override
public <T> T visit(IGameEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -0,0 +1,19 @@
package forge.game.event;
import forge.game.Game;
import forge.game.card.Card;
public class GameEventSubgameStart extends GameEvent {
public final Game subgame;
public final String message;
public GameEventSubgameStart(Game subgame0, String message0) {
subgame = subgame0;
message = message0;
}
@Override
public <T> T visit(IGameEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -44,6 +44,8 @@ public interface IGameEventVisitor<T> {
T visit(GameEventSpellAbilityCast gameEventSpellAbilityCast);
T visit(GameEventSpellResolved event);
T visit(GameEventSpellRemovedFromStack event);
T visit(GameEventSubgameStart event);
T visit(GameEventSubgameEnd event);
T visit(GameEventSurveil event);
T visit(GameEventTokenCreated event);
T visit(GameEventTurnBegan gameEventTurnBegan);
@@ -92,6 +94,8 @@ public interface IGameEventVisitor<T> {
public T visit(GameEventSpellResolved event) { return null; }
public T visit(GameEventSpellAbilityCast event) { return null; }
public T visit(GameEventSpellRemovedFromStack event) { return null; }
public T visit(GameEventSubgameStart event) { return null; }
public T visit(GameEventSubgameEnd event) { return null; }
public T visit(GameEventSurveil event) { return null; }
public T visit(GameEventTokenCreated event) { return null; }
public T visit(GameEventTurnBegan event) { return null; }

View File

@@ -77,7 +77,7 @@ import java.util.concurrent.ConcurrentSkipListMap;
public class Player extends GameEntity implements Comparable<Player> {
public static final List<ZoneType> ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield,
ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante,
ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck));
ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.Subgame));
private final Map<Card, Integer> commanderDamage = Maps.newHashMap();
@@ -141,6 +141,7 @@ public class Player extends GameEntity implements Comparable<Player> {
private final Map<ZoneType, PlayerZone> zones = Maps.newEnumMap(ZoneType.class);
private final Map<Long, Integer> adjustLandPlays = Maps.newHashMap();
private final Set<Long> adjustLandPlaysInfinite = Sets.newHashSet();
private Map<Card, Card> maingameCardsMap = Maps.newHashMap();;
private CardCollection currentPlanes = new CardCollection();
private Set<String> prowl = Sets.newHashSet();
@@ -1922,6 +1923,14 @@ public class Player extends GameEntity implements Comparable<Player> {
return !adjustLandPlaysInfinite.isEmpty();
}
public final void addMaingameCardMapping(Card subgameCard, Card maingameCard) {
maingameCardsMap.put(subgameCard, maingameCard);
}
public final Card getMappingMaingameCard(Card subgameCard) {
return maingameCardsMap.get(subgameCard);
}
public final ManaPool getManaPool() {
return manaPool;
}

View File

@@ -24,6 +24,7 @@ public enum ZoneType {
Ante(false, "lblAnteZone"),
SchemeDeck(true, "lblSchemeDeckZone"),
PlanarDeck(true, "lblPlanarDeckZone"),
Subgame(true, "lblSubgameZone"),
None(true, "lblNoneZone");
public static final List<ZoneType> STATIC_ABILITIES_SOURCE_ZONES = Arrays.asList(Battlefield, Graveyard, Exile, Command/*, Hand*/);

View File

@@ -0,0 +1,10 @@
Name:Shahrazad
ManaCost:W W
Types:Sorcery
A:SP$ Subgame | RememberPlayers$ NotWin | SubAbility$ DBRepeatEachPlayer | SpellDescription$ Players play a Magic subgame, using their libraries as their decks. Each player who doesn't win the subgame loses half their life, rounded up. | StackDescription$ SpellDescription
SVar:DBRepeatEachPlayer:DB$ RepeatEach | RepeatPlayers$ Remembered | ClearRememberedBeforeLoop$ True | RepeatSubAbility$ DBLoseLife | SpellDescription$ Each player who doesn't win the subgame loses half their life, rounded up. | StackDescription$ SpellDescription
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ X | References$ X | Defined$ Player.IsRemembered
SVar:X:PlayerCountRemembered$LifeTotal/HalfUp
AI:RemoveDeck:All
AI:RemoveDeck:Random
Oracle:Players play a Magic subgame, using their libraries as their decks. Each player who doesn't win the subgame loses half their life, rounded up.

View File

@@ -1882,6 +1882,10 @@ lblDoYouWantSacrifice=Opfern durchführen?
lblFaceDownCardCantTurnFaceUp=Verdeckte Karte kann nicht umgedreht werden
#ShuffleEffect.java
lblHaveTargetShuffle=Soll {0} mischen?
#SubgameEffect.java
lblSubgameStart=Subgame started by {0}''s effect.
lblSubgameEnd=Subgame ended. {0} wins. {1} loses.
lblSubgameEndDraw=Subgame ended in a draw.
#SurveilEffect.java
lblDoYouWantSurveil=Möchtest du Überwachen anwenden?
#TapOrUntapAllEffect.java
@@ -1937,6 +1941,7 @@ lblSideboardZone=Sideboard
lblAnteZone=Ante
lblSchemeDeckZone=Verschwörungsdeck
lblPlanarDeckZone=Weltendeck
lblSubgameZone=subgame
lblNoneZone=Keine
#BoosterDraft.java
lblChooseBlock=Wähle Block

View File

@@ -1882,6 +1882,10 @@ lblDoYouWantSacrifice=Do you want to sacrifice?
lblFaceDownCardCantTurnFaceUp=Face-down card can''t turn face up
#ShuffleEffect.java
lblHaveTargetShuffle=Have {0} shuffle?
#SubgameEffect.java
lblSubgameStart=Subgame started by {0}''s effect.
lblSubgameEnd=Subgame ended. {0} wins. {1} loses.
lblSubgameEndDraw=Subgame ended in a draw.
#SurveilEffect.java
lblDoYouWantSurveil=Do you want to surveil?
#TapOrUntapAllEffect.java
@@ -1937,6 +1941,7 @@ lblSideboardZone=sideboard
lblAnteZone=ante
lblSchemeDeckZone=schemedeck
lblPlanarDeckZone=planardeck
lblSubgameZone=subgame
lblNoneZone=none
#BoosterDraft.java
lblChooseBlock=Choose Block

View File

@@ -1882,6 +1882,10 @@ lblDoYouWantSacrifice=¿Quieres sacrificar?
lblFaceDownCardCantTurnFaceUp=La carta boca abajo no se puede girar boca arriba
#ShuffleEffect.java
lblHaveTargetShuffle=¿Ha barajado {0}?
#SubgameEffect.java
lblSubgameStart=Subgame started by {0}''s effect.
lblSubgameEnd=Subgame ended. {0} wins. {1} loses.
lblSubgameEndDraw=Subgame ended in a draw.
#SurveilEffect.java
lblDoYouWantSurveil=¿Quieres vigilar?
#TapOrUntapAllEffect.java
@@ -1937,6 +1941,7 @@ lblSideboardZone=banquillo
lblAnteZone=ante
lblSchemeDeckZone=mazo scheme
lblPlanarDeckZone=mazo planar
lblSubgameZone=subgame
lblNoneZone=ninguna
#BoosterDraft.java
lblChooseBlock=Selecciona Bloque

View File

@@ -1882,6 +1882,10 @@ lblDoYouWantSacrifice=Do you want to sacrifice?
lblFaceDownCardCantTurnFaceUp=Face-down card can''t turn face up
#ShuffleEffect.java
lblHaveTargetShuffle=Have {0} shuffle?
#SubgameEffect.java
lblSubgameStart=Subgame started by {0}''s effect.
lblSubgameEnd=Subgame ended. {0} wins. {1} loses.
lblSubgameEndDraw=Subgame ended in a draw.
#SurveilEffect.java
lblDoYouWantSurveil=Do you want to surveil?
#TapOrUntapAllEffect.java
@@ -1937,6 +1941,7 @@ lblSideboardZone=sideboard
lblAnteZone=ante
lblSchemeDeckZone=schemedeck
lblPlanarDeckZone=planardeck
lblSubgameZone=subgame
lblNoneZone=none
#BoosterDraft.java
lblChooseBlock=Choose Block

View File

@@ -1882,6 +1882,10 @@ lblDoYouWantSacrifice=你想牺牲吗?
lblFaceDownCardCantTurnFaceUp=面朝下的牌不能面朝上
#ShuffleEffect.java
lblHaveTargetShuffle={0}洗牌了吗?
#SubgameEffect.java
lblSubgameStart=Subgame started by {0}''s effect.
lblSubgameEnd=Subgame ended. {0} wins. {1} loses.
lblSubgameEndDraw=Subgame ended in a draw.
#SurveilEffect.java
lblDoYouWantSurveil=你想刺探吗?
#TapOrUntapAllEffect.java
@@ -1937,6 +1941,7 @@ lblSideboardZone=备牌
lblAnteZone=赌注牌区
lblSchemeDeckZone=魔王套牌
lblPlanarDeckZone=时空套牌
lblSubgameZone=subgame
lblNoneZone=
#BoosterDraft.java
lblChooseBlock=选择环境

View File

@@ -34,6 +34,7 @@ import forge.game.GameRules;
import forge.game.GameType;
import forge.game.GameView;
import forge.game.Match;
import forge.game.event.*;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.player.RegisteredPlayer;
@@ -332,7 +333,7 @@ public class HostedMatch {
return isMatchOver;
}
private final class MatchUiEventVisitor implements IUiEventVisitor<Void> {
private final class MatchUiEventVisitor extends IGameEventVisitor.Base<Void> implements IUiEventVisitor<Void> {
@Override
public Void visit(final UiEventBlockerAssigned event) {
for (final PlayerControllerHuman humanController : humanControllers) {
@@ -359,6 +360,69 @@ public class HostedMatch {
return null;
}
@Override
public Void visit(final GameEventSubgameStart event) {
event.subgame.subscribeToEvents(SoundSystem.instance);
event.subgame.subscribeToEvents(visitor);
final GameView gameView = event.subgame.getView();
Runnable switchGameView = new Runnable() {
@Override
public void run() {
for (final Player p : event.subgame.getPlayers()) {
if (p.getController() instanceof PlayerControllerHuman) {
final PlayerControllerHuman humanController = (PlayerControllerHuman) p.getController();
final IGuiGame gui = guis.get(p.getRegisteredPlayer());
humanController.setGui(gui);
gui.setGameView(null);
gui.setGameView(gameView);
gui.setOriginalGameController(p.getView(), humanController);
gui.openView(new TrackableCollection<>(p.getView()));
gui.setGameView(null);
gui.setGameView(gameView);
event.subgame.subscribeToEvents(new FControlGameEventHandler(humanController));
gui.message(event.message);
}
}
}
};
GuiBase.getInterface().invokeInEdtAndWait(switchGameView);
//ensure opponents set properly
for (final Player p : event.subgame.getPlayers()) {
p.updateOpponentsForView();
}
return null;
}
@Override
public Void visit(final GameEventSubgameEnd event) {
final GameView gameView = event.maingame.getView();
Runnable switchGameView = new Runnable() {
@Override
public void run() {
for (final Player p : event.maingame.getPlayers()) {
if (p.getController() instanceof PlayerControllerHuman) {
final PlayerControllerHuman humanController = (PlayerControllerHuman) p.getController();
final IGuiGame gui = guis.get(p.getRegisteredPlayer());
gui.setGameView(null);
gui.setGameView(gameView);
gui.setOriginalGameController(p.getView(), humanController);
gui.openView(new TrackableCollection<>(p.getView()));
gui.setGameView(null);
gui.setGameView(gameView);
gui.updatePhase();
gui.message(event.message);
}
}
}
};
GuiBase.getInterface().invokeInEdtAndWait(switchGameView);
return null;
}
@Subscribe
public void receiveEvent(final UiEvent evt) {
try {
@@ -368,6 +432,16 @@ public class HostedMatch {
e.printStackTrace();
}
}
@Subscribe
public void receiveGameEvent(final GameEvent evt) {
try {
evt.visit(this);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
private void addNextGameDecision(final PlayerControllerHuman controller, final NextGameDecision decision) {