mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
* Fixed wrong timer handling while other player controlled a player's turn. Attackers now marked with blue frame. Playable cards have a violet frame. If a player has to select cards from hand, the possible cards are marked yellow now. Discard of multiple cards now marks already selected cards and happens in one selection.
This commit is contained in:
parent
194efe6237
commit
67479bb5a4
20 changed files with 205 additions and 163 deletions
|
|
@ -110,6 +110,7 @@ import static mage.constants.PhaseStep.FIRST_COMBAT_DAMAGE;
|
|||
import static mage.constants.PhaseStep.UNTAP;
|
||||
import static mage.constants.PhaseStep.UPKEEP;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.constants.Zone;
|
||||
import mage.remote.Session;
|
||||
import mage.view.AbilityPickerView;
|
||||
import mage.view.CardView;
|
||||
|
|
@ -813,6 +814,26 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
*/
|
||||
public void pickTarget(String message, CardsView cardView, GameView gameView, Set<UUID> targets, boolean required, Map<String, Serializable> options, int messageId) {
|
||||
ShowCardsDialog dialog = null;
|
||||
if (options != null && options.containsKey("targetZone")) {
|
||||
if (Zone.HAND.equals(options.get("targetZone"))) { // mark selectable target cards in hand
|
||||
List<UUID> choosen = null;
|
||||
if (options.containsKey("chosen")) {
|
||||
choosen = (List<UUID>) options.get("chosen");
|
||||
}
|
||||
for(CardView card: gameView.getHand().values()) {
|
||||
if (targets == null || targets.isEmpty()) {
|
||||
card.setPlayable(false);
|
||||
card.setChoosable(true);
|
||||
} else if (targets.contains(card.getId())) {
|
||||
card.setPlayable(false);
|
||||
card.setChoosable(true);
|
||||
}
|
||||
if (choosen != null && choosen.contains(card.getId())) {
|
||||
card.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateGame(gameView);
|
||||
Map<String, Serializable> options0 = options == null ? new HashMap<String, Serializable>() : options;
|
||||
if (cardView != null && cardView.size() > 0) {
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
this.avatar.setTopText(priorityTimeValue);
|
||||
this.timerLabel.setText(priorityTimeValue);
|
||||
}
|
||||
if (player.hasPriority()) {
|
||||
if (player.isTimerActive()) {
|
||||
this.timer.resume();
|
||||
} else {
|
||||
this.timer.pause();
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
private boolean isSelected;
|
||||
private boolean isPlayable;
|
||||
private boolean isChoosable;
|
||||
private boolean canAttack;
|
||||
private boolean canAttack;
|
||||
private boolean showCastingCost;
|
||||
private boolean hasImage = false;
|
||||
private float alpha = 1.0f;
|
||||
|
|
@ -501,19 +501,17 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
} else if (isChoosable) {
|
||||
g2d.setColor(new Color(250, 250, 0, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
if (isPlayable) {
|
||||
g2d.setColor(new Color(250, 250, 0, 200));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
} else if (isPlayable) {
|
||||
g2d.setColor(new Color(153, 102, 204, 200));
|
||||
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset , cardWidth , cardHeight , cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
if (canAttack) {
|
||||
g2d.setColor(new Color(255, 0, 0, 230));
|
||||
g2d.setColor(new Color(0, 0, 255, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
|
||||
//TODO:uncomment
|
||||
/*
|
||||
if (gameCard.isAttacking()) {
|
||||
|
|
@ -589,7 +587,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
ptText.setVisible(showText);
|
||||
|
||||
int titleX = Math.round(cardWidth * (20f / 480));
|
||||
int titleY = Math.round(cardHeight * (9f / 680)) + 10;
|
||||
int titleY = Math.round(cardHeight * (9f / 680)) + 10; // TODO: Set to 0 if it's a card selection with small card offset (ike library search)
|
||||
titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY);
|
||||
|
||||
Dimension ptSize = ptText.getPreferredSize();
|
||||
|
|
@ -803,6 +801,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
this.isPlayable = card.isPlayable();
|
||||
this.isChoosable = card.isChoosable();
|
||||
this.canAttack = card.isCanAttack();
|
||||
this.isSelected = card.isSelected();
|
||||
|
||||
boolean updateImage = !gameCard.getName().equals(card.getName()) || gameCard.isFaceDown() != card.isFaceDown(); // update after e.g. turning a night/day card
|
||||
this.gameCard = card;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ public class CardView extends SimpleCardView {
|
|||
|
||||
protected boolean isPlayable;
|
||||
protected boolean isChoosable;
|
||||
protected boolean selected;
|
||||
protected boolean canAttack;
|
||||
|
||||
public CardView(Card card) {
|
||||
|
|
@ -695,6 +696,18 @@ public class CardView extends SimpleCardView {
|
|||
public boolean isChoosable() {
|
||||
return isChoosable;
|
||||
}
|
||||
|
||||
public void setChoosable(boolean isChoosable) {
|
||||
this.isChoosable = isChoosable;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public boolean isCanAttack() {
|
||||
return canAttack;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public class PlayerView implements Serializable {
|
|||
private final int handCount;
|
||||
private final boolean isActive;
|
||||
private final boolean hasPriority;
|
||||
private final boolean timerActive;
|
||||
private final boolean hasLeft;
|
||||
private final ManaPoolView manaPool;
|
||||
private final CardsView graveyard = new CardsView();
|
||||
|
|
@ -87,6 +88,10 @@ public class PlayerView implements Serializable {
|
|||
this.manaPool = new ManaPoolView(player.getManaPool());
|
||||
this.isActive = (player.getId().equals(state.getActivePlayerId()));
|
||||
this.hasPriority = player.getId().equals(state.getPriorityPlayerId());
|
||||
this.priorityTimeLeft = player.getPriorityTimeLeft();
|
||||
this.timerActive = (this.hasPriority && player.isGameUnderControl()) ||
|
||||
(player.getPlayersUnderYourControl().contains(state.getPriorityPlayerId()));
|
||||
|
||||
this.hasLeft = player.hasLeft();
|
||||
for (Card card: player.getGraveyard().getCards(game)) {
|
||||
graveyard.put(card.getId(), new CardView(card));
|
||||
|
|
@ -138,7 +143,6 @@ public class PlayerView implements Serializable {
|
|||
}
|
||||
|
||||
this.statesSavedSize = player.getStoredBookmark();
|
||||
this.priorityTimeLeft = player.getPriorityTimeLeft();
|
||||
|
||||
this.passedTurn = player.getPassedTurn();
|
||||
this.passedUntilEndOfTurn = player.getPassedUntilEndOfTurn();
|
||||
|
|
@ -244,6 +248,10 @@ public class PlayerView implements Serializable {
|
|||
return hasPriority;
|
||||
}
|
||||
|
||||
public boolean isTimerActive() {
|
||||
return timerActive;
|
||||
}
|
||||
|
||||
public boolean isPassedTurn() {
|
||||
return passedTurn;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ import java.util.concurrent.*;
|
|||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class ComputerPlayer6 extends ComputerPlayer implements Player {
|
||||
public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||
|
||||
private static final transient org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ComputerPlayer6.class);
|
||||
private static final ExecutorService pool = Executors.newFixedThreadPool(1);
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
|
|||
|
||||
@Override
|
||||
public boolean priority(Game game) {
|
||||
game.resumeTimer(playerId);
|
||||
game.resumeTimer(getTurnControlledBy());
|
||||
boolean result = priorityPlay(game);
|
||||
game.pauseTimer(playerId);
|
||||
game.pauseTimer(getTurnControlledBy());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (int i = unplayable.size() - 1; i >= 0; i--) {
|
||||
if (target.canTarget(unplayable.values().toArray(new Card[0])[i].getId(), game)) {
|
||||
target.add(unplayable.values().toArray(new Card[0])[i].getId(), game);
|
||||
return true;
|
||||
if (target.isChosen()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -173,7 +175,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (int i = 0; i < hand.size(); i++) {
|
||||
if (target.canTarget(hand.toArray(new UUID[0])[i], game)) {
|
||||
target.add(hand.toArray(new UUID[0])[i], game);
|
||||
return true;
|
||||
if (target.isChosen()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -749,10 +753,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
|
||||
@Override
|
||||
public boolean priority(Game game) {
|
||||
game.resumeTimer(playerId);
|
||||
game.resumeTimer(getTurnControlledBy());
|
||||
log.debug("priority");
|
||||
boolean result = priorityPlay(game);
|
||||
game.pauseTimer(playerId);
|
||||
game.pauseTimer(getTurnControlledBy());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,13 +83,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
protected static FilterBlockingCreature filterBlock = new FilterBlockingCreature();
|
||||
protected static final Choice replacementEffectChoice = new ChoiceImpl(true);
|
||||
|
||||
private static final Map<String, Serializable> staticOptions = new HashMap<>();
|
||||
|
||||
private static final Logger log = Logger.getLogger(HumanPlayer.class);
|
||||
|
||||
static {
|
||||
replacementEffectChoice.setMessage("Choose replacement effect to resolve first");
|
||||
staticOptions.put("UI.right.btn.text", "Done");
|
||||
}
|
||||
|
||||
protected HashSet<String> autoSelectReplacementEffects = new HashSet<>();
|
||||
|
|
@ -106,7 +102,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
protected void waitForResponse(Game game) {
|
||||
response.clear();
|
||||
log.debug("Waiting response from player: " + getId());
|
||||
game.resumeTimer(playerId);
|
||||
game.resumeTimer(getTurnControlledBy());
|
||||
synchronized(response) {
|
||||
try {
|
||||
response.wait();
|
||||
|
|
@ -114,7 +110,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
game.pauseTimer(playerId);
|
||||
game.pauseTimer(getTurnControlledBy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -236,7 +232,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
|
||||
updateGameStatePriority("choose(5)", game);
|
||||
updateGameStatePriority("choose(5)", game);
|
||||
if (options == null) {
|
||||
options = new HashMap<>();
|
||||
}
|
||||
while (!abort) {
|
||||
Set<UUID> targetIds = target.possibleTargets(sourceId, playerId, game);
|
||||
if (targetIds == null || targetIds.isEmpty()) {
|
||||
|
|
@ -246,7 +245,11 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (target.getTargets().size() >= target.getNumberOfTargets()) {
|
||||
required = false;
|
||||
}
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), targetIds, required, options);
|
||||
|
||||
List<UUID> chosen = target.getTargets();
|
||||
options.put("chosen", (Serializable)chosen);
|
||||
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), targetIds, required, getOptions(target, options));
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (!targetIds.contains(response.getUUID())) {
|
||||
|
|
@ -263,16 +266,24 @@ public class HumanPlayer extends PlayerImpl {
|
|||
MageObject object = game.getObject(sourceId);
|
||||
if (object instanceof Ability) {
|
||||
if (target.canTarget(response.getUUID(), (Ability) object, game)) {
|
||||
target.add(response.getUUID(), game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), (Ability)object, game);
|
||||
if(target.doneChosing()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (target.canTarget(response.getUUID(), game)) {
|
||||
target.add(response.getUUID(), game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), null, game);
|
||||
if(target.doneChosing()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -299,7 +310,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (possibleTargets.isEmpty() || target.getTargets().size() >= target.getNumberOfTargets()) {
|
||||
required = false;
|
||||
}
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), possibleTargets, required, getOptions(target));
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), possibleTargets, required, getOptions(target, null));
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (possibleTargets.contains(response.getUUID())) {
|
||||
|
|
@ -337,8 +348,15 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
private Map<String, Serializable> getOptions(Target target) {
|
||||
return target.getTargets().size() >= target.getNumberOfTargets() ? staticOptions : null;
|
||||
private Map<String, Serializable> getOptions(Target target, Map<String, Serializable> options ) {
|
||||
if (options == null) {
|
||||
options = new HashMap<>();
|
||||
}
|
||||
if (target.getTargets().size() >= target.getNumberOfTargets() && !options.containsKey("UI.right.btn.text")) {
|
||||
options.put("UI.right.btn.text", "Done");
|
||||
}
|
||||
options.put("targetZone", target.getZone());
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -358,11 +376,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (target.getTargets().size() >= target.getNumberOfTargets()) {
|
||||
required = false;
|
||||
}
|
||||
Map<String, Serializable> options = getOptions(target);
|
||||
if (options == null) {
|
||||
options = new HashMap<>(1);
|
||||
}
|
||||
|
||||
Map<String, Serializable> options = getOptions(target, null);
|
||||
List<UUID> chosen = target.getTargets();
|
||||
options.put("chosen", (Serializable)chosen);
|
||||
List<UUID> choosable = new ArrayList<>();
|
||||
|
|
@ -416,7 +430,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (target.getTargets().size() >= target.getNumberOfTargets()) {
|
||||
required = false;
|
||||
}
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, null);
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, getOptions(target, null));
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
|
|
@ -441,7 +455,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
|
||||
updateGameStatePriority("chooseTargetAmount", game);
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.possibleTargets(source==null?null:source.getSourceId(), playerId, game), target.isRequired(source), null);
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(),
|
||||
target.possibleTargets(source==null?null:source.getSourceId(), playerId, game),
|
||||
target.isRequired(source),
|
||||
getOptions(target, null));
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target.canTarget(response.getUUID(), source, game)) {
|
||||
|
|
@ -870,7 +887,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
protected void selectCombatGroup(UUID defenderId, UUID blockerId, Game game) {
|
||||
updateGameStatePriority("selectCombatGroup", game);
|
||||
TargetAttackingCreature target = new TargetAttackingCreature();
|
||||
game.fireSelectTargetEvent(playerId, "Select attacker to block", target.possibleTargets(null, playerId, game), false, null);
|
||||
game.fireSelectTargetEvent(playerId, "Select attacker to block", target.possibleTargets(null, playerId, game), false, getOptions(target, null));
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
// do nothing
|
||||
|
|
@ -1128,8 +1145,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
|
||||
protected void updateGameStatePriority(String methodName, Game game) {
|
||||
log.debug("Setting game priority to " + getId() + " [" + methodName + "]");
|
||||
game.getState().setPriorityPlayerId(getId());
|
||||
if (game.getState().getPriorityPlayerId() != null) { // don't do it if priority was set to null before (e.g. discard in cleanaup)
|
||||
log.debug("Setting game priority to " + getId() + " [" + methodName + "]");
|
||||
game.getState().setPriorityPlayerId(getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import mage.interfaces.callback.ClientCallback;
|
|||
import mage.players.net.UserData;
|
||||
import mage.server.draft.DraftSession;
|
||||
import mage.server.game.GameManager;
|
||||
import mage.server.game.GameSession;
|
||||
import mage.server.game.GameSessionPlayer;
|
||||
import mage.server.tournament.TournamentSession;
|
||||
import mage.server.util.SystemUtil;
|
||||
import mage.view.TableClientMessage;
|
||||
|
|
@ -68,7 +68,7 @@ public class User {
|
|||
private final String host;
|
||||
private final Date connectionTime;
|
||||
private final Map<UUID, Table> tables;
|
||||
private final Map<UUID, GameSession> gameSessions;
|
||||
private final Map<UUID, GameSessionPlayer> gameSessions;
|
||||
private final Map<UUID, DraftSession> draftSessions;
|
||||
private final Map<UUID, TournamentSession> tournamentSessions;
|
||||
private final Map<UUID, TournamentSession> constructing;
|
||||
|
|
@ -269,7 +269,7 @@ public class User {
|
|||
entry.getValue().update();
|
||||
}
|
||||
|
||||
for (Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
|
||||
for (Entry<UUID, GameSessionPlayer> entry: gameSessions.entrySet()) {
|
||||
gameStarted(entry.getValue().getGameId(), entry.getKey());
|
||||
entry.getValue().init();
|
||||
GameManager.getInstance().sendPlayerString(entry.getValue().getGameId(), userId, "");
|
||||
|
|
@ -290,7 +290,7 @@ public class User {
|
|||
}
|
||||
}
|
||||
|
||||
public void addGame(UUID playerId, GameSession gameSession) {
|
||||
public void addGame(UUID playerId, GameSessionPlayer gameSession) {
|
||||
gameSessions.put(playerId, gameSession);
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +336,7 @@ public class User {
|
|||
|
||||
public void remove(DisconnectReason reason) {
|
||||
logger.debug("REMOVE " + getName() + " Game sessions: " + gameSessions.size() );
|
||||
for (GameSession gameSession: gameSessions.values()) {
|
||||
for (GameSessionPlayer gameSession: gameSessions.values()) {
|
||||
logger.debug("-- kill game session of gameId: " + gameSession.getGameId() );
|
||||
gameSession.quitGame();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ public class GameController implements GameCallback {
|
|||
private static final ExecutorService gameExecutor = ThreadExecutor.getInstance().getGameExecutor();
|
||||
private static final Logger logger = Logger.getLogger(GameController.class);
|
||||
|
||||
private ConcurrentHashMap<UUID, GameSession> gameSessions = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<UUID, GameWatcher> watchers = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<UUID, GameSessionPlayer> gameSessions = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<UUID, GameSessionWatcher> watchers = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<UUID, PriorityTimer> timers = new ConcurrentHashMap<>();
|
||||
|
||||
private ConcurrentHashMap<UUID, UUID> userPlayerMap;
|
||||
|
|
@ -300,10 +300,10 @@ public class GameController implements GameCallback {
|
|||
logger.fatal("Player not found - playerId: " +playerId);
|
||||
return;
|
||||
}
|
||||
GameSession gameSession = gameSessions.get(playerId);
|
||||
GameSessionPlayer gameSession = gameSessions.get(playerId);
|
||||
String joinType;
|
||||
if (gameSession == null) {
|
||||
gameSession = new GameSession(game, userId, playerId, useTimeout);
|
||||
gameSession = new GameSessionPlayer(game, userId, playerId, useTimeout);
|
||||
gameSessions.put(playerId, gameSession);
|
||||
gameSession.setUserData(user.getUserData());
|
||||
joinType = "joined";
|
||||
|
|
@ -318,7 +318,7 @@ public class GameController implements GameCallback {
|
|||
|
||||
private synchronized void startGame() {
|
||||
if (gameFuture == null) {
|
||||
for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
|
||||
for (final Entry<UUID, GameSessionPlayer> entry: gameSessions.entrySet()) {
|
||||
if (!entry.getValue().init()) {
|
||||
logger.fatal("Unable to initialize client");
|
||||
//TODO: generate client error message
|
||||
|
|
@ -363,7 +363,7 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
GameWatcher gameWatcher = new GameWatcher(userId, game, false);
|
||||
GameSessionWatcher gameWatcher = new GameSessionWatcher(userId, game, false);
|
||||
watchers.put(userId, gameWatcher);
|
||||
gameWatcher.init();
|
||||
user.addGameWatchInfo(game.getId());
|
||||
|
|
@ -400,7 +400,7 @@ public class GameController implements GameCallback {
|
|||
public void quitMatch(UUID userId) {
|
||||
UUID playerId = getPlayerId(userId);
|
||||
if (playerId != null) {
|
||||
GameSession gameSession = gameSessions.get(playerId);
|
||||
GameSessionPlayer gameSession = gameSessions.get(playerId);
|
||||
if (gameSession != null) {
|
||||
gameSession.quitGame();
|
||||
}
|
||||
|
|
@ -456,7 +456,7 @@ public class GameController implements GameCallback {
|
|||
if (grantingPlayer != null) {
|
||||
if (!grantingPlayer.getUsersAllowedToSeeHandCards().contains(userIdRequester)) {
|
||||
if (grantingPlayer.isHuman()) {
|
||||
GameSession gameSession = gameSessions.get(userIdGranter);
|
||||
GameSessionPlayer gameSession = gameSessions.get(userIdGranter);
|
||||
if (gameSession != null) {
|
||||
UUID requestingPlayer = getPlayerId(userIdRequester);
|
||||
if (requestingPlayer == null || !requestingPlayer.equals(grantingPlayer.getId())) { // don't allow request for your own cards
|
||||
|
|
@ -527,11 +527,11 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
|
||||
public void endGame(final String message) throws MageException {
|
||||
for (final GameSession gameSession: gameSessions.values()) {
|
||||
for (final GameSessionPlayer gameSession: gameSessions.values()) {
|
||||
gameSession.gameOver(message);
|
||||
gameSession.removeGame();
|
||||
}
|
||||
for (final GameWatcher gameWatcher: watchers.values()) {
|
||||
for (final GameSessionWatcher gameWatcher: watchers.values()) {
|
||||
gameWatcher.gameOver(message);
|
||||
}
|
||||
TableManager.getInstance().endGame(tableId);
|
||||
|
|
@ -601,10 +601,10 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (final GameSession gameSession: gameSessions.values()) {
|
||||
for (final GameSessionPlayer gameSession: gameSessions.values()) {
|
||||
gameSession.update();
|
||||
}
|
||||
for (final GameWatcher gameWatcher: watchers.values()) {
|
||||
for (final GameSessionWatcher gameWatcher: watchers.values()) {
|
||||
gameWatcher.update();
|
||||
}
|
||||
}
|
||||
|
|
@ -613,7 +613,7 @@ public class GameController implements GameCallback {
|
|||
Table table = TableManager.getInstance().getTable(tableId);
|
||||
if (table != null) {
|
||||
if (table.getMatch() != null) {
|
||||
for (final GameSession gameSession: gameSessions.values()) {
|
||||
for (final GameSessionPlayer gameSession: gameSessions.values()) {
|
||||
gameSession.endGameInfo(table);
|
||||
}
|
||||
}
|
||||
|
|
@ -741,12 +741,12 @@ public class GameController implements GameCallback {
|
|||
message.append(game.getStep().getType().toString()).append(" - ");
|
||||
}
|
||||
message.append("Waiting for ").append(game.getPlayer(playerId).getName());
|
||||
for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
|
||||
for (final Entry<UUID, GameSessionPlayer> entry: gameSessions.entrySet()) {
|
||||
if (!entry.getKey().equals(playerId)) {
|
||||
entry.getValue().inform(message.toString());
|
||||
}
|
||||
}
|
||||
for (final GameWatcher watcher: watchers.values()) {
|
||||
for (final GameSessionWatcher watcher: watchers.values()) {
|
||||
watcher.inform(message.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -761,7 +761,7 @@ public class GameController implements GameCallback {
|
|||
return;
|
||||
}
|
||||
final String message = new StringBuilder(game.getStep().getType().toString()).append(" - Waiting for ").append(controller.getName()).toString();
|
||||
for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
|
||||
for (final Entry<UUID, GameSessionPlayer> entry: gameSessions.entrySet()) {
|
||||
boolean skip = false;
|
||||
for (UUID uuid : players) {
|
||||
if (entry.getKey().equals(uuid)) {
|
||||
|
|
@ -773,7 +773,7 @@ public class GameController implements GameCallback {
|
|||
entry.getValue().inform(message);
|
||||
}
|
||||
}
|
||||
for (final GameWatcher watcher: watchers.values()) {
|
||||
for (final GameSessionWatcher watcher: watchers.values()) {
|
||||
watcher.inform(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -795,7 +795,7 @@ public class GameController implements GameCallback {
|
|||
for (StackTraceElement e: ex.getStackTrace()) {
|
||||
sb.append(e.toString()).append("\n");
|
||||
}
|
||||
for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
|
||||
for (final Entry<UUID, GameSessionPlayer> entry: gameSessions.entrySet()) {
|
||||
entry.getValue().gameError(sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -898,7 +898,7 @@ public class GameController implements GameCallback {
|
|||
void execute(UUID player);
|
||||
}
|
||||
|
||||
private GameSession getGameSession(UUID playerId) {
|
||||
private GameSessionPlayer getGameSession(UUID playerId) {
|
||||
if (!timers.isEmpty()) {
|
||||
Player player = game.getState().getPlayer(playerId);
|
||||
PriorityTimer timer = timers.get(playerId);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import mage.game.Table;
|
|||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.players.Player;
|
||||
import mage.players.net.UserData;
|
||||
import mage.server.Main;
|
||||
import mage.server.User;
|
||||
import mage.server.UserManager;
|
||||
import mage.server.util.ConfigSettings;
|
||||
|
|
@ -66,9 +67,9 @@ import org.apache.log4j.Logger;
|
|||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class GameSession extends GameWatcher {
|
||||
public class GameSessionPlayer extends GameSessionWatcher {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(GameSession.class);
|
||||
private static final Logger logger = Logger.getLogger(GameSessionPlayer.class);
|
||||
|
||||
private final UUID playerId;
|
||||
private final boolean useTimeout;
|
||||
|
|
@ -79,7 +80,7 @@ public class GameSession extends GameWatcher {
|
|||
|
||||
private UserData userData;
|
||||
|
||||
public GameSession(Game game, UUID userId, UUID playerId, boolean useTimeout) {
|
||||
public GameSessionPlayer(Game game, UUID userId, UUID playerId, boolean useTimeout) {
|
||||
super(userId, game, true);
|
||||
this.playerId = playerId;
|
||||
this.useTimeout = useTimeout;
|
||||
|
|
@ -228,7 +229,8 @@ public class GameSession extends GameWatcher {
|
|||
}
|
||||
}
|
||||
},
|
||||
ConfigSettings.getInstance().getMaxSecondsIdle(), TimeUnit.SECONDS
|
||||
Main.isTestMode() ? 3600 :ConfigSettings.getInstance().getMaxSecondsIdle(),
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -269,7 +271,9 @@ public class GameSession extends GameWatcher {
|
|||
player.setUserData(this.userData);
|
||||
GameView gameView = new GameView(game.getState(), game, playerId, null);
|
||||
gameView.setHand(new CardsView(player.getHand().getCards(game)));
|
||||
gameView.setCanPlayInHand(player.getPlayableInHand(game));
|
||||
if (gameView.getPriorityPlayerName().equals(player.getName())) {
|
||||
gameView.setCanPlayInHand(player.getPlayableInHand(game));
|
||||
}
|
||||
|
||||
processControlledPlayers(player, gameView);
|
||||
processWatchedHands(userId, gameView);
|
||||
|
|
@ -47,16 +47,16 @@ import org.apache.log4j.Logger;
|
|||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class GameWatcher {
|
||||
public class GameSessionWatcher {
|
||||
|
||||
protected final static Logger logger = Logger.getLogger(GameWatcher.class);
|
||||
protected final static Logger logger = Logger.getLogger(GameSessionWatcher.class);
|
||||
|
||||
protected UUID userId;
|
||||
protected Game game;
|
||||
protected boolean killed = false;
|
||||
protected boolean isPlayer;
|
||||
|
||||
public GameWatcher(UUID userId, Game game, boolean isPlayer) {
|
||||
public GameSessionWatcher(UUID userId, Game game, boolean isPlayer) {
|
||||
this.userId = userId;
|
||||
this.game = game;
|
||||
this.isPlayer = isPlayer;
|
||||
|
|
@ -34,7 +34,7 @@ import java.util.UUID;
|
|||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class MindRot extends mage.sets.magic2010.MindRot {
|
||||
public class MindRot extends mage.sets.tenth.MindRot {
|
||||
|
||||
public MindRot(UUID ownerId) {
|
||||
super(ownerId);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class CragganwickCrematorEffect extends OneShotEffect {
|
|||
|
||||
public CragganwickCrematorEffect() {
|
||||
super(Outcome.Neutral);
|
||||
this.staticText = "discard a card at random. If you discard a creature card this way, <this> deals damage equal to that card's power to target player";
|
||||
this.staticText = "discard a card at random. If you discard a creature card this way, {this} deals damage equal to that card's power to target player";
|
||||
}
|
||||
|
||||
public CragganwickCrematorEffect(final CragganwickCrematorEffect effect) {
|
||||
|
|
@ -97,20 +97,14 @@ class CragganwickCrematorEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player you = game.getPlayer(source.getControllerId());
|
||||
Player targetedPlayer = game.getPlayer(source.getFirstTarget());
|
||||
if (you != null) {
|
||||
Effect discardEffect = new DiscardTargetEffect(1, true, true);
|
||||
discardEffect.setTargetPointer(new FixedTarget(you.getId()));
|
||||
if (discardEffect.apply(game, source)) {
|
||||
Card discardedCard = game.getCard(this.getTargetPointer().getFirst(game, source));
|
||||
if (discardedCard != null
|
||||
&& discardedCard.getCardType().contains(CardType.CREATURE)) {
|
||||
int damage = discardedCard.getPower().getValue();
|
||||
if (targetedPlayer != null) {
|
||||
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (you != null && targetedPlayer != null) {
|
||||
Card discardedCard = targetedPlayer.discardOne(true, source, game);
|
||||
if (discardedCard != null
|
||||
&& discardedCard.getCardType().contains(CardType.CREATURE)) {
|
||||
int damage = discardedCard.getPower().getValue();
|
||||
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,13 +31,10 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.Mode;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
|
|
@ -48,7 +45,6 @@ public class DiscardTargetEffect extends OneShotEffect {
|
|||
|
||||
protected DynamicValue amount;
|
||||
protected boolean randomDiscard;
|
||||
protected boolean setTargetPointer;
|
||||
|
||||
public DiscardTargetEffect(DynamicValue amount) {
|
||||
this(amount, false);
|
||||
|
|
@ -64,22 +60,22 @@ public class DiscardTargetEffect extends OneShotEffect {
|
|||
this(new StaticValue(amount));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param amount amount of cards to discard
|
||||
* @param randomDiscard discard the cards by random
|
||||
*
|
||||
*/
|
||||
public DiscardTargetEffect(int amount, boolean randomDiscard) {
|
||||
this(new StaticValue(amount), randomDiscard);
|
||||
}
|
||||
|
||||
public DiscardTargetEffect(int amount, boolean randomDiscard, boolean setTargetPointer) {
|
||||
super(Outcome.Discard);
|
||||
this.randomDiscard = randomDiscard;
|
||||
this.amount = new StaticValue(amount);
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
public DiscardTargetEffect(final DiscardTargetEffect effect) {
|
||||
super(effect);
|
||||
this.amount = effect.amount.copy();
|
||||
this.randomDiscard = effect.randomDiscard;
|
||||
this.setTargetPointer = effect.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -91,23 +87,7 @@ public class DiscardTargetEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
if (player != null) {
|
||||
if (randomDiscard) {
|
||||
int maxAmount = Math.min(amount.calculate(game, source, this), player.getHand().size());
|
||||
for (int i = 0; i < maxAmount; i++) {
|
||||
Card card = player.getHand().getRandom(game);
|
||||
if (card != null) {
|
||||
player.discard(card, source, game);
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : source.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.discard(amount.calculate(game, source, this), source, game);
|
||||
}
|
||||
|
||||
player.discard(amount.calculate(game, source, this), randomDiscard, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
int deduction = 1;
|
||||
if (freeMulligans > 0) {
|
||||
if (usedFreeMulligans != null && usedFreeMulligans.containsKey(player.getId())) {
|
||||
int used = usedFreeMulligans.get(player.getId()).intValue();
|
||||
int used = usedFreeMulligans.get(player.getId());
|
||||
if (used < freeMulligans ) {
|
||||
deduction = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ import mage.target.TargetCard;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetDiscard;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.common.BloodthirstWatcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -563,6 +564,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public void setGameUnderYourControl(boolean value) {
|
||||
this.isGameUnderControl = value;
|
||||
if (isGameUnderControl) {
|
||||
this.turnController = getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -623,12 +627,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public void discardToMax(Game game) {
|
||||
if (hand.size() > this.maxHandSize) {
|
||||
game.informPlayers(new StringBuilder(getName()).append(" discards down to ").append(this.maxHandSize).append(this.maxHandSize == 1?" hand card":" hand cards").toString());
|
||||
while (isInGame() && hand.size() > this.maxHandSize) {
|
||||
TargetDiscard target = new TargetDiscard(playerId);
|
||||
target.setTargetName(new StringBuilder(" card to discard (").append(hand.size() - this.maxHandSize).append(" in total)").toString());
|
||||
choose(Outcome.Discard, target, null, game);
|
||||
discard(hand.get(target.getFirstTarget(), game), null, game);
|
||||
}
|
||||
discard(hand.size() - this.maxHandSize, null, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -682,21 +681,17 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
return discardedCards;
|
||||
}
|
||||
int numDiscarded = 0;
|
||||
while (isInGame() && numDiscarded < amount) {
|
||||
if (this.getHand().size() == 0) {
|
||||
break;
|
||||
if (random) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Card card = this.getHand().getRandom(game);
|
||||
discardedCards.add(card);
|
||||
discard(card, source, game);
|
||||
}
|
||||
Card card;
|
||||
if (random) {
|
||||
card = this.getHand().getRandom(game);
|
||||
} else {
|
||||
TargetDiscard target = new TargetDiscard(playerId);
|
||||
choose(Outcome.Discard, target, source.getSourceId(), game);
|
||||
card = this.getHand().get(target.getFirstTarget(), game);
|
||||
}
|
||||
if (card != null) {
|
||||
numDiscarded++;
|
||||
} else {
|
||||
TargetDiscard target = new TargetDiscard(amount, amount, new FilterCard(CardUtil.numberToText(amount, "a") + " card" + (amount > 1 ?"s":"")), playerId);
|
||||
choose(Outcome.Discard, target, source == null?null:source.getSourceId(), game);
|
||||
for (UUID cardId: target.getTargets()) {
|
||||
Card card = this.getHand().get(cardId, game);
|
||||
discardedCards.add(card);
|
||||
discard(card, source, game);
|
||||
}
|
||||
|
|
@ -2253,36 +2248,40 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return playable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of card ids that are currently playable.<br>
|
||||
* Used to mark the playable cards in GameView
|
||||
*
|
||||
* @return A Set of cardIds that are playable
|
||||
* @see mage.server.GameSessionPlayer#getGameView()
|
||||
*
|
||||
* @param game
|
||||
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Set<UUID> getPlayableInHand(Game game) {
|
||||
Set<UUID> playable = new HashSet<>();
|
||||
if (!shouldSkipGettingPlayable(game)) {
|
||||
// for clean_up phase show all cards
|
||||
if (game.getPhase() != null && PhaseStep.CLEANUP.equals(game.getPhase().getStep().getType())) {
|
||||
for (Card card: hand.getCards(game)) {
|
||||
playable.add(card.getId());
|
||||
}
|
||||
} else {
|
||||
ManaOptions available = getManaAvailable(game);
|
||||
available.addMana(manaPool.getMana());
|
||||
ManaOptions available = getManaAvailable(game);
|
||||
available.addMana(manaPool.getMana());
|
||||
|
||||
for (Card card : hand.getCards(game)) {
|
||||
for (ActivatedAbility ability : card.getAbilities().getPlayableAbilities(Zone.HAND)) {
|
||||
if (ability instanceof PlayLandAbility) {
|
||||
if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canPlay(ability, available, card, game)) {
|
||||
playable.add(card.getId());
|
||||
for (Card card : hand.getCards(game)) {
|
||||
for (ActivatedAbility ability : card.getAbilities().getPlayableAbilities(Zone.HAND)) {
|
||||
if (ability instanceof PlayLandAbility) {
|
||||
if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||
if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, card, game)) {
|
||||
playable.add(card.getId());
|
||||
break;
|
||||
}
|
||||
if (canPlay(ability, available, card, game)) {
|
||||
playable.add(card.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||
if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, card, game)) {
|
||||
playable.add(card.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
package mage.target;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class TargetDiscard extends TargetCard {
|
|||
super(minNumTargets, maxNumTargets, Zone.HAND, filter);
|
||||
this.filter.add(new OwnerIdPredicate(playerId));
|
||||
this.playerId = playerId;
|
||||
this.targetName = "card to discard";
|
||||
this.targetName = this.filter.getMessage() + " to discard";
|
||||
}
|
||||
|
||||
public TargetDiscard(final TargetDiscard target) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue