mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
GUI: stack - added card icon with targets info (announced and triggered targets, target choices);
This commit is contained in:
parent
caf35c88c9
commit
9ad456239e
6 changed files with 152 additions and 81 deletions
|
|
@ -45,7 +45,7 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public class CardView extends SimpleCardView {
|
||||
|
||||
|
|
@ -441,48 +441,6 @@ public class CardView extends SimpleCardView {
|
|||
controlledByOwner = false;
|
||||
}
|
||||
}
|
||||
|
||||
// card icons for permanents on battlefield
|
||||
|
||||
// icon - all from abilities
|
||||
permanent.getAbilities(game).forEach(ability -> {
|
||||
this.cardIcons.addAll(ability.getIcons(game));
|
||||
});
|
||||
|
||||
// icon - face down
|
||||
if (permanent.isFaceDown(game)) {
|
||||
this.cardIcons.add(CardIconImpl.FACE_DOWN);
|
||||
}
|
||||
|
||||
// icon - commander
|
||||
if (game != null) {
|
||||
Player owner = game.getPlayer(game.getOwnerId(permanent));
|
||||
if (owner != null && game.isCommanderObject(owner, permanent)) {
|
||||
this.cardIcons.add(CardIconImpl.COMMANDER);
|
||||
}
|
||||
}
|
||||
|
||||
// icon - ring-bearer
|
||||
if (permanent.isRingBearer()) {
|
||||
this.cardIcons.add(CardIconImpl.RINGBEARER);
|
||||
}
|
||||
|
||||
// icon - restrictions (search it in card hints)
|
||||
List<String> restricts = new ArrayList<>();
|
||||
this.rules.forEach(r -> {
|
||||
if (r.startsWith(HintUtils.HINT_ICON_RESTRICT)
|
||||
|| r.startsWith(HintUtils.HINT_ICON_REQUIRE)) {
|
||||
restricts.add(r
|
||||
.replace(HintUtils.HINT_ICON_RESTRICT, "")
|
||||
.replace(HintUtils.HINT_ICON_REQUIRE, "")
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
});
|
||||
if (!restricts.isEmpty()) {
|
||||
restricts.sort(String::compareTo);
|
||||
this.cardIcons.add(new CardIconImpl(CardIconType.OTHER_HAS_RESTRICTIONS, String.join("<br>", restricts)));
|
||||
}
|
||||
} else {
|
||||
if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
|
|
@ -499,25 +457,6 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
}
|
||||
|
||||
// card icons for any permanents and cards
|
||||
if (game != null) {
|
||||
// x cost
|
||||
Zone cardZone = game.getState().getZone(card.getId());
|
||||
if (card.getManaCost().containsX()
|
||||
&& card.getSpellAbility() != null
|
||||
&& (cardZone.match(Zone.BATTLEFIELD) || cardZone.match(Zone.STACK))) {
|
||||
int costX;
|
||||
if (card instanceof Permanent) {
|
||||
// permanent on battlefield (can show x icon multiple turns, so use end_game source)
|
||||
costX = ManacostVariableValue.END_GAME.calculate(game, card.getSpellAbility(), null);
|
||||
} else {
|
||||
// other like Stack (can show x icon on stack only, so use normal source)
|
||||
costX = ManacostVariableValue.REGULAR.calculate(game, card.getSpellAbility(), null);
|
||||
}
|
||||
this.cardIcons.add(CardIconImpl.variableCost(costX));
|
||||
}
|
||||
}
|
||||
|
||||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = new ArrayList<>(card.getCardType(game));
|
||||
|
|
@ -647,6 +586,141 @@ public class CardView extends SimpleCardView {
|
|||
|
||||
// Get starting defense
|
||||
this.startingDefense = CardUtil.convertLoyaltyOrDefense(card.getStartingDefense());
|
||||
|
||||
// add card icons at the end, so it will have full card view data
|
||||
this.generateCardIcons(null, card, game);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate card icons for current object (support card, permanent or stack ability)
|
||||
*
|
||||
* @param ability only for stack ability, all other must use null
|
||||
* @param object original card/permanent/source
|
||||
*/
|
||||
final protected void generateCardIcons(Ability ability, MageObject object, Game game) {
|
||||
if (object instanceof Permanent) {
|
||||
this.generateCardIconsForPermanent((Permanent) object, game);
|
||||
}
|
||||
this.generateCardIconsForAny(object, ability, game);
|
||||
}
|
||||
|
||||
private void generateCardIconsForPermanent(Permanent permanent, Game game) {
|
||||
// card icons for permanents on battlefield
|
||||
if (game == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// icon - all from abilities
|
||||
permanent.getAbilities(game).forEach(ability -> {
|
||||
this.cardIcons.addAll(ability.getIcons(game));
|
||||
});
|
||||
|
||||
// icon - face down
|
||||
if (permanent.isFaceDown(game)) {
|
||||
this.cardIcons.add(CardIconImpl.FACE_DOWN);
|
||||
}
|
||||
|
||||
// icon - commander
|
||||
Player owner = game.getPlayer(game.getOwnerId(permanent));
|
||||
if (owner != null && game.isCommanderObject(owner, permanent)) {
|
||||
this.cardIcons.add(CardIconImpl.COMMANDER);
|
||||
}
|
||||
|
||||
// icon - ring-bearer
|
||||
if (permanent.isRingBearer()) {
|
||||
this.cardIcons.add(CardIconImpl.RINGBEARER);
|
||||
}
|
||||
|
||||
// icon - restrictions (search it in card hints)
|
||||
List<String> restricts = new ArrayList<>();
|
||||
this.rules.forEach(r -> {
|
||||
if (r.startsWith(HintUtils.HINT_ICON_RESTRICT)
|
||||
|| r.startsWith(HintUtils.HINT_ICON_REQUIRE)) {
|
||||
restricts.add(r
|
||||
.replace(HintUtils.HINT_ICON_RESTRICT, "")
|
||||
.replace(HintUtils.HINT_ICON_REQUIRE, "")
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
});
|
||||
if (!restricts.isEmpty()) {
|
||||
restricts.sort(String::compareTo);
|
||||
this.cardIcons.add(new CardIconImpl(CardIconType.OTHER_HAS_RESTRICTIONS, String.join("<br>", restricts)));
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCardIconsForAny(MageObject object, Ability ability, Game game) {
|
||||
if (game == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Card showCard = (object instanceof Card) ? (Card) object : null;
|
||||
|
||||
Zone showZone;
|
||||
if (ability instanceof StackAbility) {
|
||||
showZone = Zone.STACK;
|
||||
} else {
|
||||
showZone = game.getState().getZone(object.getId());
|
||||
}
|
||||
if (showZone == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ability showAbility;
|
||||
if (ability != null) {
|
||||
showAbility = ability;
|
||||
} else if (showCard != null) {
|
||||
showAbility = showCard.getSpellAbility();
|
||||
} else {
|
||||
showAbility = null;
|
||||
}
|
||||
|
||||
// icon - x cost
|
||||
if (showCard != null
|
||||
&& showCard.getManaCost().containsX()
|
||||
&& showAbility != null
|
||||
&& (showZone.match(Zone.BATTLEFIELD) || showZone.match(Zone.STACK))) {
|
||||
int costX;
|
||||
if (showCard instanceof Permanent) {
|
||||
// permanent on battlefield (can show x icon multiple turns, so use end_game source)
|
||||
costX = ManacostVariableValue.END_GAME.calculate(game, showAbility, null);
|
||||
} else {
|
||||
// other like Stack (can show x icon on stack only, so use normal source)
|
||||
costX = ManacostVariableValue.REGULAR.calculate(game, showAbility, null);
|
||||
}
|
||||
this.cardIcons.add(CardIconImpl.variableCost(costX));
|
||||
}
|
||||
|
||||
// icon - targets in stack
|
||||
if (showZone.match(Zone.STACK) && this.getTargets() != null && !this.getTargets().isEmpty()) {
|
||||
List<String> targets = new ArrayList<>();
|
||||
this.getTargets()
|
||||
.stream()
|
||||
.map(t -> {
|
||||
String info;
|
||||
MageObject targetObject = game.getObject(t);
|
||||
if (targetObject != null) {
|
||||
info = targetObject.getIdName();
|
||||
} else {
|
||||
Player targetPlayer = game.getPlayer(t);
|
||||
if (targetPlayer != null) {
|
||||
info = targetPlayer.getName();
|
||||
} else {
|
||||
info = "Unknown";
|
||||
}
|
||||
}
|
||||
return info;
|
||||
})
|
||||
.sorted()
|
||||
.forEach(targets::add);
|
||||
|
||||
this.cardIcons.add(new CardIconImpl(
|
||||
CardIconType.OTHER_HAS_TARGETS,
|
||||
String.format("Has %d target(s). Move mouse over card to see target arrows:", this.getTargets().size())
|
||||
+ "<br><br>" + String.join("<br>", targets),
|
||||
"T-" + this.getTargets().size()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public CardView(MageObject object, Game game) {
|
||||
|
|
@ -1350,6 +1424,7 @@ public class CardView extends SimpleCardView {
|
|||
public boolean isExtraDeckCard() {
|
||||
return this.extraDeckCard;
|
||||
}
|
||||
|
||||
public boolean isLand() {
|
||||
return cardTypes.contains(CardType.LAND);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import java.io.Serializable;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public class GameView implements Serializable {
|
||||
|
||||
|
|
@ -91,12 +91,12 @@ public class GameView implements Serializable {
|
|||
if (object != null) {
|
||||
if (object instanceof Permanent) {
|
||||
boolean controlled = ((Permanent) object).getControllerId().equals(createdForPlayerId);
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, object.getName(), new CardView(((Permanent) object), game, controlled, false, false)));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, object.getName(), object, new CardView(((Permanent) object), game, controlled, false, false)));
|
||||
} else {
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, card.getName(), new CardView(card, game, false, false, false)));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, card.getName(), card, new CardView(card, game, false, false, false)));
|
||||
}
|
||||
} else {
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, "", new CardView(card, game)));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, "", card, new CardView(card, game)));
|
||||
}
|
||||
if (card.isTransformable()) {
|
||||
updateLatestCardView(game, card, stackObject.getId());
|
||||
|
|
@ -105,7 +105,7 @@ public class GameView implements Serializable {
|
|||
} else if (object != null) {
|
||||
if (object instanceof PermanentToken) {
|
||||
PermanentToken token = (PermanentToken) object;
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, token.getName(), new CardView(token, game)));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, token.getName(), token, new CardView(token, game)));
|
||||
checkPaid(stackObject.getId(), (StackAbility) stackObject);
|
||||
} else if (object instanceof Emblem) {
|
||||
CardView cardView = new CardView(new EmblemView((Emblem) object));
|
||||
|
|
@ -113,24 +113,24 @@ public class GameView implements Serializable {
|
|||
stackObject.setName(object.getName());
|
||||
// ((StackAbility) stackObject).setExpansionSetCode(sourceCard.getExpansionSetCode());
|
||||
stack.put(stackObject.getId(),
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView));
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), object, cardView));
|
||||
checkPaid(stackObject.getId(), ((StackAbility) stackObject));
|
||||
} else if (object instanceof Dungeon) {
|
||||
CardView cardView = new CardView(new DungeonView((Dungeon) object));
|
||||
stackObject.setName(object.getName());
|
||||
stack.put(stackObject.getId(),
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView));
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), object, cardView));
|
||||
checkPaid(stackObject.getId(), ((StackAbility) stackObject));
|
||||
} else if (object instanceof Plane) {
|
||||
CardView cardView = new CardView(new PlaneView((Plane) object));
|
||||
stackObject.setName(object.getName());
|
||||
stack.put(stackObject.getId(),
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView));
|
||||
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), object, cardView));
|
||||
checkPaid(stackObject.getId(), ((StackAbility) stackObject));
|
||||
} else if (object instanceof Designation) {
|
||||
Designation designation = (Designation) game.getObject(object.getId());
|
||||
if (designation != null) {
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, designation.getName(), new CardView(designation, game)));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, designation.getName(), designation, new CardView(designation, game)));
|
||||
} else {
|
||||
LOGGER.fatal("Designation object not found: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ public class StackAbilityView extends CardView {
|
|||
// selectable, chooseable, card icons etc. Search by getSourceCard
|
||||
private final CardView sourceCard;
|
||||
|
||||
public StackAbilityView(Game game, StackAbility ability, String sourceName, CardView sourceCard) {
|
||||
public StackAbilityView(Game game, StackAbility ability, String sourceName, MageObject sourceObject, CardView sourceView) {
|
||||
this.id = ability.getId();
|
||||
this.mageObjectType = MageObjectType.ABILITY_STACK;
|
||||
this.abilityType = ability.getStackAbility().getAbilityType();
|
||||
this.sourceCard = sourceCard;
|
||||
this.sourceCard = sourceView;
|
||||
this.sourceCard.setMageObjectType(mageObjectType);
|
||||
this.name = "Ability";
|
||||
this.loyalty = "";
|
||||
|
|
@ -79,12 +79,7 @@ public class StackAbilityView extends CardView {
|
|||
|
||||
updateTargets(game, ability);
|
||||
|
||||
// card icons (warning, it must be synced in gui dialogs with replaced card, see comments at the start of the file)
|
||||
// cost x
|
||||
if (ability.getManaCostsToPay().containsX()) {
|
||||
int costX = ManacostVariableValue.END_GAME.calculate(game, ability, null);
|
||||
this.cardIcons.add(CardIconImpl.variableCost(costX));
|
||||
}
|
||||
this.generateCardIcons(ability, sourceObject, game);
|
||||
}
|
||||
|
||||
private void updateTargets(Game game, StackAbility ability) {
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ public final class Main {
|
|||
try {
|
||||
MageServer testServer = (MageServer) TransporterClient.createTransporterClient(serverLocator.getLocatorURI(), MageServer.class, metadata);
|
||||
if (testServer != null) {
|
||||
testServer.getServerState();
|
||||
testServer.getServerState(); // check connection
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||
public class UserManagerImpl implements UserManager {
|
||||
|
||||
// timeouts on user's activity (on connection problems)
|
||||
private static final int USER_CONNECTION_TIMEOUTS_CHECK_SECS = 30; // TODO: replace to 60 before merge
|
||||
private static final int USER_CONNECTION_TIMEOUTS_CHECK_SECS = 30;
|
||||
private static final int USER_CONNECTION_TIMEOUT_INFORM_AFTER_SECS = 30; // inform user's opponents about problem
|
||||
private static final int USER_CONNECTION_TIMEOUT_SESSION_EXPIRE_AFTER_SECS = 3 * 60; // session expire - remove from all tables and chats (can't reconnect after it)
|
||||
private static final int USER_CONNECTION_TIMEOUT_REMOVE_FROM_SERVER_SECS = 8 * 60; // removes from users list
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public enum CardIconType {
|
|||
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
OTHER_HAS_RESTRICTIONS("prepared/exclamation-triangle-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
OTHER_HAS_TARGETS("prepared/square-fill.svg", CardIconCategory.COMMANDER, 100),
|
||||
//
|
||||
RINGBEARER("prepared/ring.svg", CardIconCategory.COMMANDER, 100),
|
||||
COMMANDER("prepared/crown.svg", CardIconCategory.COMMANDER, 100), // TODO: fix big size, see CardIconsPanel
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue